How to execute a function at same time for multiple people? - javascript

I have an application stored in IBM server where the same application is being used by multiple people. We have a feature where we need to execute that particular piece of code exactly at same time for multiple people. How can I achieve this? The feature is that, a particular person will initiate a recording feature which will open the microphones of every person. This is achieved by maintaining a variable whose value I am setting and de setting, but when I am ending the recording the person who ends immediately the code gets executed but for other people it takes few milliseconds and even seconds to execute that same piece of code? Any help how can I tackle to this issue.
render () {
this.props.meetingData.isMeetingDiscussionStarted ? this.recordFullAudio() : null;
!this.props.meetingData.isMeetingDiscussionStarted ? this.stopRecordingAudio() : null;
}
recordFullAudio = () => {
const constraints = {
audio: {
channels: 1
},
video: false
};
getUserMedia(constraints)
.then(stream => {
this.stream = stream;
const mimeType = 'audio/mpeg';
const mime = ['audio/wav', 'audio/mpeg', 'audio/webm', 'audio/ogg']
.filter(MediaRecorder.isTypeSupported)[0];
const options = {
mimeType: 'audio/webm',
};
this.mediaRecorder = new MediaRecorder(stream);
this.mediaRecorder.addEventListener('dataavailable', event => {
audioChunks.push(event.data);
});
this.mediaRecorder.addEventListener('stop', () => { });
}).catch(error => { });
}
stopRecordingAudio = () => {
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
this.mediaRecorder.stop();
this.stream.getTracks().forEach((track) => {
track.stop();
});
}
// Cleanup
this.mediaRecorder = null;
this.stream = null;
}
isMeetingDiscussionStarted is that variable maintained in NodeJS sharedb doc which is used to start and end recording.

Related

Use incomplete browser fetch request in video/audio element

I have some code like this:
fetch(audioSRC).then(response => {
return new Response( new ReadableStream({
start(controller) {
const reader = response.body.getReader();
read(); function read() {
reader.read().then(({done, value}) => {
if (done) {
controller.close();
return;
}
read();
})
}
}
})
);
}).then(response => response.blob()).then(blob => {
let vid = URL.createObjectURL(blob);
player.src = vid;
})
i was wondering if it is possible to take this stream while it's incomplete, and play what IS downloaded in the video/audio element before the download is complete? If there is a way to do it smoothly, it would be good so that the user doesn't have to wait until it's fully downloaded.
It works with https://developer.mozilla.org/en-US/docs/Web/API/MediaSource
After hours of experimenting, found a half-working solution: https://stackoverflow.com/a/68778572/11979842

Having issues with working with socket.io and mediastream api to send realtime, live audio chat between clients in a room

I am having an issue that I can't seem to figure out. I am creating an application in which clients in a room will be able to talk to each other via their microphone. So more specifically, I need to stream audio from one client's microphone, send the data (while it is being recorded) to the server and then to a different client so that they can can hear the other persons voice in real-time. I have a method of doing this, but it is inefficient, choppy, and blatantly bad...
My method as of now:
This snippet is on the client side of the person recording audio
setInterval(() => {
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
const mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start();
const audioChunks = [];
mediaRecorder.addEventListener("dataavailable", (event) => {
audioChunks.push(event.data);
});
mediaRecorder.addEventListener("stop", () => {
socket.emit('liveAudioToServer', audioChunks)
});
setTimeout(() => {
mediaRecorder.stop();
},2000);
});
}, 2000);
This snippet is the server side:
socket.on('liveAudioToServer', (data) => {
socket.broadcast.to(room).emit('liveAudioToClient', data)
})
And this snippet is the client side on the receiving end of the audio:
socket.on('liveAudioToClient', (data) => {
const audioBlob = new Blob(data);
const audioUrl = URL.createObjectURL(audioBlob);
const audio = new Audio(audioUrl);
audio.play()
})
Basically, what this code does is it sends an audio buffer every two seconds to the server and then the server broadcast the buffer to the other clients in the room. once the other clients receive the buffer, they compile it into audio that is played. The main issue with this is that you can clearly tell when the audio ends and begins and it is not smooth in the slightest. However, I tried a different solution that with some tweaking I feel like it could work. But it doesn't work as of now..
Other Method:
if(navigator.getUserMedia) {
navigator.getUserMedia(
{audio: true},
function(stream) {
const audioContext3 = new AudioContext();
const audioSource3 = audioContext3.createMediaStreamSource(stream);
const analyser3 = audioContext3.createAnalyser();
audioSource3.connect(analyser3);
analyser3.fftSize = 256;
const bufferLength = analyser3.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
function sendAudioChunks(){
analyser3.getByteFrequencyData(dataArray);
requestAnimationFrame(sendAudioChunks);
socket.emit('liveAudioToServer', dataArray)
}
sendAudioChunks();
},
function(){ console.log("Error 003.")}
);
}
server side:
socket.on('liveAudioToServer', (data) => {
socket.broadcast.to(getRoom(socket.id)).emit('liveAudioToClient', data)
})
other clients side (receiving audio)
socket.on('liveAudioToClient', (data) => {
const audioBlob = new Blob([new Uint8Array(data)])
const audioUrl = URL.createObjectURL(audioBlob);
const audioo = new Audio(audioUrl);
audioo.play()
})
I've really looked everywhere for the solution to this and I have had no luck so if anyone could help me that would be greatly appreciated!!!

