MediaSource API - 将多个视频附加/连接到一个缓冲区中
Posted
技术标签:
【中文标题】MediaSource API - 将多个视频附加/连接到一个缓冲区中【英文标题】:MediaSource API - append/concatenate multiple videos together into a single buffer 【发布时间】:2016-05-03 08:45:12 【问题描述】:更新:
所以我能够通过使用 offsetTimestamp 属性(在附加每个视频后递增它)来使其工作。
我现在的问题: 1) 为什么将 MediaSource.mode 设置为 sequence 时没有正确完成?
2) 为什么我的 MediaSource.duration 总是“无限”而不是正确的持续时间?
我正在尝试使用 MediaSource API 来附加多个视频文件并无缝播放它们,就像它是 1 个视频一样。
我已根据规范 (DASH-MPEG) 正确地对我的视频进行了转码,并且在单独播放它们时,它们可以正常工作。
但是,当我尝试追加多个时,我遇到了片段相互覆盖、持续时间不正确等问题。尽管一切似乎都按预期执行。
我尝试过使用 offsetTimestamp,但根据文档将 MediaSource.mode 设置为 'sequence' 应该会自动处理此问题。此外,由于某种原因,MediaSource.duration 似乎总是“无限”,即使在附加了一个片段之后也是如此。
这是我的代码:
<script>
function downloadData(url, cb)
console.log("Downloading " + url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function ()
cb(new Uint8Array(xhr.response));
;
xhr.send();
if (MediaSource.isTypeSupported('video/mp4; codecs="avc1.64001E"'))
console.log("mp4 codec supported");
var videoSources = [
"% static 'mp4/ff_97.mp4' %",
"% static 'mp4/ff_98.mp4' %",
"% static 'mp4/ff_99.mp4' %",
"% static 'mp4/ff_118.mp4' %"
]
var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', function(e)
var sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.64001E"');
sourceBuffer.mode = 'sequence';
console.log('SourceBuffer mode set to ' + sourceBuffer.mode);
sourceBuffer.addEventListener('updateend', function(e)
console.log('Finished updating buffer');
console.log('New duration is ' + String(mediaSource.duration));
if (videoSources.length == 0)
mediaSource.endOfStream();
video.currentTime = 0;
video.play();
return;
downloadData(videoSources.pop(), function(arrayBuffer)
console.log('Finished downloading buffer of size ' + String(arrayBuffer.length));
console.log('Updating buffer');
sourceBuffer.appendBuffer(arrayBuffer);
);
console.log('New duration: ' + String(mediaSource.duration));
);
downloadData(videoSources.pop(), function(arrayBuffer)
console.log('Finished downloading buffer of size ' + String(arrayBuffer.length));
console.log('Updating buffer');
sourceBuffer.appendBuffer(arrayBuffer);
);
, false);
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(mediaSource);
这里是日志:
mp4 codec supported
(index):78 SourceBuffer mode set to sequence
(index):45 Downloading /static/mp4/ff_118.mp4
(index):103 Finished downloading buffer of size 89107
(index):104 Updating buffer
(index):81 Finished updating buffer
(index):82 New duration is Infinity
(index):45 Downloading /static/mp4/ff_99.mp4
(index):98 New duration: Infinity
(index):92 Finished downloading buffer of size 46651
(index):93 Updating buffer
(index):81 Finished updating buffer
(index):82 New duration is Infinity
(index):45 Downloading /static/mp4/ff_98.mp4
(index):98 New duration: Infinity
(index):92 Finished downloading buffer of size 79242
(index):93 Updating buffer
(index):81 Finished updating buffer
(index):82 New duration is Infinity
(index):45 Downloading /static/mp4/ff_97.mp4
(index):98 New duration: Infinity
(index):92 Finished downloading buffer of size 380070
(index):93 Updating buffer
(index):81 Finished updating buffer
(index):82 New duration is Infinity
【问题讨论】:
【参考方案1】:2) 为什么我的 MediaSource.duration 总是“无限”而不是正确的持续时间?
您需要调用MediaSource.endOfStream()
以便MediaSource 对象计算其SourceBuffer
中段的实际持续时间。我看到您正在这样做,但看起来您在调用endOfStream()
之前尝试访问MediaSource.duration
。我建议您阅读 MSE 规范中的 end of stream algorithm,您会注意到它会导致调用 duration change algorithm。
如果您想让<video>
元素在调用MediaSource.endOfStream()
之前报告持续时间,您实际上可以设置一个值,使用MediaSource.duration
根据您自己对附加段的估计。 p>
1) 为什么将 MediaSource.mode 设置为 sequence 时没有正确完成?
据我所知,应该可以。但是我自己更喜欢显式的timestampOffset
方法,因为它在想要在缓冲区中很远的地方追加段时提供了更大的灵活性(即,如果用户在当前缓冲区结束之前寻找,你会想要开始加载+追加间隔后)。虽然我很感激在您的用例中寻求我不是一个要求。
【讨论】:
【参考方案2】:为什么将 MediaSource.mode 设置为 sequence 时没有正确完成?
您必须稍后在代码中执行此操作。具体什么时候?我不知道。当我在追加之前立即执行此操作时,它可以工作。
sourceBuffer.mode = 'sequence';
sourceBuffer.appendBuffer(chunk);
【讨论】:
以上是关于MediaSource API - 将多个视频附加/连接到一个缓冲区中的主要内容,如果未能解决你的问题,请参考以下文章
第一次后附加到 SourceBuffer 的 MediaSource 不起作用
将 FFMPEG 编码为 MPEG-DASH - 或带有关键帧集群的 WebM - 用于 MediaSource API