I'm trying to broadcast a webcam's video to other clients in real-time, but I encounter some problems when viewer's start watching in the middle.

For this purpose, I get the webcam's stream using getUserMedia (and all its siblings).

Then, on a button click, I start recording the stream and send each segment/chunk/whatever you call it to the broadcaster's websocket's backend:

var mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start(1000);
mediaRecorder.ondataavailable = function (event) {
    uploadVideoSegment(event); //wrap with a blob and call socket.send(...)
}

On the server side (Web API, using Microsoft.Web.WebSockets), I get the byte[] as is perfectly.

Then I send the byte[] to the Viewers which are currently connected to the Broadcaster, read it on the onmessage event of the socket using a FileReader and append the Uint8Array to the sourceBuffer of the MediaSource which is the src of the HTML5 video element.

When the Viewers get the byte[] from the beginning, specifically, the first 126 bytes which start with the EBMLHeader (0x1A45DFA3) and end with the Cluster's beginning (0x1F43B675), and then the whole bulk of the media - it's being played fine.

The problem occurs when a new viewer joins in the middle and fetches the second chunk and later.

I've been trying to research and get the hands a little dirty with some kinds of ways. I understand that the header is essential (http://www.slideshare.net/mganeko/media-recorder-and-webm), that there's some stuff concerning keyframes and all this stuff but I got confused very quickly.

So far, I tried to write my own simple webm parser in c# (from a reference of node.js project in github - https://github.com/mganeko/wmls). Thus I splitted the header from the first chunk, cached it and tried to send it with each chunk later. Of course it didn't work.

I think that maybe the MediaRecorder is splitting the cluster in the middle as the ondataavailable event is fired (that's because I've noticed the the start fo the second chunk doesn't begin with the Cluster's header).

At this point I got stuck without knowing how to use the parser to get it work.

Then I read about using ffmpeg to convert the webm stream s.t each frame is also a keyframe - Encoding FFMPEG to MPEG-DASH – or WebM with Keyframe Clusters – for MediaSource API (in Chris Nolet's answer).

I tried to use FFMpegConverter (for .Net) using:

var conv = new FFMpegConverter();
var outputStream = new MemoryStream();

var liveMedia = conv.ConvertLiveMedia("webm", outputStream, "webm", new ConvertSettings { VideoCodec = "vp8", CustomOutputArgs = "-g 1" });
liveMedia.Start();
liveMedia.Write(vs.RawByteArr, 0, vs.RawByteArr.Length); //vs.RawByteArr is the byte[] I got from the MediaRecorder
liveMedia.Stop();

byte[] buf = new byte[outputStream.Length];
outputStream.Position = 0;
outputStream.Read(buf, 0, (int)outputStream.Length);

I'm not familiar with FFMPEG so probably I'm not getting in the parameters correctly although in the answer that's what I saw but they kind of wrote it very shortly there.

Of course I encountered here plenty of problems: When using websockets, the running of the FFMpegConverter simply forced closing the websockets channel. (I'll glad if someone could explain why).

I didn't give up, I wrote everything without websockets using HttpGet (for fetching the segment from the server) and HttpPost (with multipart blobs and all the after-party for posting the recorded chunks) methods and tried to use the FFMpegConverter as mentioned above.

For the first segment it worked BUT outputed a byte[] with half length of the original one (I'll be glad if someone could explain that as well), and for the other chunks it threw an exception (every time not just once) saying the pipe has been ended.

I'm getting lost.

Please help me, anybody. The main 4 questions are:

  1. How can I get played the chunks that follow the first chunk of the MediaRecorder? (Meanwhile, I just get the sourcebuffer close/end events fired and the sourceBuffer is detached from its parent MediaSource object (causing an exception like the "sourceBuffer has been removed from its parent") due to the fact that the byte[] passed to it is not good - Maybe i'm not using the webm parser I wrote in the correct way to detect important parts in the second chunk (which by the way doesn't start with a cluster - which why I wrote that it seems that the MediaRecorder is cutting the cluster in the middle))

  2. Why does the FFMpeg cause the WebSockets to be closed?

  3. Am I using the FFMpegConverter.ConvertLiveMedia with the correct parameters in order to get a new webm segment with all the information needed in it to get it as a standalone chunk, without being dependent on the former chunks (as Chris Nolet said in his answer in the SO link above)?

  4. Why does the FFMpegConverter throw "the pipe ended" exception?

Any help will be extremely highly appreciated.

0

There are 0 answers