Request video during PeerJs ongoing live connection (stream)

I am new to PeerJs and recently starting developing an app for my school during this Covid pandemic.
I have been able to deploy code to NodeJs server with express and was able to establish connection between 2 users.
But the problem arises when video is turned off from the beginning of stream for both users and a user wants to initiate a video call.
What I need is, to send some kind of notification to user 2 that user 1 is requesting for video. So that user 2 will turn on video.
My existing code is:
var url = new URL(window.location.href);
var disableStreamInBeginning = url.searchParams.get("disableStreamInBeginning"); // To disable video in the beginning
var passwordProtectedRoom = url.searchParams.get("passwordProtectedRoom");
var muteAllInBeginning = url.searchParams.get("muteAllInBeginning");
const socket = io('/')
const localVideoDiv = document.getElementById('local-video-div')
const oneOnOneSelf = document.getElementById('local-video')
const oneOnOneRemote = document.getElementById('remote-video')
if(typeof disableStreamInBeginning !== 'undefined' && disableStreamInBeginning == 'true'){
var disbaleSelfStream = true
} else {
var disbaleSelfStream = false
}
if(typeof passwordProtectedRoom !== 'undefined' && passwordProtectedRoom == 'true'){
var passwordProtected = true
} else {
var passwordProtected = false
}
if(typeof muteAllInBeginning !== 'undefined' && muteAllInBeginning == 'true'){
var muteAll = true
} else {
var muteAll = false
}
var systemStream
oneOnOneSelf.style.opacity = 0
oneOnOneRemote.style.opacity = 0
const myPeer = new Peer(undefined, {
host: '/',
port: '443',
path: '/myapp',
secure: true
})
const ownVideoView = document.createElement('video')
const peers = {}
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(ownStream => {
systemStream = ownStream
addVideoStream(ownStream, oneOnOneSelf)
myPeer.on('call', call => {
call.answer(ownStream)
call.on('stream', remoteStream => {
addVideoStream(remoteStream, oneOnOneRemote)
})
})
socket.on('user-connected', userId => {
//connectToNewUser(userId, stream)
setTimeout(connectToNewUser, 1000, userId, ownStream)
})
})
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
myPeer.on('open', id => {
//Android.onPeerConnected();
socket.emit('join-room', ROOM_ID, id)
})
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream)
call.on('stream', remoteStream => {
//console.log('Testing')
addVideoStream(remoteStream, oneOnOneRemote)
})
call.on('close', () => {
oneOnOneRemote.remove()
})
peers[userId] = call
}
function addVideoStream(stream, videoView) {
videoView.srcObject = stream
videoView.addEventListener('loadedmetadata', () => {
if(disbaleSelfStream){
audioVideo(true)
} else {
localVideoDiv.style.opacity = 0
videoView.style.opacity = 1
videoView.play()
}
})
}
function audioVideo(bool) {
if(bool == true){
localVideoDiv.style.opacity = 1
oneOnOneSelf.style.opacity = 0
systemStream.getVideoTracks()[0].enabled = false
} else {
if(disbaleSelfStream){
console.log('Waiting For Another User To Accept') // Here is need to inform user 2 to tun on video call
} else {
localVideoDiv.style.opacity = 0
oneOnOneSelf.style.opacity = 1
systemStream.getVideoTracks()[0].enabled = true
}
}
}
function muteUnmute(bool) {
if(bool == true){
systemStream.getAudioTracks()[0].enabled = true
} else {
systemStream.getAudioTracks()[0].enabled = false
}
}
function remoteVideoClick(){
alert('Hi');
}
Please help.
You can send messages back and forth directly using peer itself
const dataConnection = peer.connect(id) will connect you to the remote peer, it returns a dataConnection class instance that you can later use with the send method of that class.
Just remember that you also want to setup listener on the other side to listen for this events, like "open" to know when the data channel is open:
dataConnection.on('open', and dataConnection.on('data...
You have a bug in your code above, I know you didn't ask about it, it is hard to see and not always will manifest. The problem will occur when your originator sends a call before the destination has had time to receive the promise back with its local video/audio stream. The solution is to invert the order of the calls and to start by setting up the event handler for peer.on("call", ... rather than by starting by waiting for a promise to return when we ask for the video stream. The failure mode will depend on how long does it take for your destination client to signal it wants and call to the originator plus how long it takes for the originator to respond versus how long it takes for the stream promise to return on the destination client. You can see a complete working example, where messages are also sent back and forth here.
// Function to obtain stream and then await until after it is obtained to go into video chat call and answer code. Critical to start the event listener ahead of everything to ensure not to miss an incoming call.
peer.on("call", async (call) => {
let stream = null;
console.log('*** "call" event received, calling call.answer(strem)');
// Obtain the stream object
try {
stream = await navigator.mediaDevices.getUserMedia(
{
audio: true,
video: true,
});
// Set up event listener for a peer media call -- peer.call, returns a mediaConnection that I name call
// Answer the call by sending this clients video stream --myVideo-- to calling remote user
call.answer(stream);
// Create new DOM element to place the remote user video when it comes
const video = document.createElement('video');
// Set up event listener for a stream coming from the remote user in response to this client answering its call
call.on("stream", (userVideoStream) => {
console.log('***"stream" event received, calling addVideoStream(UserVideoStream)');
// Add remote user video stream to this client's active videos in the DOM
addVideoStream(video, userVideoStream);
});
} catch (err) {
/* handle the error */
console.log('*** ERROR returning the stream: ' + err);
};
});

How decline a offer o call in peerjs

hello guys How I can reject o accepted a call or offer is coming from the sender peer, I just using Peerjs client and peer server
this is my sender client
const peer = new Peer('sender', { host: '1.0.0.99', port: 9000, path: '/' })
var call = document.getElementById('call');
call.addEventListener('click',startChat);
function startChat(){
navigator.mediaDevices.getUserMedia({ video: true}).then((localStream) =>{
document.querySelector('video#local').srcObject = localStream;
var call = peer.call('receiver',localStream);
call.on('stream',remoteStream => {
document.querySelector('video#remote').srcObject = remoteStream
})
})
}
this is my receiver
const peer = new Peer('receiver', { host: '1.0.0.99', port: 9000, path: '/' })
peer.on('call', call => {
const startChat = async () => {
const localStream = await navigator.mediaDevices.getUserMedia({
video: true
})
document.querySelector('video#local').srcObject = localStream
// call.answer(localStream)
call.close(mediaStream);
call.on('stream', remoteStream => {
document.querySelector('video#remote').srcObject = remoteStream
})
}
startChat();
})
my goal on receiver can decline and accepted sorry I am new in this, thanks for any help
According to the oficial documentation, the MediaConnection API, states that the close() method should be used to reject the call, and the answer() method to accept it. In your code, you have tried both, even though you're passing an argument to the close() function, which doesn't take any. Now if you close the Media Connection, I assume that the callback on the the 'stream' message is invalid.
well I found the way
peer.on('call', call => {
var acceptsCall = confirm("Videocall incoming, do you want to accept it ?");
if (acceptsCall) {
const startChat = async () => {
const localStream = await navigator.mediaDevices.getUserMedia({
video: true
})
document.querySelector('video#local').srcObject = localStream
call.answer(localStream)
call.on('stream', remoteStream => {
document.querySelector('video#remote').srcObject = remoteStream
});
// Handle when the call finishes
call.on('close', function () {
alert("The videocall has finished");
});
}
startChat();
} else {
alert('call decline!');
}
})
one of the solutions I found was to start a conversation and after 0.1 seconds, close the connection, it is not one of the best solutions, but it was the one that served me the most.

RTCPeerConnection connectionState never moves from "new" to "checking"/"connected"

I have taken over a WebRTC project from someone and though I'm starting to wrap my head around the concepts, I continue to be stumped by a specific problem: getting the WebRTC connection to move from new to checking/completed, etc...
Here is the extent of the output from chrome://webrtc-internals:
Our code calls connect():
connect(mediaStream, interviewUid, applicantUid) {
return new Promise((resolve, reject) => {
this.connectRtcPeerConnection()
.then(() => {
this.connectionState = Socket.CONNECTION_STATES.connected;
this.rtcPeer.addStream(mediaStream);
return this.rtcPeer.createOffer({ offerToReceiveAudio: 1, offerToReceiveVideo: 1 });
}).then((offer) => {
console.log('offer created', offer);
return this.rtcPeer.setLocalDescription(offer);
}).then(() => {
const message = {
id: SENDABLE_MESSAGES.connect,
sdpOffer: this.rtcPeer.localDescription,
interviewUid,
applicantUid,
};
this.sendMessageToServer(message);
resolve();
})
.catch((error) => {
console.error(error);
reject();
});
});
}
which in turns calls connectRtcPeerConnection():
connectRtcPeerConnection(
) {
return new Promise((resolve, reject) => {
if (this.rtcPeer) {
resolve();
}
console.log('started connecting');
const rtcPeerOptions = {
iceServers: [TRUNCATED],
};
console.log('rtcPeerOptions', rtcPeerOptions);
this.rtcPeer = new RTCPeerConnection(rtcPeerOptions);
console.log('rtcPeer object: ', this.rtcPeer);
this.rtcPeer.onerror = reject;
this.rtcPeer.onicecandidate = (candidate) => { this.handleIceCandidateEvent(candidate); };
this.rtcPeer.oniceconnectionstatechange = () => {
this.handleIceConnectionStateChangeEvent();
};
this.rtcPeer.onaddstream = () => { console.log('handleAddStreamEvent'); };
this.rtcPeer.onremovestream = () => { console.log('handleRemoveStreamEvent'); };
this.rtcPeer.onicegatheringstatechange = () => { console.log('handleIceGatheringStateChangeEvent'); };
this.rtcPeer.onsignalingstatechange = () => { console.log('handleSignalingStateChangeEvent'); };
this.rtcPeer.onnegotiationneeded = () => { console.log('handleNegotiationNeededEvent'); };
resolve();
});
}
This chunk of code never gets executed:
this.rtcPeer.oniceconnectionstatechange = () => {
this.handleIceConnectionStateChangeEvent();
};
I've followed every conditional and code path and don't currently see what the issue might be. Has anyone encountered this and is able to shed some light on potential things to look at/consider?
Thanks!
When I was implementing Kurento library for iOS, tried something like this:
Generated SDPOffer
Set LocalDescription at our end
WebRTC started generating IceCandidate
Sent Ice Candidate through WebSocket
At this point, other party sent SDPAnswer.
Processed SDPAnswer at our end.
Set RemoteDescription at our end.
Server started sending IceCandidate gathered at their end.
Added these IceCandidate in array at our end.
Here received change in connection state to "Checking"
Received RemoteStream at this point.
Here received change in connection state to "Connected"
Hope it helps!
well, you never call setRemoteDescription or add a remote ice candidate via addIceCandidate. Without that there is no-one to talk to

Categories

Resources