Using Html and Javascript in Flutter - javascript

I am using peerJS for screen sharing feature and flutter for web app, I'm able to call javascript functions in flutter but not able to pass values from Javascript and Flutter and make them listen in flutter.
this is my script.js:
const PRE = "Devcom"
const SUF = "Community"
var room_id;
var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
var local_stream;
var screenStream;
var peer = null;
var currentPeer = null
var screenSharing = false
function createRoom() {
console.log("Creating Room")
let room = document.getElementById("room-input").value;
if (room == " " || room == "") {
alert("Please enter room number")
return;
}
room_id = PRE + room + SUF;
peer = new Peer(room_id)
peer.on('open', (id) => {
console.log("Peer Connected with ID: ", id)
hideModal()
getUserMedia({ video: true, audio: true }, (stream) => {
local_stream = stream;
setLocalStream(local_stream)
}, (err) => {
console.log(err)
})
notify("Waiting for peer to join.")
})
peer.on('call', (call) => {
call.answer(local_stream);
call.on('stream', (stream) => {
setRemoteStream(stream)
})
currentPeer = call;
})
}
function setLocalStream(stream) {
let video = document.getElementById("local-video");
video.srcObject = stream;
video.muted = true;
video.play();
}
function setRemoteStream(stream) {
let video = document.getElementById("remote-video");
video.srcObject = stream;
video.play();
}
function hideModal() {
document.getElementById("entry-modal").hidden = true
}
function notify(msg) {
let notification = document.getElementById("notification")
notification.innerHTML = msg
notification.hidden = false
setTimeout(() => {
notification.hidden = true;
}, 3000)
}
function joinRoom() {
console.log("Joining Room")
let room = document.getElementById("room-input").value;
if (room == " " || room == "") {
alert("Please enter room number")
return;
}
room_id = PRE + room + SUF;
hideModal()
peer = new Peer()
peer.on('open', (id) => {
console.log("Connected with Id: " + id)
getUserMedia({ video: true, audio: true }, (stream) => {
local_stream = stream;
setLocalStream(local_stream)
notify("Joining peer")
let call = peer.call(room_id, stream)
call.on('stream', (stream) => {
setRemoteStream(stream);
})
currentPeer = call;
}, (err) => {
console.log(err)
})
})
}
function startScreenShare() {
if (screenSharing) {
stopScreenSharing()
}
navigator.mediaDevices.getDisplayMedia({ video: true }).then((stream) => {
screenStream = stream;
let videoTrack = screenStream.getVideoTracks()[0];
videoTrack.onended = () => {
stopScreenSharing()
}
if (peer) {
let sender = currentPeer.peerConnection.getSenders().find(function (s) {
return s.track.kind == videoTrack.kind;
})
sender.replaceTrack(videoTrack)
screenSharing = true
}
console.log(screenStream)
})
}
function stopScreenSharing() {
if (!screenSharing) return;
let videoTrack = local_stream.getVideoTracks()[0];
if (peer) {
let sender = currentPeer.peerConnection.getSenders().find(function (s) {
return s.track.kind == videoTrack.kind;
})
sender.replaceTrack(videoTrack)
}
screenStream.getTracks().forEach(function (track) {
track.stop();
});
screenSharing = false
}
function alertMessage(text) {
alert(text)
}
window.logger = (flutter_value) => {
console.log({ js_context: this, flutter_value });
}
window.state = {
hello: 'world'
}
I am able to call these javascript functions in my flutter app using:
import 'dart:js' as js;
js.context.callMethod('alertMessage', ['Flutter is calling upon JavaScript!']);
I have webRTC.html file below which works fine with my js file attached above:
<html>
<head>
<title>DEVCOM - Rooms</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<h1 class="title">Devcom</h1>
<p id="notification" hidden></p>
<div class="entry-modal" id="entry-modal">
<p>Create or Join Meeting</p>
<input id="room-input" class="room-input" placeholder="Enter Room ID">
<div>
<button onclick="createRoom()">Create Room</button>
<button onclick="joinRoom()">Join Room</button>
</div>
</div>
<div class="meet-area">
<!-- Remote Video Element-->
<video id="remote-video"></video>
<!-- Local Video Element-->
<video id="local-video"></video>
<div class="meet-controls-bar">
<button onclick="startScreenShare()">Screen Share</button>
</div>
</div>
</body>
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<script src="script.js"></script>
</html>
but the problem which I am facing is how can I make a flutter widget listen to javascript like instead of using document.getElementById("room-input").value I want to make javascript listen to flutter widgets and variables rather than html id, values...
or Is there any other way which can make html rendering in flutter web I tried webview_flutter, easy_web_view, flutter_html but nothing worked for me as I want to use it in windows chrome (web) few of earlier mentioned plugins are rather legacy and other are only for android and ios

