I'm trying to keep Mute Button that will act like Push to talk
This App.js file (main file)
navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
//get browser cmopt
var me = {};
var myStream;
var peers = {};
init();
function init() {
if (!navigator.getUserMedia) return unsupported();
getLocalAudioStream(function(err, stream) {
if (err || !stream) return;
connectToPeerJS(function(err) {
if (err) return;
registerIdWithServer(me.id);
if (call.peers.length) callPeers();
else displayShareMessage();
});
});
} // initialization
function connectToPeerJS(cb) {
display('Connecting to PeerJS...');
//me = new Peer({key: API_KEY});
me = new Peer({ host:'rapidserver.herokuapp.com', secure:true, port:443, key: 'peerjs', debug: 3})
me.on('call', handleIncomingCall);
me.on('open', function() {
display('Connected.');
display('ID: ' + me.id);
cb && cb(null, me);
});// connect to peerJs Server and get ID From the Server
me.on('error', function(err) {
display(err);
cb && cb(err);
});
}
function registerIdWithServer() {
display('Registering ID with server...');
$.post('/' + call.id + '/addpeer/' + me.id);
} // Add our ID to the list of PeerJS IDs for this call
function unregisterIdWithServer() {
$.post('/' + call.id + '/removepeer/' + me.id);
}
function callPeers() {
call.peers.forEach(callPeer);
}
function callPeer(peerId) {
display('Calling ' + peerId + '...');
var peer = getPeer(peerId);
peer.outgoing = me.call(peerId, myStream);
peer.outgoing.on('error', function(err) {
display(err);
});
peer.outgoing.on('stream', function(stream) {
display('Connected to ' + peerId + '.');
addIncomingStream(peer, stream);
});
}
function handleIncomingCall(incoming) {
display('Answering incoming call from ' + incoming.peer);
var peer = getPeer(incoming.peer);
peer.incoming = incoming;
incoming.answer(myStream);
peer.incoming.on('stream', function(stream) {
addIncomingStream(peer, stream);
});
}// When someone initiates a call via PeerJS
// Add the new audio stream. Either from an incoming call, or from the response to one of our outgoing calls
function addIncomingStream(peer, stream) {
display('Adding incoming stream from .... ' + peer.id);
peer.incomingStream = stream;
playStream(stream);
}
function playStream(stream) {
var audio = $('<audio autoplay />').appendTo('body');
audio[0].src = (URL || webkitURL || mozURL).createObjectURL(stream);
}
function getLocalAudioStream(cb) {
display('Trying to access your microphone. Please click "Allow".');
navigator.getUserMedia (
{video: false, audio: true},
function success(audioStream) {
display('Microphone is open.');
myStream = audioStream;
if (cb) cb(null, myStream);
},
function error(err) {
display('Couldn\'t connect to microphone. Reload the page to try again.');
if (cb) cb(err);
}
);
}
function getPeer(peerId) {
return peers[peerId] || (peers[peerId] = {id: peerId});
}
function displayShareMessage() {
display('Give someone this URL to chat.');
display('<input type="text" value="' + location.href + '" readonly>');
$('#display input').click(function() {
this.select();
});
}
function unsupported() {
display("Your browser doesn't support getUserMedia.");
}
function display(message) {
$('<div />').html(message).appendTo('#display');
}
And this is my index.ejs (html index file)
<body>
<div class="wrapper">
<div id="display"></div>
</div>
<footer>
<div class="wrapper">
~~~~~Start another call~~~~~~~
</div>
</footer>
<script type="text/javascript">
window.API_KEY = "<%= apiKey %>";
window.call = <%- JSON.stringify(call, null, 2) %>;
</script>
</script>
I'm thinking to add something like mute button or toggle button but i am not sure how do i make it happen with call and with each peer can mute and unmute the call.
Please help me. It would be great help. Thanks in Advance.
I Tried Using this.
<input type="button" name="button" id="mute"> Mute </input>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.js">
$(document).ready(function(){ function Mute() { var button = document.createElement("button"); button.appendChild(document.createTextNode("Toggle Hold"));
button.onclick = function(){ mediaStream.use getAudioTracks()()[0].enabled =!(mediaStream.use getAudioTracks()()[0].enabled);
} }
$("#mute").click(Mute);
});
Related
I'm trying to write a javascript file which will be able to cast images to a chromecast. There will be multiple buttons on an html page. Depending on the button the user clicks, a url will be sent to the chromecast. I have the names of the files stored in a JSON file called videoNames.json, which I loop over to get the names. At the moment all the files to be casted are images. When I run the code the screen remains blank and no buttons show up. Here is my code:
<!doctype html>
<html>
<head>
<title>Casting</title>
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<SCRIPT language= "Javascript">
var session = null;
$( document ).ready(function(){
var loadCastInterval = setInterval(function(){
if (chrome.cast.isAvailable) {
console.log('Cast has loaded.');
clearInterval(loadCastInterval);
initializeCastApi();
} else {
console.log('Unavailable');
}
}, 1000);
});
function initializeCastApi() {
var applicationID = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID;
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
sessionListener,
receiverListener);
chrome.cast.initialize(apiConfig, onInitSuccess, onInitError);
};
function sessionListener(e) {
session = e;
console.log('New session');
if (session.media.length != 0) {
console.log('Found ' + session.media.length + ' sessions.');
}
}
function receiverListener(e) {
if( e === 'available' ) {
console.log("Chromecast was found on the network.");
}
else {
console.log("There are no Chromecasts available.");
}
}
function onInitSuccess() {
console.log("Initialization succeeded");
}
function onInitError() {
console.log("Initialization failed");
}
function getArray(){
return $.getJSON('./videoNames.json');
}
getArray().done( function(json) {
//console.log(json); // show the json data in console
//var len = json.length;
var fixture;
//loop through json and match today's date with match-date
for (var i in json) {
fixture = json[i];
document.write(fixture.name);
var butt = document.createElement("button");
var text = document.createTextNode("Click to cast");
butt.appendChild(text);
butt.id = i;
var nameArray[i] = fixture.name;
document.body.appendChild(butt);
}
});
$(#i).click(function(nameArray[i]){
launchApp(nameArray[i]);
});
function getFileNameExtension(filename){
return filename.split('.').pop();
}
function launchApp(nameArray[i]) {
console.log("Launching the Chromecast App...");
chrome.cast.requestSession(onRequestSessionSuccess(nameArray[i]), onLaunchError);
}
function onRequestSessionSuccess(e) {
console.log("Successfully created session: " + e.sessionId);
session = e;
}
function onLaunchError() {
console.log("Error connecting to the Chromecast.");
}
function onRequestSessionSuccess(e, nameArray[i]) {
console.log("Successfully created session: " + e.sessionId);
session = e;
loadMedia(nameArray[i]);
}
function loadMedia(nameArray[i]) {
if (!session) {
console.log("No session.");
return;
}
var mediaInfo = new
chrome.cast.media.MediaInfo('http://52.60.153.189/video_files/' + nameArray[i]);
mediaInfo.contentType = 'image/' + getFileNameExtension(nameArray[i]);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.autoplay = true;
session.loadMedia(request, onLoadSuccess, onLoadError);
}
function onLoadSuccess() {
console.log('Successfully loaded image.');
}
function onLoadError() {
console.log('Failed to load image.');
}
$('#stop').click(function(){
stopApp();
});
function stopApp() {
session.stop(onStopAppSuccess, onStopAppError);
}
function onStopAppSuccess() {
console.log('Successfully stopped app.');
}
function onStopAppError() {
console.log('Error stopping app.');
}
</SCRIPT>
</body>
</html>
Any help is appreciated. Thanks!
I tried to test an exercise with WebRTC socket.io for a video call and chat .
I could not get the console errors on firefox but not attacking me the two local / remote stream between them .
my browser code is this
'use strict';
var p = navigator.mediaDevices.getUserMedia ({video: true, audio: true});
// Clean-up function:
// collect garbage before unloading browser's window
window.onbeforeunload = function(e){
hangup();
}
// Data channel information
var sendChannel, receiveChannel;
var sendButton = document.getElementById("sendButton");
var sendTextarea = document.getElementById("dataChannelSend");
var receiveTextarea = document.getElementById("dataChannelReceive");
// HTML5 <video> elements
var localVideo = document.querySelector('#localVideo');
var remoteVideo = document.querySelector('#remoteVideo');
// Handler associated with Send button
sendButton.onclick = sendData;
// Flags...
var isChannelReady = false;
var isInitiator = false;
var isStarted = false;
// WebRTC data structures
// Streams
var SStream;
var BStream;
var localStream;
var remoteStream;
// PeerConnection
var pc;
var pc_constraints = {
'optional': [
{'DtlsSrtpKeyAgreement': true}
]};
var sdpConstraints = {};
// Let's get started: prompt user for input (room name)
var room = prompt('Enter room name:');
// Connect to signaling server
var socket = io.connect("http://localhost:8181");
// Send 'Create or join' message to singnaling server
if (room !== '') {
console.log('Create or join room ', room);
socket.emit('create or join',room);
}
// Server-mediated message exchanging...
// 1. Server-->Client...
// this peer is the initiator
socket.on('created', function (room){
console.log('Created room ' + room);
isInitiator = true;
// Call getUserMedia()
p.then (function (MediaStream) {
SStream=MediaStream;
localVideo.src = window.URL.createObjectURL (MediaStream);
localVideo.onloadedmetadata = function (e) {
console.log("add local stream");
sendMessage('got user media');
};
});
p.catch (function (err) {console.log (err.name);});
checkAndStart();
});
// Handle 'join' message coming back from server:
// another peer is joining the channel
socket.on('join',function(room){
console.log('this peer is the iniator of room '+room+' !');
isChannelReady=true;
})
// Handle 'joined' message coming back from server:
// this is the second peer joining the channel
socket.on('joined', function (room){
console.log('This peer has joined room ' + room);
isChannelReady = true;
// Call getUserMedia()
p.then (function (MediaStream) {
isChannelReady = true;
BStream=MediaStream;
remoteVideo.src = window.URL.createObjectURL (MediaStream);
remoteVideo.onloadedmetadata = function (e) {
console.log("add remote stream");
sendMessage('got user media');
};
});
p.catch (function (err) {console.log (err.name);});
});
// Server-sent log message...
socket.on('log', function (array){
console.log.apply(console, array);
});
// Receive message from the other peer via the signaling server
socket.on('message', function (message){
console.log('Received message: ', message);
if (message === 'got user media') {
console.log('sono in if');
checkAndStart();
}
else if (message.type === 'offer') {
if (!isInitiator && !isStarted) {
checkAndStart();
}
pc.setRemoteDescription(new RTCSessionDescription(message));
doAnswer();
}
else if (message.type === 'answer' && isStarted) {
pc.setRemoteDescription(new RTCSessionDescription(message));
}
else if (message.type === 'candidate' && isStarted) {
var candidate = new RTCIceCandidate({sdpMLineIndex:message.label,candidate:message.candidate});
pc.addIceCandidate(candidate);
}
else if (message === 'bye' && isStarted) {
handleRemoteHangup();
}
});
// 2. Client-->Server
// Send message to the other peer via the signaling server
function sendMessage(message){
console.log('Sending message: ', message);
socket.emit('message', message);
}
// Channel negotiation trigger function
function checkAndStart() {
if (!isStarted && isChannelReady) {
createPeerConnection();
isStarted = true;
if (isInitiator) {
doCall();
}
}
}
// PeerConnection management...
function createPeerConnection() {
try {
/*posso aggiungere turn, google ecc...*/
pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:93.33.165.245' }] }, {
'optional': [
{'DtlsSrtpKeyAgreement': true}
]});
if(isInitiator){
SStream.getTracks().forEach(track => pc.addTrack(track,SStream));
pc.ontrack= handleRemoteStreamAdded;}
else{
BStream.getTracks().forEach(track => pc.addTrack(track,BStream));}
pc.onicecandidate = handleIceCandidate;
console.log('create RTCPeerConnection');
}
catch (e) {
console.log('Failed to create PeerConnection, exception: ' + e.message);
alert('Cannot create RTCPeerConnection object.');
return;
}
pc.ontrack= handleRemoteStreamAdded;
pc.onremovestream = handleRemoteStreamRemoved;
if (isInitiator) {
try {
// Create a reliable data channel
sendChannel = pc.createDataChannel("sendDataChannel",
{reliable: true});
console.log('Created send data channel');
} catch (e) {
alert('Failed to create data channel. ');
console.log('createDataChannel() failed with exception: ' + e.message);
}
sendChannel.onopen = handleSendChannelStateChange;
sendChannel.onmessage = handleMessage;
sendChannel.onclose = handleSendChannelStateChange;
} else { // Joiner
pc.ondatachannel = gotReceiveChannel;
}
}
// Data channel management
function sendData() {
var data = sendTextarea.value;
if(isInitiator) sendChannel.send(data);
else receiveChannel.send(data);
console.log('Sent data: ' + data);
}
// Handlers...
function gotReceiveChannel(event) {
console.log('Receive Channel Callback');
receiveChannel = event.channel;
receiveChannel.onmessage = handleMessage;
receiveChannel.onopen = handleReceiveChannelStateChange;
receiveChannel.onclose = handleReceiveChannelStateChange;
}
function handleMessage(event) {
console.log('Received message: ' + event.data);
receiveTextarea.value += event.data + '\n';
}
function handleSendChannelStateChange() {
var readyState = sendChannel.readyState;
console.log('Send channel state is: ' + readyState);
// If channel ready, enable user's input
if (readyState == "open") {
dataChannelSend.disabled = false;
dataChannelSend.focus();
dataChannelSend.placeholder = "";
sendButton.disabled = false;
} else {
dataChannelSend.disabled = true;
sendButton.disabled = true;
}
}
function handleReceiveChannelStateChange() {
var readyState = receiveChannel.readyState;
console.log('Receive channel state is: ' + readyState);
// If channel ready, enable user's input
if (readyState == "open") {
dataChannelSend.disabled = false;
dataChannelSend.focus();
dataChannelSend.placeholder = "";
sendButton.disabled = false;
} else {
dataChannelSend.disabled = true;
sendButton.disabled = true;
}
}
// ICE candidates management
function handleIceCandidate(event) {
console.log('handleIceCandidate event: ', event);
if (event.candidate) {
sendMessage({
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate});
} else {
console.log('End of candidates.');
}
}
// Create Offer
function doCall() {
console.log('Creating Offer...');
pc.createOffer(setLocalAndSendMessage, onSignalingError, sdpConstraints);
}
// Signaling error handler
function onSignalingError(error) {
console.log('Failed to create signaling message : ' + error.name);
}
// Create Answer
function doAnswer() {
console.log('Sending answer to peer.');
pc.createAnswer(setLocalAndSendMessage, onSignalingError, sdpConstraints);
}
// Success handler for both createOffer()
// and createAnswer()
function setLocalAndSendMessage(sessionDescription) {
pc.setLocalDescription(sessionDescription);
sendMessage(sessionDescription);
}
// Remote stream handlers...
function handleRemoteStreamAdded(event) {
attachMediaStream(BStream, event.stream);
BStream = event.stream;
}
function handleRemoteStreamRemoved(event) {
console.log('Remote stream removed. Event: ', event);
}
// Clean-up functions...
function hangup() {
console.log('Hanging up.');
stop();
sendMessage('bye');
}
function handleRemoteHangup() {
console.log('Session terminated.');
stop();
isInitiator = false;
}
function stop() {
isStarted = false;
if (sendChannel) sendChannel.close();
if (receiveChannel) receiveChannel.close();
if (pc) pc.close();
pc = null;
sendButton.disabled=true;
}
someone tell me where I'm wrong and how to fix ?
attachMediaStream is not part of WebRTC. It's a shim adapter.js used to expose for setting video.src or video.srcObject (which Chrome still doesn't support, but Canary does).
In any case, you're passing in the wrong arguments, which should be an element and a stream, not two streams. I.e. make it:
attachMediaStream(remoteVideo, event.streams[0]);
or better, use the spec-way that adapter.js now supports on all browsers:
remoteVideo.srcObject = event.streams[0];
Important: The pc.ontrack event contains event.streams (plural), not event.stream! - It's an array since a track may (but rarely does) exist in more than one stream.
If you're not using the latest adapter.js, then note that pc.ontrack is only natively available in Firefox at the moment, so in Chrome you would need the older pc.onaddstream (and its event.stream).
PS: You're currently setting remoteVideo.src to the local video. Don't do that.
PPS: Remove pc_constraints. Really old stuff that will break Chrome.
Here's a demo of ontrack (use https fiddle in Chrome):
var pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => pc1.addStream(video1.srcObject = stream))
.catch(log);
var add = (pc, can) => can && pc.addIceCandidate(can).catch(log);
pc1.onicecandidate = e => add(pc2, e.candidate);
pc2.onicecandidate = e => add(pc1, e.candidate);
pc2.ontrack = e => video2.srcObject = e.streams[0];
pc1.oniceconnectionstatechange = e => log(pc1.iceConnectionState);
pc1.onnegotiationneeded = e =>
pc1.createOffer().then(d => pc1.setLocalDescription(d))
.then(() => pc2.setRemoteDescription(pc1.localDescription))
.then(() => pc2.createAnswer()).then(d => pc2.setLocalDescription(d))
.then(() => pc1.setRemoteDescription(pc2.localDescription))
.catch(log);
var log = msg => div.innerHTML += "<br>" + msg;
<video id="video1" height="120" width="160" autoplay muted></video>
<video id="video2" height="120" width="160" autoplay></video><br>
<div id="div"></div>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
While setting the remoteDescription , I am getting below error in firefox :
DOMException [InvalidStateError: "Cannot set remote offer in state have-local-offer"
code: 11
nsresult: 0x8053000b
location: http://localhost:8080/resources/assets/js/test-online.js:111]
Please find below my test-online.js code
var localVideo;
var remoteVideo;
var peerConnection;
var serverConnection;
var peerConnectionConfig = {'iceServers': [{'url': 'stun:stun.services.mozilla.com'}, {'url': 'stun:stun.l.google.com:19302'}]};
pageReady();
var offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
var sdpConstraints = {'mandatory': {
'OfferToReceiveAudio':true,
'OfferToReceiveVideo':true }};
function pageReady() {
localVideo = document.getElementById('localVideo');
remoteVideo = document.getElementById('remoteVideo');
localVideo.addEventListener('loadedmetadata', function() {
trace('Local video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});
remoteVideo.addEventListener('loadedmetadata', function() {
trace('Remote video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});
remoteVideo.onresize = function() {
trace('Remote video size changed to ' +
remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
// We'll use the first onsize callback as an indication that video has started
// playing out.
if (startTime) {
var elapsedTime = window.performance.now() - startTime;
trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
startTime = null;
}
};
serverConnection = new SockJS("/onlineHandler");
serverConnection.onopen = function() {
console.log("Opening server connection");
};
serverConnection.onmessage = gotMessageFromServer;
serverConnection.onclose = function() {
console.log("Closing server connection");
};
//serverConnection.onmessage = gotMessageFromServer;
var constraints = {
video: true,
audio: true,
};
navigator.mediaDevices.getUserMedia(constraints)
.then(getUserMediaSuccess)
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
}
function getUserMediaSuccess(stream) {
trace('Received local stream');
localVideo.srcObject = stream;
localStream = stream;
}
function start(isCaller) {
trace('Starting call');
startTime = window.performance.now();
var videoTracks = localStream.getVideoTracks();
var audioTracks = localStream.getAudioTracks();
if (videoTracks.length > 0) {
trace('Using video device: ' + videoTracks[0].label);
}
if (audioTracks.length > 0) {
trace('Using audio device: ' + audioTracks[0].label);
}
peerConnection = new RTCPeerConnection(peerConnectionConfig);
peerConnection.onicecandidate = gotIceCandidate;
peerConnection.oniceconnectionstatechange = onIceStateChange;
peerConnection.onaddStream = gotRemoteStream;
peerConnection.addStream(localStream);
if(isCaller) {
peerConnection.createOffer(gotDescription, errorHandler , offerOptions);
}
}
function gotMessageFromServer(message) {
/* if(!peerConnection) start(false);
var signal = JSON.parse(message.data);
// console.log("Got Message from server :" + message.data);
if(signal.sdp) {;
console.log("hi in sdp" + message.data);
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp), function() {
console.log("Creating answer :");
if (peerConnection.remoteDescription.type == 'offer')
peerConnection.createAnswer(gotDescription, errorHandler);
}, errorHandler);
} else if(signal.ice) {
peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice));
}*/
var signal = JSON.parse(message.data);
if (signal.type === 'offer') {
peerConnection.setRemoteDescription(new RTCSessionDescription(signal),doAnswer,errorHandler);
} else if (signal.type === 'answer') {
peerConnection.setRemoteDescription(new RTCSessionDescription(signal),doNothing, errorHandler);
} else if (signal.type === 'candidate') {
var candidate = new RTCIceCandidate({
sdpMLineIndex:signal.label,
candidate: signal.candidate
});
peerConnection.addIceCandidate(candidate);
} else if (signal === 'bye' && isStarted) {
handleRemoteHangup();
}
}
function doNothing(){
}
function doAnswer() {
console.log('Sending answer to peer.');
peerConnection.createAnswer(gotDescription, errorHandler, sdpConstraints);
}
function handleRemoteHangup() {
// console.log('Session terminated.');
// stop();
// isInitiator = false;
}
function gotIceCandidate(event) {
if(event.candidate != null) {
var message ={
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate};
// serverConnection.send(JSON.stringify({'ice': event.candidate}));
serverConnection.send(JSON.stringify(message));
}
}
function onIceStateChange(event) {
if (peerConnection) {
trace(' ICE state: ' + peerConnection.iceConnectionState);
console.log('ICE state change event: ', event);
}
}
function gotDescription(description) {
// trace('Offer from peerConnection\n' + description.sdp);
description.sdp = preferOpus(description.sdp);
// pc.setLocalDescription(description);
console.log('setLocalAndSendMessage sending message' , description);
// trace('peerConnection setLocalDescription start');
peerConnection.setLocalDescription(
description,
function () {
serverConnection.send(JSON.stringify(description));
},
onSetSessionDescriptionError
);
}
function preferOpus(sdp) {
var sdpLines = sdp.split('\r\n');
var mLineIndex;
// Search for m line.
for (var i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('m=audio') !== -1) {
mLineIndex = i;
break;
}
}
if (mLineIndex === null) {
return sdp;
}
// If Opus is available, set it as the default in m line.
for (i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('opus/48000') !== -1) {
var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
if (opusPayload) {
sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], opusPayload);
}
break;
}
}
// Remove CN in m line and sdp.
sdpLines = removeCN(sdpLines, mLineIndex);
sdp = sdpLines.join('\r\n');
return sdp;
}
function extractSdp(sdpLine, pattern) {
var result = sdpLine.match(pattern);
return result && result.length === 2 ? result[1] : null;
}
// Set the selected codec to the first in m line.
function setDefaultCodec(mLine, payload) {
var elements = mLine.split(' ');
var newLine = [];
var index = 0;
for (var i = 0; i < elements.length; i++) {
if (index === 3) { // Format of media starts from the fourth.
newLine[index++] = payload; // Put target payload to the first.
}
if (elements[i] !== payload) {
newLine[index++] = elements[i];
}
}
return newLine.join(' ');
}
// Strip CN from sdp before CN constraints is ready.
function removeCN(sdpLines, mLineIndex) {
var mLineElements = sdpLines[mLineIndex].split(' ');
// Scan from end for the convenience of removing an item.
for (var i = sdpLines.length-1; i >= 0; i--) {
var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
if (payload) {
var cnPos = mLineElements.indexOf(payload);
if (cnPos !== -1) {
// Remove CN payload from m line.
mLineElements.splice(cnPos, 1);
}
// Remove CN line in sdp
sdpLines.splice(i, 1);
}
}
sdpLines[mLineIndex] = mLineElements.join(' ');
return sdpLines;
}
function onSetSessionDescriptionError(error) {
trace('Failed to set session description: ' + error.toString());
}
function gotRemoteStream(event) {
remoteVideo.srcObject = event.stream;
trace('Received remote stream');
}
function errorHandler(error) {
console.log(error);
}
And my html code is below :
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html lang="en">
<head>
<link
href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css"
rel="stylesheet">
<!-- Meta tag to not followed by search engine. -->
<meta name="robots" content="noindex,nofollow,nosnippet,noodp,noarchive">
<meta name="keywords" content="JavaScript, WebRTC" />
<meta name="description" content="WebRTC codelab" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1">
<style>
video {
filter: hue-rotate(180deg) saturate(200%);
-moz-filter: hue-rotate(180deg) saturate(200%);
-webkit-filter: hue-rotate(180deg) saturate(200%);
/*-webkit-filter: grayscale(0.3) hue-rotate(360deg) saturate(10) opacity(0.7) sepia(0.5); */
}
</style>
</head>
<body>
<div id='videos'>
<video id='localVideo' autoplay muted></video>
<video id='remoteVideo' autoplay></video>
</div>
<input type="button" id="start" onclick="start(true)" value="Start Video"></input>
<script src="//cdn.jsdelivr.net/sockjs/1.0.0/sockjs.min.js"></script>
<script
src="${pageContext.request.contextPath}/resources/assets/js/jquery-2.1.1.min.js"></script>
<script
src="${pageContext.request.contextPath}/resources/assets/js/bootstrap.min.js"></script>
<script src ="${pageContext.request.contextPath}/resources/assets/js/adapter-0.2.10.js"></script>
<script src="${pageContext.request.contextPath}/resources/assets/js/test-online.js"></script>
</body>
</html>
I am not able to understand what I am doing wrong here.I am still a novice in webrtc field juts want to run this basic thing in my code.
The offer-answer exchange is a state machine, and some methods are disallowed in certain states.
Calling setLocalDescription (or setRemoteDescription) changes the signaling state to "have-local-offer" (or "have-remote-offer").
At that point, it is the application's job to bring the state back to stable or closed, as described in the spec.
For instance, it is the application's responsibility to handle glare (which is where both sides send an offer at the same time).
There is also a bug in Firefox that it doesn't allow you to call createOffer or setLocalDescription again once in have-local-offer and vice versa for the answer (the little hoops in the state diagram in the spec linked above). But it doesn't sound from your error message like you're hitting that.
This code works in google chrome fine ,
but i tried to convert it to support Firefox
and i always get no error in the console .
the cam it seems ruining but there's no video.
here's the script
var socket = new WebSocket('ws://127.0.0.1:1338/'); // change the IP address to your websocket server
var stunServer = "stun.l.google.com:19302";
var sourcevid = document.getElementById('sourcevid');
var remotevid = document.getElementById('remotevid');
var localStream = null;
var remoteStream;
var peerConn = null;
var started = false;
var isRTCPeerConnection = true;
var mediaConstraints = {mandatory: {
OfferToReceiveAudio:true,
OfferToReceiveVideo:true }};
var logg = function(s) { console.log(s); };
// send the message to websocket server
function sendMessage(message) {
var mymsg = JSON.stringify(message);
logg("SEND: " + mymsg);
socket.send(mymsg);
}
function createPeerConnection() {
try {
logg("Creating peer connection");
var servers = [];
servers.push({'url':'stun:' + stunServer});
var pc_config = {'iceServers':servers};
peerConn = new webkitRTCPeerConnection(pc_config);
peerConn.onicecandidate = onIceCandidate;
} catch (e) {
try {
peerConn = new RTCPeerConnection('STUN ' + stunServer, onIceCandidate00);
isRTCPeerConnection = false;
} catch (e) {
logg("Failed to create PeerConnection, exception: " + e.message);
}
}
peerConn.onaddstream = onRemoteStreamAdded;
peerConn.onremovestream = onRemoteStreamRemoved;
}
// when remote adds a stream, hand it on to the local video element
function onRemoteStreamAdded(event) {
logg("Added remote stream");
remotevid.src = window.webkitURL.createObjectURL(event.stream);
}
function waitForRemoteVideo() {
if (remoteStream.videoTracks.length === 0 || remotevid.currentTime > 0) {
transitionToActive();
} else {
setTimeout(waitForRemoteVideo, 100);
}
}
function transitionToActive() {
remotevid.style.opacity = 1;
card.style.webkitTransform = "rotateY(180deg)";
setTimeout(function() { sourcevid.src = ""; }, 500);
setStatus("<input type=\"button\" id=\"hangup\" value=\"Hang up\" onclick=\"onHangup()\" />");
}
// when remote removes a stream, remove it from the local video element
function onRemoteStreamRemoved(event) {
logg("Remove remote stream");
remotevid.src = "";
}
function onIceCandidate(event) {
if (event.candidate) {
sendMessage({type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate});
} else {
logg("End of candidates.");
}
}
function onIceCandidate00(candidate, moreToFollow) {
if (candidate) {
sendMessage({type: 'candidate', label: candidate.label, candidate: candidate.toSdp()});
}
if (!moreToFollow) {
logg("End of candidates.");
}
}
// start the connection upon user request
function connect() {
if (!started && localStream) {
console.log("Creating PeerConnection.");
createPeerConnection();
logg('Adding local stream...');
peerConn.addStream(localStream);
started = true;
logg("isRTCPeerConnection: " + isRTCPeerConnection);
//create offer
if (isRTCPeerConnection) {
peerConn.createOffer(setLocalAndSendMessage, null, mediaConstraints);
} else {
var offer = peerConn.createOffer(mediaConstraints);
peerConn.setLocalDescription(peerConn.SDP_OFFER, offer);
sendMessage({type: 'offer', sdp: offer.toSdp()});
peerConn.startIce();
}
} else {
alert("Local stream not running yet.");
}
}
// accept connection request
socket.addEventListener("message", onMessage, false);
function onMessage(evt) {
logg("RECEIVED: " + evt.data);
if (isRTCPeerConnection)
processSignalingMessage(evt.data);
else
processSignalingMessage00(evt.data);
}
function processSignalingMessage(message) {
var msg = JSON.parse(message);
if (msg.type === 'offer') {
if (!started && localStream) {
createPeerConnection();
logg('Adding local stream...');
peerConn.addStream(localStream);
started = true;
logg("isRTCPeerConnection: " + isRTCPeerConnection);
if (isRTCPeerConnection) {
//set remote description
peerConn.setRemoteDescription(new RTCSessionDescription(msg));
//create answer
console.log("Sending answer to peer.");
peerConn.createAnswer(setLocalAndSendMessage, null, mediaConstraints);
} else {
//set remote description
peerConn.setRemoteDescription(peerConn.SDP_OFFER, new SessionDescription(msg.sdp));
//create answer
var offer = peerConn.remoteDescription;
var answer = peerConn.createAnswer(offer.toSdp(), mediaConstraints);
console.log("Sending answer to peer.");
setLocalAndSendMessage00(answer);
}
}
} else if (msg.type === 'answer' && started) {
peerConn.setRemoteDescription(new RTCSessionDescription(msg));
} else if (msg.type === 'candidate' && started) {
var candidate = new RTCIceCandidate({sdpMLineIndex:msg.label, candidate:msg.candidate});
peerConn.addIceCandidate(candidate);
} else if (msg.type == 'chat'){
addChatMsg(msg.nick, msg.cid, msg.data);
}
else if (msg.type === 'bye' && started) {
onRemoteHangUp();
}
}
function processSignalingMessage00(message) {
var msg = JSON.parse(message);
// if (msg.type === 'offer') --> will never happened since isRTCPeerConnection=true initially
if (msg.type === 'answer' && started) {
peerConn.setRemoteDescription(peerConn.SDP_ANSWER, new SessionDescription(msg.sdp));
} else if (msg.type === 'candidate' && started) {
var candidate = new IceCandidate(msg.label, msg.candidate);
peerConn.processIceMessage(candidate);
} else if (msg.type === 'bye' && started) {
onRemoteHangUp();
}
}
function setLocalAndSendMessage(sessionDescription) {
peerConn.setLocalDescription(sessionDescription);
sendMessage(sessionDescription);
}
function setLocalAndSendMessage00(answer) {
peerConn.setLocalDescription(peerConn.SDP_ANSWER, answer);
sendMessage({type: 'answer', sdp: answer.toSdp()});
peerConn.startIce();
}
function onRemoteHangUp() {
logg("Remote Hang up.");
closeSession();
}
function onHangUp() {
logg("Hang up.");
if (started) {
sendMessage({type: 'bye'});
closeSession();
}
}
function closeSession() {
peerConn.close();
peerConn = null;
started = false;
remotevid.src = "";
}
window.onbeforeunload = function() {
if (started) {
sendMessage({type: 'bye'});
}
}
function startVideo() {
// Replace the source of the video element with the stream from the camera
if (navigator.mozGetUserMedia) {
try {
navigator.mozGetUserMedia({audio: true, video: true}, successCallback, errorCallback);
} catch (e) {
navigator.mozGetUserMedia("video,audio", successCallback, errorCallback);
}
}
else {
try {
navigator.webkitGetUserMedia({audio: true, video: true}, successCallback, errorCallback);
} catch (e) {
navigator.webkitGetUserMedia("video,audio", successCallback, errorCallback);
}
}
function successCallback(stream) {
if (navigator.mozGetUserMedia) {
sourcevid.mozSrcObject = stream;
sourcevid.style.webkitTransform = "rotateY(180deg)";
localStream = stream;
}
if(navigator.webkitGetUserMedia){
sourcevid.src = window.webkitURL.createObjectURL(stream);
sourcevid.style.webkitTransform = "rotateY(180deg)";
localStream = stream;
}
}
function errorCallback(error) {
logg('An error occurred: [CODE ' + error.code + ']');
}
}
function stopVideo() {
sourcevid.src = "";
}
and here is the html
<script type="text/javascript" src="{{ asset('bundles/PFESiivt/js/visio.js') }}"></script>
<div id="main">
<div id="" style="height:280px;width:700;">
<div id="livevideodivk" style="float:left;">
<video id="sourcevid" style="height:280px;width:320px;" autoplay></video>
</div>
<div id="remotevideodivk" style="float:left;margin-left:10px">
<video id="remotevid" style="height:280px;width:320px;" autoplay></video>
</div>
</div>
<center>
<button id="btn" type="button" onclick="startVideo();">Start video</button>
<button id="btn" type="button" onclick="stopVideo();">Stop video</button>
<button id="btn" type="button" onclick="connect();">Connect</button>
<button id="btn" type="button" onclick="onHangUp();">Hang Up</button>
</center>
</div>
Have not gone through the complete code, but for starters...
for firefox it is mozRTCPeerConnection not RTCPeerConnection.
secondly, for firefox PeerConnection object, the onicecandidate handler is missing.
P. S: I think it is a very bad idea to post complete code, would advice to do bit of debugging yourself( to identify the block causing issue) and then post the relevant block when not able to solve it.
So, I have created a simple chat system which consists of nodeJS and mongodb. I currently 'host' it on apache, and it works perfectly on my computer, but if someone else connects to my site on the local network, then the chat doesnt work as intended. The send message and show message function breaks.
Ps: The code is from phpacademy, so cudos to them.
Here's the code I used:
HTML:
<!DOCTYPE html>
<html>
<head>
<title>ChattSystem</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="chat">
<input type="text" class="chat-name" placeholder="Enter your name">
<div class="chat-messages"></div>
<textarea placeholder="Type your message"></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name');
statusDefault = status.textContent,
setStatus = function(s) {
status.textContent = s;
if(s !== statusDefault) {
var delay = setTimeout(function() {
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
try {
var socket = io.connect('http://127.0.0.1:8080');
} catch(e) {
// Set status to warn user
}
if(socket !== undefined) {
// Listen for output
socket.on('output', function(data) {
if(data.length) {
// Loop through results
for(var x = 0; x < data.length; x = x + 1) {
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = data[x].name + ': ' + data[x].message;
// Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
// Listen for a status
socket.on('status', function(data) {
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true) {
textarea.value = '';
}
});
// Listen for keydown
textarea.addEventListener('keydown', function(event) {
var self = this,
name = chatName.value;
if(event.which);if(event.which == 13 && event.shiftKey === false) {
socket.emit('input', {
name: name,
message: self.value
});
event.preventDefault();
}
});
}
})();
</script>
</body>
</html>
Server.js
var mongo = require('mongodb').MongoClient,
client = require('socket.io').listen(8080).sockets;
mongo.connect('mongodb://127.0.0.1/chat', function(err, db) {
if(err) throw err;
client.on('connection', function(socket) {
var col = db.collection('messages'),
sendStatus = function(s) {
socket.emit('status', s);
};
// Emit all messages
col.find().limit(100).sort({_id: 1}).toArray(function(err, res) {
if(err) throw err;
socket.emit('output', res);
});
// Wait for input
socket.on('input', function(data) {
var name = data.name,
message = data.message,
whitespacePattern = /^\s*$/;
if(whitespacePattern.test(name) || whitespacePattern.test(message)) {
sendStatus('Name and message is required.');
} else {
col.insert({name: name, message: message}, function() {
// Emit latest message to ALL qclients
client.emit('output', [data]);
sendStatus({
message: "Message sent",
clear: true
});
});
}
});
});
});
In your JS from client side, change the IP to your server IP..
You script has currently the same local IP, thats mean what is always in localhost...
Find your IP and put it:
HTML (JS client side)
try {
var socket = io.connect('http://192.168.x.x:8080');
} catch(e) {
// Set status to warn user
}