我正在提供这个由 ffmpeg 创建的碎片化 mp4 文件。
这是客户端代码:
<!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>
视频文件是 websocket 上的服务器。
该解决方案适用于(至少在 Windows 10 下):
- Chrome 浏览器版本 80.0.3987.116(官方构建)(64 位)
- 微软边缘44.18362.449.0
- Internet Explorer 11.657.18362.0
- 歌剧66.0.3515.103
但是 in 不起作用:
- Firefox 73.0.1(64 位)(Windows 10 下)
- Ubuntu 18.04 下的Firefox 73.0(64 位)
该视频未在 Firefox 浏览器中播放,浏览器声称Media resource blob:http://abcdef could not be decoded.
。
如何调试 Firefox 以查看问题所在?