Related

Blurry close-up shots with rear camera on iPhone 14 Pro on web

I'm currently working on web development and using the camera on my device. I've noticed that the rear camera on my iPhone 14 Pro doesn't automatically focus properly when taking close-up shots, especially when using it on the web. Here are some actual screenshots I took while testing with my iPhone 14 Pro:
For comparison, here are the results of using the same code on an iPhone 12:
I was wondering if anyone has dealt with a similar issue. I haven't been able to find any relevant solutions online, but I have seen some people resolving this issue on other web applications, so I'm hoping there might be a way to fix this.
Here's the source code I used for testing:
<body>
<div id="contentainer">
<div class="title">get divce camera and show video</div>
<div class="video-button">
<button id="start">start</button>
<button id="stop">stop</button>
</div>
<video id="video" width="640" height="480" autoplay></video>
<select class="midia-list-select"></select>
</div>
<script>
const constraints = {
video: true,
};
function inferFacingModeFromLabel(label) {
if (label.toLowerCase().includes("back")) {
return "environment";
} else if (label.toLowerCase().includes("front")) {
return "user";
} else {
return "environment";
}
}
function inferFacingModeFromCapabilities(capabilities) {
if ((capabilities?.facingMode?.indexOf("user") ?? -1) >= 0) {
return "front";
} else if (
(capabilities?.facingMode?.indexOf("environment") ?? -1) >= 0
) {
return "back";
} else {
return undefined;
}
}
function midiaOnSelect() {
const midiaList = document.querySelector(".midia-list-select");
const midiaId = midiaList.value;
navigator.mediaDevices
.getUserMedia({
video: {
deviceId: {
exact: midiaId,
},
},
})
.then((stream) => {
console.log(stream);
const video = document.getElementById("video");
video.srcObject = stream;
});
}
function getMidiaVideoList() {
function createMidiaOption(device, facingMode) {
const option = document.createElement("option");
option.value = device.deviceId;
option.text = `${facingMode.facingModeFromapabilities}|${facingMode.facingModeFromLabel}------${device.label}`;
return option;
}
navigator.mediaDevices.enumerateDevices().then(async (devices) => {
console.log("divices", devices);
devices.forEach((device) => {
console.log("divice", device);
if (device.kind === "videoinput") {
navigator.mediaDevices
.getUserMedia({
video: {
deviceId: {
exact: device.deviceId,
},
},
})
.then((stream) => {
const track = stream.getVideoTracks()?.[0];
const capabilities = (
track?.getCapabilities ?? (() => undefined)
).bind(track)();
console.log(capabilities);
const midiaList =
document.querySelector(".midia-list-select");
const facingModeFromLabel = inferFacingModeFromLabel(
device?.label
);
const facingModeFromapabilities =
inferFacingModeFromCapabilities(capabilities);
midiaList.appendChild(
createMidiaOption(device, {
facingModeFromapabilities,
facingModeFromLabel,
})
);
});
}
});
});
}
window.onload = async function () {
const start = document.getElementById("start");
const stop = document.getElementById("stop");
const midiaList = document.querySelector(".midia-list-select");
start.addEventListener("click", () => {
midiaOnSelect();
video.play();
});
stop.addEventListener("click", () => {
video.pause();
});
midiaList.addEventListener("change", midiaOnSelect);
const video = document.getElementById("video");
const media = await navigator.mediaDevices.getUserMedia({
video: true,
});
media.getTracks().forEach(function (track) {
track.stop();
});
getMidiaVideoList();
};
</script>
</body>
Thank you all in advance for your answers and suggestions. I appreciate your help!

