我可以将WebM的任意块(从字节偏移量开始)发送到要播放的mediaSource缓冲区吗



我试图从Node.js服务器发送WebM文件的特定截断部分,从任意关键帧开始,由客户端使用MediaSource缓冲进行播放,但我不确定这是否可能,也不确定如何进行。

到目前为止,这就是我正在尝试的:

  1. 使用mse_json_manifest从https://github.com/acolwell/mse-tools
  2. init段和随机选择的媒体段的concat流
  3. 通过HTTP请求或套接字事件向客户端发送流

看起来发送init段总是有效的,因为客户端的HTMl5视频播放器显示原始文件的持续时间,但它不会缓冲随后发送的连接媒体段。

这是相关的服务器代码:

const merge = (...streams: ReadStream[]) => {
let pass = new PassThrough();
let waiting = streams.length;
for (let stream of streams) {
pass = stream.pipe(pass, {end: false});
stream.once("end", () => --waiting === 0 && pass.emit("end"));
}
return pass;
}
io.on("connection", (socket) => {
const streams = [
fs.createReadStream(file, {
start: audioJson.init.offset,
end: audioJson.init.size,
}),
fs.createReadStream(file, {
start: audioJson.media[150].offset,
})
];
merge(...streams).on("data", (data) => socket.emit("audio-data", data));
});

客户:

const streamVideo = document.getElementById("webmStream");
const mediaSource = new MediaSource();
const streamSource = URL.createObjectURL(mediaSource);
streamVideo.src = streamSource;
const audioMime = `audio/webm; codecs="opus"`;
const videoMime = `video/webm; codecs="vp9"`;
mediaSource.addEventListener("sourceopen", () => {
const audioBuffer = mediaSource.addSourceBuffer(audioMime);
const audioChunks = [];
function appendOrQueueChunk(chunk) {
if (!audioBuffer.updating && !audioChunks.length) {
audioBuffer.appendBuffer(chunk);
} else {
audioChunks.push(chunk);
}
}
socket.on("audio-data", appendOrQueueChunk);
audioBuffer.addEventListener("updateend", () => {
if (audioChunks.length) audioBuffer.appendBuffer(audioChunks.shift());
});

还有一段JSON:

{
"type": "audio/webm;codecs="opus"",
"duration": 93100.000000,
"init": { "offset": 0, "size": 526},
"media": [
{ "offset": 526, "size": 10941, "timecode": 0.000000 },
{ "offset": 11467, "size": 10382, "timecode": 0.260000 },
{ "offset": 21849, "size": 10301, "timecode": 0.520000 },
{ "offset": 32150, "size": 10495, "timecode": 0.780000 },
...

只要我只是直接从fs发出套接字事件,套接字流就可以正常工作。ReadStream的整个WebM文件,所以它可能与按顺序发送流有关,但我觉得完全超出了我的深度,认为我在概念上遗漏了一些东西。

您甚至不需要MediaSource。普通的视频元素可以通过一个简单的HTTP请求从Node.js服务器流式传输。不需要Socket.IO什么的。

<video src="https://nodejs-stream-server.example.com/something"></video>

我不知道你使用的库,所以我会用更通用的术语告诉你我过去是如何完成这项任务的,也许你可以调整它或重新实现它。

首先,当媒体流的请求进入Node.js服务器时,您必须发送一些初始化数据。听起来你已经成功地做到了。这个初始化数据基本上是流中直到第一个Cluster元素的所有数据。

因此,当你的编码器启动时,一定要缓冲数据,这样你就可以把它发送给新的客户端了。

接下来,您可以从任意Cluster元素开始,只要该Cluster以关键帧开始即可(对于视频(。如果这现在不起作用,我怀疑集群不是从关键帧开始的,或者它们有一些奇怪的地方。在JSON中,您显示一个音频流。。。这是故意的吗?

我建议阅读EBML,它本质上是Matroska/WebM的基本容器格式。Matroska只是EBML文档的一种模式。WebM只是Matroska,但被指定为一组核心编解码器。

所以,是的,总的来说,我认为你有这个概念,但它可以简化。

你可能会发现其他一些有用的东西:

  • https://stackoverflow.com/a/45172617/362536

最新更新