Давайте рассмотрим этот видеофайл (A) и этот файл (B).
Я хочу воспроизвести оба файла в браузере с HTML5 и MSE. Технически я хочу обслуживать этот файл по частям, и JavaScript будет подавать тег видео через MSE:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket and MSE demo</title>
</head>
<body>
<video id="livestream" width="640" height="480" autoplay />
</body>
<script>
//var verbose = false;
var verbose = true;
// set mimetype and codec
var mimeType = "video/mp4";
var codecPars = mimeType;
var streamingStarted = false; // is the sourceBuffer updateend callback active nor not
// create media source instance
var ms = new MediaSource();
// queue for incoming media packets
var queue = [];
var ws; // websocket
// ** two callbacks **
// - pushPacket : called when websocket receives data
// - loadPacket : called when sourceBuffer is ready for more data
// Both operate on a common fifo
function pushPacket(arr) { // receives ArrayBuffer. Called when websocket gets more data
// first packet ever to arrive: write directly to sourceBuffer
// sourceBuffer ready to accept: write directly to SourceBuffer
// otherwise insert to fifo
var view = new Uint8Array(arr);
if (verbose) { console.log("got", arr.byteLength, "bytes. Values=", view[0], view[1], view[2], view[3], view[4]); }
data = arr;
if (!streamingStarted && !sourceBuffer.updating) {
if (verbose) console.log("Streaming started with", view[0], view[1], view[2], view[3], view[4]);
sourceBuffer.appendBuffer(data);
streamingStarted=true;
return;
}
queue.push(data); // add to the end
if (verbose) { console.log("queue push:", queue.length); }
}
function loadPacket() { // called when sourceBuffer is ready for more
if (!sourceBuffer.updating) { // really, really ready
if (queue.length>0) {
inp = queue.shift(); // pop from the beginning
if (verbose) { console.log("queue PULL:", queue.length); }
var view = new Uint8Array(inp);
if (verbose) { console.log(" writing buffer with", view[0], view[1], view[2], view[3], view[4]); }
sourceBuffer.appendBuffer(inp);
}
else { // the queue runs empty, so we must force-feed the next packet
streamingStarted = false;
}
}
else { // so it was not?
}
}
function opened() { // now the MediaSource object is ready to go
sourceBuffer = ms.addSourceBuffer(codecPars);
sourceBuffer.addEventListener("updateend",loadPacket);
// set up the websocket
ws = new WebSocket("ws://videoserver");
ws.binaryType = "arraybuffer";
ws.onmessage = function (event) {
pushPacket(event.data);
};
}
function startup() {
// add event listeners
ms.addEventListener('sourceopen',opened,false);
// get reference to video
var livestream = document.getElementById('livestream');
// set mediasource as source of video
livestream.src = window.URL.createObjectURL(ms);
}
window.onload = function() {
startup();
}
</script>
</html>
Файл 'A' на 100% правильный, может воспроизводиться моим кодом.
Файл 'B' может быть не на 100% корректным, но он хорошо воспроизводится в VL C (Windows и Ubuntu), а также в «Фильмах и ТВ» на Windows, но может не воспроизводится моим кодом .
Браузеры (Chrome, Firefox) не выдают никаких сообщений об ошибках или предупреждений, когда я пытаюсь воспроизвести файл 'B'. Это просто не отображается.
Я поместил эти файлы в http://thumb.co.il, который является видеоинспектором. Файлы кажутся одинаковыми и хорошими (оба начинаются с ftyp, moov, moof, mdat).
У меня два вопроса:
- В чем проблема с файлом 'B'?
- Как я могу изменить код для воспроизведения также файла 'B'? (использование дополнительной клиентской библиотеки может быть приемлемым решением)