Raspberry PI WebRTC Video Stream via USB Camera on Chromium freezing & blacking out

I have a Raspberry Pi running a Node express server with webRTC. The Raspberry Pi is connected to a web cam. I'm able to view the index.html page and see the video stream, but then it randomly freezes or black out completely. I've tried researching the issue but most solutions refer to changing settings on components that are not part of what I'm using. Help is sincerely appreciated as I've been banging my head for the past few days.
index.html
<!DOCTYPE html>
<html>
<head>
<title>Stream</title>
<meta charset="UTF-8" />
<link href="/styles.css" rel="stylesheet" />
</head>
<body>
<video playsinline autoplay muted></video>
<button id="enable-audio">Enable audio</button>
<script src="/socket.io/socket.io.js"></script>
<script src="/watch.js"></script>
</body>
</html>
broadcast.js
// wip 21 January 2022
const peerConnections = {};
const config = {
iceServers: [
{
"urls": "stun:stun.l.google.com:19302",
},
// {
// "urls": "turn:TURN_IP?transport=tcp",
// "username": "TURN_USERNAME",
// "credential": "TURN_CREDENTIALS"
// }
]
};
const socket = io.connect(window.location.origin);
socket.on("answer", (id, description) => {
peerConnections[id].setRemoteDescription(description);
});
socket.on("watcher", id => {
const peerConnection = new RTCPeerConnection(config);
peerConnections[id] = peerConnection;
let stream = videoElement.srcObject;
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
peerConnection.onicecandidate = event => {
if (event.candidate) {
socket.emit("candidate", id, event.candidate);
}
};
peerConnection
.createOffer()
.then(sdp => peerConnection.setLocalDescription(sdp))
.then(() => {
socket.emit("offer", id, peerConnection.localDescription);
});
});
socket.on("candidate", (id, candidate) => {
peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate));
});
socket.on("disconnectPeer", id => {
peerConnections[id].close();
delete peerConnections[id];
});
window.onunload = window.onbeforeunload = () => {
socket.close();
};
// Get camera and microphone
const videoElement = document.querySelector("video");
const audioSelect = document.querySelector("select#audioSource");
const videoSelect = document.querySelector("select#videoSource");
audioSelect.onchange = getStream;
videoSelect.onchange = getStream;
getStream()
.then(getDevices)
.then(gotDevices);
function getDevices() {
return navigator.mediaDevices.enumerateDevices();
}
function gotDevices(deviceInfos) {
window.deviceInfos = deviceInfos;
for (const deviceInfo of deviceInfos) {
const option = document.createElement("option");
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === "audioinput") {
option.text = deviceInfo.label || `Microphone ${audioSelect.length + 1}`;
audioSelect.appendChild(option);
} else if (deviceInfo.kind === "videoinput") {
option.text = deviceInfo.label || `Camera ${videoSelect.length + 1}`;
videoSelect.appendChild(option);
}
}
}
function getStream() {
if (window.stream) {
window.stream.getTracks().forEach(track => {
track.stop();
});
}
const audioSource = audioSelect.value;
const videoSource = videoSelect.value;
const constraints = {
audio: { deviceId: audioSource ? { exact: audioSource } : undefined },
video: { deviceId: videoSource ? { exact: videoSource } : undefined }
};
return navigator.mediaDevices
.getUserMedia(constraints)
.then(gotStream)
.catch(handleError);
}
function gotStream(stream) {
window.stream = stream;
audioSelect.selectedIndex = [...audioSelect.options].findIndex(
option => option.text === stream.getAudioTracks()[0].label
);
videoSelect.selectedIndex = [...videoSelect.options].findIndex(
option => option.text === stream.getVideoTracks()[0].label
);
videoElement.srcObject = stream;
socket.emit("broadcaster");
}
function handleError(error) {
console.error("Error: ", error);
}
watch.js
let peerConnection;
const config = {
iceServers: [
{
"urls": "stun:stun.l.google.com:19302",
},
// {
// "urls": "turn:TURN_IP?transport=tcp",
// "username": "TURN_USERNAME",
// "credential": "TURN_CREDENTIALS"
// }
]
};
const socket = io.connect(window.location.origin);
const video = document.querySelector("video");
const enableAudioButton = document.querySelector("#enable-audio");
enableAudioButton.addEventListener("click", enableAudio)
socket.on("offer", (id, description) => {
peerConnection = new RTCPeerConnection(config);
peerConnection
.setRemoteDescription(description)
.then(() => peerConnection.createAnswer())
.then(sdp => peerConnection.setLocalDescription(sdp))
.then(() => {
socket.emit("answer", id, peerConnection.localDescription);
});
peerConnection.ontrack = event => {
video.srcObject = event.streams[0];
};
peerConnection.onicecandidate = event => {
if (event.candidate) {
socket.emit("candidate", id, event.candidate);
}
};
});
socket.on("candidate", (id, candidate) => {
peerConnection
.addIceCandidate(new RTCIceCandidate(candidate))
.catch(e => console.error(e));
});
socket.on("connect", () => {
socket.emit("watcher");
});
socket.on("broadcaster", () => {
socket.emit("watcher");
});
window.onunload = window.onbeforeunload = () => {
socket.close();
peerConnection.close();
};
function enableAudio() {
console.log("Enabling audio")
video.muted = false;
}

