Transmisión en vivo de la cámara web en línea (usando getUserMedia) mediante la grabación de fragmentos con MediaRecorder a través de WEB API con WebSockets y MediaSource

Estoy tratando de transmitir el video de una cámara web a otros clientes en tiempo real, pero encuentro algunos problemas cuando el espectador comienza a mirar en el medio.

Para este propósito, obtengo la transmisión de la cámara web usando getUserMedia (y todos sus hermanos).

Luego, al hacer clic en un botón, empiezo a grabar la transmisión y envío cada segmento / fragmento / como se llame al backend websocket de la emisora:

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

En el lado del servidor (API web, usando Microsoft.Web.WebSockets), obtengo el byte [] como está perfectamente.

Luego envío el byte [] a los espectadores que están conectados actualmente a la emisora, lo leo en el evento onmessage del socket usando un FileReader y agrego el Uint8Array al sourceBuffer de MediaSource, que es el src del elemento de video HTML5.

Cuando los espectadores obtienen el byte [] desde el principio, específicamente, los primeros 126 bytes que comienzan con EBMLHeader (0x1A45DFA3) y terminan con el comienzo del Cluster (0x1F43B675), y luego todo el volumen de los medios, se está reproduciendo bien.

El problema ocurre cuando un nuevo espectador se une en el medio y obtiene el segundo fragmento y más tarde.

He estado tratando de investigar y ensuciarme las manos de alguna manera. Entiendo que el encabezado es esencial (http://www.slideshare.net/mganeko/media-recorder-and-webm), que hay algunas cosas relacionadas con los fotogramas clave y todo esto, pero me confundí muy rápido.

Hasta ahora, intenté escribir mi propio analizador webm simple en c # (a partir de una referencia del proyecto node.js en github -https://github.com/mganeko/wmls) Por lo tanto, separé el encabezado del primer fragmento, lo almacené en caché e intenté enviarlo con cada fragmento más tarde. Por supuesto que no funcionó.

Creo que tal vez MediaRecorder está dividiendo el clúster en el medio a medida que se activa el evento ondataavailable (eso es porque he notado que el comienzo del segundo fragmento no comienza con el encabezado del Cluster).

En este punto me quedé atascado sin saber cómo usar el analizador para que funcione.

Luego leí sobre el uso de ffmpeg para convertir la transmisión webm en cada fotograma también es un fotograma clave:Codificación de FFMPEG a MPEG-DASH, o WebM con clústeres de fotogramas clave, para la API de MediaSource (en la respuesta de Chris Nolet).

Traté de usar FFMpegConverter (para .Net) usando:

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);

No estoy familiarizado con FFMPEG, así que probablemente no entiendo los parámetros correctamente, aunque en la respuesta eso es lo que vi, pero lo escribieron muy poco allí.

Por supuesto, encontré muchos problemas aquí: cuando utilizo websockets, la ejecución del FFMpegConverter simplemente forzó el cierre del canal websockets. (Me alegraría si alguien pudiera explicar por qué).

No me di por vencido, escribí todo sin websockets usando HttpGet (para obtener el segmento del servidor) y HttpPost (con blobs multiparte y todo el after-party para publicar los fragmentos grabados) y traté de usar el FFMpegConverter como se mencionó encima.

Para el primer segmento funcionó PERO superó un byte [] con la mitad de longitud que el original (me alegraría si alguien pudiera explicar eso también), y para los otros fragmentos arrojó una excepción (cada vez, no solo una vez) diciendo que la tubería ha terminado.

Me estoy perdiendo

Por favor, ayúdenme, cualquiera. Las 4 preguntas principales son:

¿Cómo puedo reproducir los fragmentos que siguen al primer fragmento de MediaRecorder? (Mientras tanto, acabo de disparar los eventos de cierre / finalización del buffer de origen y el sourceBuffer se separa de su objeto MediaSource principal (lo que provoca una excepción como "el sourceBuffer se ha eliminado de su padre") debido al hecho de que el byte [] pasó a no es bueno: tal vez no estoy usando el analizador webm que escribí de la manera correcta para detectar partes importantes en el segundo fragmento (que por cierto no comienza con un clúster, por lo que escribí que parece que el MediaRecorder está cortando el clúster en el medio))

¿Por qué FFMpeg hace que se cierren los WebSockets?

¿Estoy usando el FFMpegConverter.ConvertLiveMedia con los parámetros correctos para obtener un nuevo segmento webm con toda la información necesaria para obtenerlo como un fragmento independiente, sin depender de los fragmentos anteriores (como dijo Chris Nolet en su respuesta en el enlace SO anterior)?

¿Por qué el FFMpegConverter arroja la excepción "la tubería terminó"?

Cualquier ayuda será muy apreciada.

Respuestas a la pregunta(0)

Su respuesta a la pregunta