使用WebSockets和MediaSource通过WEB API在MediaRecorder上记录块来实时流式摄像头webm流(使用getUserMedia)

Shi*_*ach 8 live-streaming webm asp.net-web-api media-source mediarecorder-api

我正在尝试实时向其他客户端播放网络摄像头的视频,但是当观众开始在中间观看时我遇到了一些问题.

为此,我使用getUserMedia(及其所有兄弟姐妹)获取网络摄像头的流.

然后,在按钮单击时,我开始记录流并将每个段/块/任何你调用它发送到广播公司的websocket的后端:

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

在服务器端(Web API,使用Microsoft.Web.WebSockets),我得到了完美的byte [].

然后我将byte []发送到当前连接到Broadcaster的Viewers,使用FileReader在socket的onmessage事件上读取它,并将Uint8Array附加到MediaSource的sourceBuffer,这是HTML5视频元素的src.

当观众从头开始获取byte []时,具体地说,前面的126个字节以EBMLHeader(0x1A45DFA3)开头并以Cluster的开头(0x1F43B675)结束,然后是整个媒体 - 它正好被播放.

当新的查看器加入中间并获取第二个块以及之后时,会出现此问题.

我一直在努力研究并用某种方式让手有点脏.我知道标题是必不可少的(http://www.slideshare.net/mganeko/media-recorder-and-webm),关于关键帧和所有这些东西有一些东西,但我很快就感到困惑.

到目前为止,我尝试在c#中编写自己的简单webm解析器(来自github中的node.js项目的引用 - https://github.com/mganeko/wmls).因此,我从第一个块中分割出标头,缓存它并尝试稍后将其与每个块一起发送.当然它没有用.

我认为可能是MediaRecorder在中间分裂集群,因为ondataavailable事件被触发(这是因为我注意到第二个块的开始并不是从Cluster的头开始).

在这一点上,我不知道如何使用解析器使其工作.

然后我读到了使用ffmpeg来转换webm流,每个帧也是一个关键帧 - 编码FFMPEG到MPEG-DASH - 或带有Keyframe Clusters的WebM - 用于MediaSource API(在Chris Nolet的回答中).

我尝试使用FFMpegConverter(用于.Net):

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);
Run Code Online (Sandbox Code Playgroud)

我不熟悉FFMPEG,所以可能我没有正确地参与参数,尽管在我看到的答案中,但他们很快就在那里写了.

当然我在这里遇到了很多问题:当使用websockets时,FFMpegConverter的运行只是强制关闭websockets通道.(如果有人能解释原因,我会很高兴).

我没有放弃,我使用HttpGet(用于从服务器获取段)和HttpPost(使用多部分blob和所有派对来发布记录的块)方法编写了没有websockets的所有内容,并尝试使用FFMpegConverter,如上所述以上.

对于第一个段它工作但是输出了一个byte [],其长度是原始段的一半(如果有人能够解释那个,我会很高兴),而对于其他块,它会抛出一个异常(每次都不是一次)说管子已经结束了.

我迷路了.

请帮助我,任何人.主要的4个问题是:

  1. 如何播放MediaRecorder第一块后面的块?(同时,我刚刚触发了sourcebuffer close/end事件,并且sourceBuffer与其父MediaSource对象分离(导致像"sourceBuffer已从其父节点中删除"之类的异常),因为byte []传递给它并不好 - 也许我没有使用我用正确方法编写的webm解析器来检测第二个块中的重要部分(顺便说一句,它不是从一个簇开始的 - 这就是为什么我写的那个似乎是MediaRecorder正在削减中间的集群))

  2. 为什么FFMpeg会导致WebSockets关闭?

  3. 我使用FFMpegConverter.ConvertLiveMedia和正确的参数,以获得一个新的webm段,其中包含所需的所有信息,使其成为一个独立的块,而不依赖于前面的块(正如Chris Nolet在他的回答中所说的那样)上面的SO链接)?

  4. 为什么FFMpegConverter抛出"管道结束"异常?

任何帮助将非常感谢.