how to correctly use getDisplayMedia on peer js?

hello recently I've been creating a video system called that is working super well here the code I'm using: Html
<html>
<head>
<title>Delta Meet</title>
</head>
<body>
<h1 class="title">Delta Meet</h1>
<p id="notification" hidden></p>
<div class="entry-modal" id="entry-modal">
<p>Create or Join Meeting</p>
<input id="room-input" class="room-input" placeholder="Enter Room ID">
<div>
<button onclick="createRoom()">Create Room</button>
<button onclick="joinRoom()">Join Room</button>
</div>
</div>
<div class="meet-area">
<!-- Remote Video Element-->
<video id="remote-video"></video>
<!-- Local Video Element-->
<video id="local-video"></video>
</div>
<br><br><br>
</body>
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<script src="script.js"></script>
</html>
and here the js:
const PRE = "DELTA"
const SUF = "MEET"
var room_id;
var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
var local_stream;
function createRoom(){
console.log("Creating Room")
let room = document.getElementById("room-input").value;
if(room == " " || room == "") {
alert("Please enter room number")
return;
}
room_id = PRE+room+SUF;
let peer = new Peer(room_id)
peer.on('open', (id)=>{
console.log("Peer Connected with ID: ", id)
hideModal()
getUserMedia({video: true, audio: true}, (stream)=>{
local_stream = stream;
setLocalStream(local_stream)
},(err)=>{
console.log(err)
})
notify("Waiting for peer to join.")
})
peer.on('call',(call)=>{
call.answer(local_stream);
call.on('stream',(stream)=>{
setRemoteStream(stream)
})
})
}
function setLocalStream(stream){
let video = document.getElementById("local-video");
video.srcObject = stream;
video.muted = true;
video.play();
}
function setRemoteStream(stream){
let video = document.getElementById("remote-video");
video.srcObject = stream;
video.play();
}
function hideModal(){
document.getElementById("entry-modal").hidden = true
}
function notify(msg){
let notification = document.getElementById("notification")
notification.innerHTML = msg
notification.hidden = false
setTimeout(()=>{
notification.hidden = true;
}, 3000)
}
function joinRoom(){
console.log("Joining Room")
let room = document.getElementById("room-input").value;
if(room == " " || room == "") {
alert("Please enter room number")
return;
}
room_id = PRE+room+SUF;
hideModal()
let peer = new Peer()
peer.on('open', (id)=>{
console.log("Connected with Id: "+id)
getUserMedia({video: true, audio: true}, (stream)=>{
local_stream = stream;
setLocalStream(local_stream)
notify("Joining peer")
let call = peer.call(room_id, stream)
call.on('stream', (stream)=>{
setRemoteStream(stream);
})
}, (err)=>{
console.log(err)
})
})
}
so far so good, so I decided to create a button for the user to be able to share the screen:
<button id="start">Start Capture</button> <button id="stop">Stop Capture</button>
then I went there and created a script:
async function startCapture() {
try {
videoElem.srcObject = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
dumpOptionsInfo();
} catch(err) {
console.error("Error: " + err);
}
}
function stopCapture(evt) {
let tracks = videoElem.srcObject.getTracks();
tracks.forEach(track => track.stop());
videoElem.srcObject = null;
}
function dumpOptionsInfo() {
const videoTrack = videoElem.srcObject.getVideoTracks()[0];
console.info("Track settings:");
console.info(JSON.stringify(videoTrack.getSettings(), null, 2));
console.info("Track constraints:");
console.info(JSON.stringify(videoTrack.getConstraints(), null, 2));
}const videoElem = document.getElementById("local-video");
const logElem = document.getElementById("log");
const startElem = document.getElementById("start");
const stopElem = document.getElementById("stop");
// Options for getDisplayMedia()
var displayMediaOptions = {
video: {
cursor: "always"
},
audio: false
};
// Set event listeners for the start and stop buttons
startElem.addEventListener("click", function(evt) {
startCapture();
}, false);
stopElem.addEventListener("click", function(evt) {
stopCapture();
}, false);
it works just right for me because for the other user it doesn't appear at all. What did I do wrong?

