I'm actually working on an application based on NodeJS, ws, WebRTC.io and socket.io. The aim of this application is to broadcast the video of an Host to multiple attendees.
The host and all the attendees load the web application, then the host launch his video and stream it to all the attendees. For this case I don't have any problem, but if the host launch his video, then an attendee join the room, this attendee is not able to retrieve the stream, and I don't how to get this stream.
I've tried many solution.
When an attendee arrive in the room, he send a message via socket.io to the Host which send back his stream. The problem is that the stream arrive to the attendee as an Object and not as a MediaStream, so I can't use it.
When an attendee arrive in the room, he send a message via socket.io to the Host which send back a blob created with window.webkitURL.createObjectURL(rtc.streams[0]), then I use this blob as the video source for the attendee, but I obtain a 404 error.
Here is the code for both solutions :
var isStreamCreated = false;
function startVideoLive() {
var video = document.getElementById('video');
//Test if peer connection is available for the browser
if (PeerConnection) {
if (getRole() == 1) {
rtc.createStream({
"video": true,
"audio": true
}, function (stream) {
video.src = URL.createObjectURL(stream);
video.play();
isStreamCreated = true
});
}
}
if (isConnected != true) {
var room = '1234';
rtc.connect('ws://' + server + ':8443', room);
isConnected = true;
}
}
function setAttendeeWebRTC() {
if (getRole() == 0) {
var message = {
type: "getStreamInfos",
URL: null,
stream: null
}
socket.emit('message', message);
rtc.on('add remote stream', function (stream, socketId) {
rtc.attachStream(stream, 'video');
isStreamCreated = true;
});
}
}
startVideoLive();
setAttendeeWebRTC();
function onGetStreamInfos(message) {
if (getRole() == 1 && isStreamCreated == true) {
message.URL = window.webkitURL.createObjectURL(rtc.streams[0]);
message.stream = rtc.streams[0];
socket.emit('message', message);
} else if (getRole() == 0 && isStreamCreated == false && message.URL != null && message.stream != null) {
document.getElementById('video').src = message.URL;
// OR
rtc.attachStream(message.stream, 'video')
isStreamCreated = true;
}
}
getRole() is used to know if the user connected is an attendee (0) or the host (1).
In the server side I just broadcast the websocket message, and add webrtc.io (and many other things, but not usefull in this case).
Here is the errors for the 2 case :
With the blob : GET blob:http%3A//128.1.222.159%3A8081/881928b6-70d3-4054-b15e-88d635a2125f 404 (Not Found)
With the stream : Uncaught TypeError: Type error
rtc.attachStream
onGetStreamInfos
(anonymous function)
EventEmitter.emit socket.io.js?=1375350434038:633
SocketNamespace.onPacket socket.io.js?=1375350434038:2248
Socket.onPacket socket.io.js?=1375350434038:1930
Transport.onPacket socket.io.js?=1375350434038:1332
Transport.onData socket.io.js?_=1375350434038:1303
WS.open.websocket.onmessage
If someone has any ideas on how I can deal with my problem, I would thank in advance.
I found how to figured out my problem, but there is a new problem. Here is my partial solution :
function onGetStreamInfos(message) {
if (getRole() == 1 && isStreamCreated == true) {
rtc.createPeerConnections();
rtc.addStreams();
rtc.addDataChannels();
rtc.sendOffers()
} else if (getRole() == 0 && isStreamCreated == false) {
isStreamCreated = true;
}
}
But now, when an attendee join the room the other attendees lost the video. I think it's because normally I shouldn't create peer a peer connection between the new attendee and the old one.
I'm not sure if it's very clear, but if you need more information don't hesitate to ask, and if I finally find how to fix my problem I'll give the solution here.
By removing rtc.createPeerConnections(); and rtc.addDataChannels(); it seems to work in most of the case (I didn't test so much case).
If I'm understanding your question correctly, it looks like you're trying to exchange video data via Socket.io messaging, whereas this needs to be done via RTCPeerConnection.
Shameless self promotion, but you might want to look at the WebRTC codelab I wrote, which uses Socket.io for signaling.
For a few attendees, you can get away with multiple RTCPeerConnections. (Take a look at apps like Talky, Tawk, FACEmeeting or Browser Meeting.)
For more attendees, you'll need to use an MCU (there are open source implementations available), or roll your own server-side WebRTC app. There's more information about WebRTC architectures in this year's Google I/O presentation: video, slides.
Why are you doing rtc.addDataChannels(); datachannels are created for transmitting data (not media), for media you need to just use RTCPeerConnection, send sdp and ice candidates to peer through signalling channels. If everything goes well you will have a media stream.
datachannels have no role in sending media stream, its rather to be used for peer to peer data (games, files etc.)
If you don't want to go through the hassle of setting up your own signaling server, you can use Pubnub or Pusher to handle that for you. They are real-time data platform but that can be use to do webRTC signaling too.
Here's a webRTC signaling tutorial using Pusher if you are interested in trying it out.
http://pusher.com/tutorials/webrtc_chat
disclaimer: I work at Pusher.