使用媒体源扩展 API 时的视频 'Stuck'
Video 'Stuck' when using Media Source Extension API
我使用媒体源 API 使我自己的实现工作时运气不佳。
我只是想看看一个工作示例是否可以在本地正常工作,所以我复制并粘贴了示例中的源代码:
http://html5-demos.appspot.com/static/media-source.html
来源:
查看源代码:http://html5-demos.appspot.com/static/media-source.html
我没有 'test.webm' 视频,所以我可以使用自己的 .webm 视频文件。
我使用的测试文件是.webm 视频文件 14.6m
结果是它的工作方式并不完全相同。
检查控制台我可以看到有一些错误,所以我添加了一个队列来收集视频块,同时来自媒体源的 sourceBuffer 正在更新。
这有助于修复错误,我可以看到视频已完全加载到播放器上,但问题是视频从未开始播放。只是显示视频时长的黑屏。
如果我手动将它移动到 1 秒的开始点,它会一直播放到结束。我假设这意味着实施工作正常。在黑屏时检查视频的 video.paused bool 也会返回错误。目前不确定这是否只是 html 视频的问题。
这是我对示例脚本的更新:
<script>
var FILE = 'test.webm';
// var FILE = 'perigny.mp4';
var NUM_CHUNKS = 10;
var video = document.querySelector('video');
finished = false;
window.MediaSource = window.MediaSource || window.WebKitMediaSource;
if (!!!window.MediaSource) {
alert('MediaSource API is not available');
}
var mediaSource = new MediaSource();
video.src = window.URL.createObjectURL(mediaSource);
function callback(e) {
console.log("video.paused: ", video.paused);
var sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');
// sourceBuffer = mediaSource.addSourceBuffer('video/mp4;codecs="avc1.4d001e"');
queue = [];
sourceBuffer.addEventListener('updatestart',
function(e) { console.error('updatestart: ' + mediaSource.readyState);});
sourceBuffer.addEventListener('update',
function(e) {
console.log('update: ' + mediaSource.readyState);
});
sourceBuffer.addEventListener('updateend', function() { // Note: Have tried 'updateend'
console.log('updateend: ' + mediaSource.readyState);
if (queue.length > 0 && !sourceBuffer.updating) {
console.error("queue.shift");
// if (queue.length) {
sourceBuffer.appendBuffer(queue.shift());
}
if (finished && !sourceBuffer.updating) {
console.log("finished");
mediaSource.endOfStream();
console.log("MediaSource", mediaSource);
console.log("video.paused: ", video.paused);
video.pause();
video.play();
}
}, false);
logger.log('mediaSource readyState: ' + this.readyState);
GET(FILE, function(uInt8Array) {
var file = new Blob([uInt8Array], {type: 'video/webm'});
var chunkSize = Math.ceil(file.size / NUM_CHUNKS);
logger.log('num chunks:' + NUM_CHUNKS);
logger.log('chunkSize:' + chunkSize + ', totalSize:' + file.size);
// Slice the video into NUM_CHUNKS and append each to the media element.
var i = 0;
(function readChunk_(i) {
var reader = new FileReader();
// Reads aren't guaranteed to finish in the same order they're started in,
// so we need to read + append the next chunk after the previous reader
// is done (onload is fired).
reader.onload = function(e) {
console.log("i", i);
if (sourceBuffer.updating || queue.length > 0) {
console.log("addSourceBuffer is updating");
queue.push(new Uint8Array(e.target.result));
}
else {
console.log("sourceBuffer.appendBuffer();");
sourceBuffer.appendBuffer(new Uint8Array(e.target.result));
}
logger.log('appending chunk:' + i);
if (i == NUM_CHUNKS - 1) {
console.log("End of stream");
finished = true;
// if (!sourceBuffer.updating)
// mediaSource.endOfStream();
} else {
if (video.paused) {
video.play(); // Start playing after 1st chunk is appended.
}
readChunk_(++i);
}
};
var startByte = chunkSize * i;
var chunk = file.slice(startByte, startByte + chunkSize);
reader.readAsArrayBuffer(chunk);
})(i); // Start the recursive call by self calling.
});
}
mediaSource.addEventListener('sourceopen', callback, false);
mediaSource.addEventListener('webkitsourceopen', callback, false);
mediaSource.addEventListener('sourceended', function(e) {
logger.log('mediaSource readyState: ' + this.readyState);
}, false);
function GET(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.send();
xhr.onload = function(e) {
if (xhr.status != 200) {
alert("Unexpected status code " + xhr.status + " for " + url);
return false;
}
callback(new Uint8Array(xhr.response));
};
}
</script>
编辑:希望帮助可能遇到此问题的其他人,让我添加 solution/outcome。
事实证明这是我尝试使用的原始 .webm 视频文件的关键框架问题。似乎 MSE API 非常挑剔,即使它是它需要的确切文件格式。
我最终从以下位置下载了 .webm 视频:
http://techslides.com/sample-webm-ogg-and-mp4-video-files-for-html5
我现在打算继续使用这些其他文件格式。
不要从 HTML 页面获取代码,从 Github 下载整个项目:https://github.com/dazedsheep/DASH-JS.
确保将它放在 localhost/dash 下可以调用的地方。
您必须确保目录 "bunny_2s_700kbit" 中有您必须从此处下载的媒体文件:
http://www-itec.uni-klu.ac.at/ftp/datasets/mmsys12/BigBuckBunny/bunny_2s_480p_only/bunny_2s_700kbit/
然后确保 bigbuckbunny_mp.mpd:
中的路径正确
<BaseURL>http://localhost/dash/</BaseURL>
和
<Initialization sourceURL="bunny_2s_700kbit/bunny_480_700kbit_dash.mp4"/>
和 dashtest.html 中的正确路径:
var dashPlayer = new DASHPlayer(video,"bigbuckbunny_mp.mpd");
我使用媒体源 API 使我自己的实现工作时运气不佳。
我只是想看看一个工作示例是否可以在本地正常工作,所以我复制并粘贴了示例中的源代码: http://html5-demos.appspot.com/static/media-source.html
来源: 查看源代码:http://html5-demos.appspot.com/static/media-source.html
我没有 'test.webm' 视频,所以我可以使用自己的 .webm 视频文件。 我使用的测试文件是.webm 视频文件 14.6m
结果是它的工作方式并不完全相同。 检查控制台我可以看到有一些错误,所以我添加了一个队列来收集视频块,同时来自媒体源的 sourceBuffer 正在更新。
这有助于修复错误,我可以看到视频已完全加载到播放器上,但问题是视频从未开始播放。只是显示视频时长的黑屏。
如果我手动将它移动到 1 秒的开始点,它会一直播放到结束。我假设这意味着实施工作正常。在黑屏时检查视频的 video.paused bool 也会返回错误。目前不确定这是否只是 html 视频的问题。
这是我对示例脚本的更新:
<script>
var FILE = 'test.webm';
// var FILE = 'perigny.mp4';
var NUM_CHUNKS = 10;
var video = document.querySelector('video');
finished = false;
window.MediaSource = window.MediaSource || window.WebKitMediaSource;
if (!!!window.MediaSource) {
alert('MediaSource API is not available');
}
var mediaSource = new MediaSource();
video.src = window.URL.createObjectURL(mediaSource);
function callback(e) {
console.log("video.paused: ", video.paused);
var sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');
// sourceBuffer = mediaSource.addSourceBuffer('video/mp4;codecs="avc1.4d001e"');
queue = [];
sourceBuffer.addEventListener('updatestart',
function(e) { console.error('updatestart: ' + mediaSource.readyState);});
sourceBuffer.addEventListener('update',
function(e) {
console.log('update: ' + mediaSource.readyState);
});
sourceBuffer.addEventListener('updateend', function() { // Note: Have tried 'updateend'
console.log('updateend: ' + mediaSource.readyState);
if (queue.length > 0 && !sourceBuffer.updating) {
console.error("queue.shift");
// if (queue.length) {
sourceBuffer.appendBuffer(queue.shift());
}
if (finished && !sourceBuffer.updating) {
console.log("finished");
mediaSource.endOfStream();
console.log("MediaSource", mediaSource);
console.log("video.paused: ", video.paused);
video.pause();
video.play();
}
}, false);
logger.log('mediaSource readyState: ' + this.readyState);
GET(FILE, function(uInt8Array) {
var file = new Blob([uInt8Array], {type: 'video/webm'});
var chunkSize = Math.ceil(file.size / NUM_CHUNKS);
logger.log('num chunks:' + NUM_CHUNKS);
logger.log('chunkSize:' + chunkSize + ', totalSize:' + file.size);
// Slice the video into NUM_CHUNKS and append each to the media element.
var i = 0;
(function readChunk_(i) {
var reader = new FileReader();
// Reads aren't guaranteed to finish in the same order they're started in,
// so we need to read + append the next chunk after the previous reader
// is done (onload is fired).
reader.onload = function(e) {
console.log("i", i);
if (sourceBuffer.updating || queue.length > 0) {
console.log("addSourceBuffer is updating");
queue.push(new Uint8Array(e.target.result));
}
else {
console.log("sourceBuffer.appendBuffer();");
sourceBuffer.appendBuffer(new Uint8Array(e.target.result));
}
logger.log('appending chunk:' + i);
if (i == NUM_CHUNKS - 1) {
console.log("End of stream");
finished = true;
// if (!sourceBuffer.updating)
// mediaSource.endOfStream();
} else {
if (video.paused) {
video.play(); // Start playing after 1st chunk is appended.
}
readChunk_(++i);
}
};
var startByte = chunkSize * i;
var chunk = file.slice(startByte, startByte + chunkSize);
reader.readAsArrayBuffer(chunk);
})(i); // Start the recursive call by self calling.
});
}
mediaSource.addEventListener('sourceopen', callback, false);
mediaSource.addEventListener('webkitsourceopen', callback, false);
mediaSource.addEventListener('sourceended', function(e) {
logger.log('mediaSource readyState: ' + this.readyState);
}, false);
function GET(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.send();
xhr.onload = function(e) {
if (xhr.status != 200) {
alert("Unexpected status code " + xhr.status + " for " + url);
return false;
}
callback(new Uint8Array(xhr.response));
};
}
</script>
编辑:希望帮助可能遇到此问题的其他人,让我添加 solution/outcome。
事实证明这是我尝试使用的原始 .webm 视频文件的关键框架问题。似乎 MSE API 非常挑剔,即使它是它需要的确切文件格式。 我最终从以下位置下载了 .webm 视频: http://techslides.com/sample-webm-ogg-and-mp4-video-files-for-html5
我现在打算继续使用这些其他文件格式。
不要从 HTML 页面获取代码,从 Github 下载整个项目:https://github.com/dazedsheep/DASH-JS.
确保将它放在 localhost/dash 下可以调用的地方。
您必须确保目录 "bunny_2s_700kbit" 中有您必须从此处下载的媒体文件: http://www-itec.uni-klu.ac.at/ftp/datasets/mmsys12/BigBuckBunny/bunny_2s_480p_only/bunny_2s_700kbit/
然后确保 bigbuckbunny_mp.mpd:
中的路径正确<BaseURL>http://localhost/dash/</BaseURL>
和
<Initialization sourceURL="bunny_2s_700kbit/bunny_480_700kbit_dash.mp4"/>
和 dashtest.html 中的正确路径:
var dashPlayer = new DASHPlayer(video,"bigbuckbunny_mp.mpd");