twilio video call JS/.Net MVC

I am implementing twilio video call feature using Javascript & MVC .net. When I execute the project Web browser asks for the camera and Microphone permissions but it does not show camera.
I can't find any related stuff in the documentation.
https://media.twiliocdn.com/sdk/js/video/releases/1.14.0/docs/index.html
If anyone can identify the mistake here that would be great. Thanks
Index.cshtml
#model twilioTest.Models.twilioVideoCall
#{
ViewBag.Title = "Index";
}
#{
ViewBag.Title = "Home Page";
}
<div class="jumbotron">
<p>test</p>
<div id="myCall"></div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jquery")
<script src="//media.twiliocdn.com/sdk/js/video/releases/2.7.0/twilio-video.min.js"></script>
<script>
const Video = Twilio.Video;
Video.connect('#Model.twilioToken', { name: '#Model.room.UniqueName' }).then(room => {
// debugger;
console.log('Connected to Room "%s"', room.name);
console.log('room.participants "%s"', JSON.stringify(room.localParticipant));
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
room.once('disconnected', error => room.participants.forEach(participantDisconnected));
});
function participantConnected(participant) {
// debugger;
console.log('test')
console.log('Participant "%s" connected', participant.identity);
const div = document.createElement('div');
div.id = participant.sid;
div.innerText = participant.identity;
participant.on('trackSubscribed', track => trackSubscribed(div, track));
participant.on('trackUnsubscribed', trackUnsubscribed);
participant.tracks.forEach(publication => {
if (publication.isSubscribed) {
trackSubscribed(div, publication.track);
}
});
$("#myCall").html(div);
// document.body.appendChild(div);
}
function participantDisconnected(participant) {
// debugger;
console.log('Participant "%s" disconnected', participant.identity);
document.getElementById(participant.sid).remove();
}
function trackSubscribed(div, track) {
// debugger;
div.appendChild(track.attach());
}
function trackUnsubscribed(track) {
// debugger;
track.detach().forEach(element => element.remove());
}
</script>
}
HomeController.cs
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Video.V1.Room;
using Twilio.Base;
using Twilio.Rest.Video.V1;
using Twilio.Jwt.AccessToken;
using System.Web.Mvc;
using twilioTest.Models;
namespace twilioTest.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
const string accountSid = "XXXXXXXXXX";
const string authToken = "XXXXXXXXXX";
var apiKeySid = "XXXXXXXXXX";
var apiKeySecret = "XXXXXXXXXX";
var identity = "test";
string roomName = "TESTROOM";
TwilioClient.Init(accountSid, authToken);
//create a Room
var room = RoomResource.Create(uniqueName: roomName);
//access token
var grant = new VideoGrant(); // Create a video grant for the token
grant.Room = roomName;
var grants = new HashSet<IGrant> { grant };
// Create an Access Token generator
var token = new Token(accountSid, apiKeySid, apiKeySecret, identity: identity, grants: grants);
// Serialize the token as a JWT
twilioVideoCall modelTwVidCall = new twilioVideoCall();
modelTwVidCall.room = room;
modelTwVidCall.twilioToken = token.ToJwt().ToString();
return View(modelTwVidCall);
}
}
}
#{
ViewBag.Title = null;
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Twilio Video Serverless Demo</title>
</head>
<body>
<div id="room-controls">
<video id="video" autoplay muted="true" width="320"
height="240"></video>
<button id="button-join">Join Room</button>
<button id="button-leave" disabled>Leave Room</button>
<input type="text" id="txtMobile" />
</div>
<script src="//media.twiliocdn.com/sdk/js/video/releases/2.3.0/twilio-video.min.js"></script>
</body>
</html>
#Scripts.Render("~/bundles/jquery")
<script src="//media.twiliocdn.com/sdk/js/video/releases/2.7.0/twilio-video.min.js"></script>
<script>
(() => {
'use strict';
const TWILIO_DOMAIN = location.host; //unique to user, will be website to visit for video app
const ROOM_NAME = 'Room_999';
const token = "";
const Video = Twilio.Video;
let videoRoom, localStream;
const video = document.getElementById("video");
$(document).ready(function () {
//var ExpertPhone = $("#ExpertPhone").val("MobileNo");
//$.post("/ExpertDashboard/Generate", { mobileNo: "MobileNo" }, function (data) {
// token = data.token;
//});
});
// preview screen
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(vid => {
video.srcObject = vid;
localStream = vid;
})
// buttons
const joinRoomButton = document.getElementById("button-join");
const leaveRoomButton = document.getElementById("button-leave");
var site = 'https://${TWILIO_DOMAIN}/video-token';
console.log('site ${site}');
joinRoomButton.onclick = () => {
// get access token
var txtMobile = $("#txtMobile").val();
$.post("/ExpertDashboard/Generate", { mobileNo: txtMobile }, function (data) {
const token = data.token;
console.log(token);
//connect to room
Video.connect(token, { name: ROOM_NAME }).then((room) => {
console.log('Connected to Room ${room.name}');
videoRoom = room;
room.participants.forEach(participantConnected);
room.on("participantConnected", participantConnected);
room.on("participantDisconnected", participantDisconnected);
room.once("disconnected", (error) =>
room.participants.forEach(participantDisconnected)
);
joinRoomButton.disabled = true;
leaveRoomButton.disabled = false;
});
});
};
// leave room
leaveRoomButton.onclick = () => {
videoRoom.disconnect();
console.log('Disconnected from Room ${videoRoom.name}');
joinRoomButton.disabled = false;
leaveRoomButton.disabled = true;
};
})();
// connect participant
const participantConnected = (participant) => {
console.log('Participant ${participant.identity} connected');
const div = document.createElement('div'); //create div for new participant
div.id = participant.sid;
participant.on('trackSubscribed', track => trackSubscribed(div, track));
participant.on('trackUnsubscribed', trackUnsubscribed);
participant.tracks.forEach(publication => {
if (publication.isSubscribed) {
trackSubscribed(div, publication.track);
}
});
document.body.appendChild(div);
}
const participantDisconnected = (participant) => {
console.log('Participant ${participant.identity} disconnected.');
document.getElementById(participant.sid).remove();
}
const trackSubscribed = (div, track) => {
div.appendChild(track.attach());
}
const trackUnsubscribed = (track) => {
track.detach().forEach(element => element.remove());
}
</script>

Error simple WebRTC chat on react.js and meteor.js

I'm trying to make a simple chat using webrtc technology, react.js and meteor.js.
This is client code:
class Rtc extends Component {
constructor(props) {
super(props);
}
componentDidUpdate(){
let localVideo, remoteVideo, peerConnection, localStream;
$('#start').on('click', ()=>{ start(true) });
let id = Meteor.uuid();
localVideo = document.getElementById('localVideo');
remoteVideo = document.getElementById('remoteVideo');
if (!this.props.loadingRtc) {
this.props.messagesRtc.forEach((item, i ,arr)=>{
let signal = JSON.parse(item.text);
if(i == 0)return;
gotMessageFromServer(signal);
});
}
if(navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia( { video:true, audio:true}).then( ( stream )=> {
localStream = stream;
localVideo.src = window.URL.createObjectURL(stream);
}).catch(errorHandler);
} else { alert('Your browser does not support getUserMedia API'); }
function start(isCaller) {
peerConnection = new RTCPeerConnection( { 'iceServers': [{'urls': 'stun:stun.services.mozilla.com'}, {'urls': 'stun:stun.l.google.com:19302'},]});
peerConnection.onicecandidate = ( e ) => {
console.log('e.candidate', e.candidate);
if(e.candidate != null) {
Meteor.call('addMsgRtc', JSON.stringify({'ice': e.candidate, '_id':id}), id);
}
};
peerConnection.onaddstream = ( e )=>{
remoteVideo.src = window.URL.createObjectURL(e.stream);
};
peerConnection.addStream(localStream);
if(isCaller) {
peerConnection.createOffer().then(createdDescription).catch(errorHandler);
}
}
function gotMessageFromServer(signal) {
if(!peerConnection) start(false);
if(signal._id == id) return;
if(signal.sdp) {
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp)).then(()=> {
if(signal.sdp.type == 'offer') {
peerConnection.createAnswer().then(createdDescription).catch(errorHandler);
}
}).catch(errorHandler);
} else if(signal.ice) {
peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice)).catch(errorHandler);
}
}
function createdDescription(description) {
peerConnection.setLocalDescription(description).then(()=> {
Meteor.call('addMsgRtc', JSON.stringify({'sdp':peerConnection.localDescription, '_id':id}), id);
}).catch(errorHandler);
}
function errorHandler(error) { console.log(error); }
}
render() {
return (
<div>
<video id="localVideo" autoPlay muted style={{width:"40%"}}></video>
<video id="remoteVideo" autoPlay style={{width:"40%"}}></video>
<br/>
<input type="button" id="start" value="Start Video"/>
</div>
);
}
}
export default createContainer( ()=> {
const subscriptionRtc = Meteor.subscribe('rtc');
const loadingRtc = !subscriptionRtc.ready();
return {
loadingRtc:loadingRtc,
messagesRtc: msgRtc.find().fetch(),
};
}, App);
Server code:
export const msgRtc = new Mongo.Collection('rtc');
let messagesRtc = [];
let clients = [];
Meteor.publish('rtc', function wsPub() {
clients.push(this);
_.each(messagesRtc, (message) => {
this.added('rtc', message._id, message);
});
this.ready();
});
Meteor.methods({
'addMsgRtc'(arr, id) {
let newMessage = {_id:id, 'text':arr};
messagesRtc.push(newMessage);
_.each(clients, (client) => {
client.added('rtc', id, newMessage);
});
},
The problem is that why after the initialization of getUserMedia does not want to further this videos and what not so I can't understand. Because it is actually a similar code with the usual websockets like this works and syncs fine.
UPD:
When you click on the button and call the function start.
TypeError: Argument 1 of RTCPeerConnection.addStream is not an object
If websockets to put in then then it turns out another error:
Code:
navigator.mediaDevices.getUserMedia( { video:true, audio:true}).then( ( stream )=> {
localStream = stream;
localVideo.src = window.URL.createObjectURL(stream);
}).catch(errorHandler).then(()=>{
if (!this.props.loadingRtc) {
for(let i of this.props.messagesRtc){
let signal = JSON.parse(i.text);
gotMessageFromServer(signal)
}
}
}).catch(errorHandler);
Error:
DOMException [InvalidStateError: "Cannot set remote offer or answer in
current state have-remote-offer" code: 11 nsresult: 0x8053000b]
app.js:11075:9 DOMException [InvalidStateError: "No outstanding offer"
code: 11 nsresult: 0x8053000b]

Categories