我正在开发一个Web应用程序,其中应用程序下载加密的数据块。然后我必须解密并播放视频。但我不能让用户等待所有解密。因此我正在使用Media Stream API。这是工作。但是在解密最后一个块之后我收到了这个错误。
“未捕获DOMException:无法在'MediaSource'上执行'addSourceBuffer':此MediaSource已达到它可以处理的SourceBuffer对象的限制。不能添加其他SourceBuffer对象。(...)”
<script type="text/javascript">
//////////
var no_of_files = 0;
var no_of_dlfiles = 0;
var FilesURL = [];
var files_str = 'video/vid_1.webm, video/vid_2.webm, video/vid_3.webm, video/vid_4.webm, video/vid_5.webm';
var file_counter = 0;
var mimeCodec = 'video/webm; codecs="vorbis,vp8"';
var passkey = "014bcbc0e15c4fc68b098f9b16f62bb7shahbaz.hansinfotech@gmail.com";
FilesURL = files_str.split(',');
no_of_files = FilesURL.length;
var player = document.getElementById('videoplayer');
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
player.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
//////////
function sourceOpen (_) {
console.log("start");
var mediaSource = this;
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
sourceBuffer.mode = "sequence";
function WriteDatatoTemp()
{
//console.log(this.readyState); // open
if(file_counter<FilesURL.length)
{
console.log(file_counter);
no_of_dlfiles++;
$("#decryptionRatio").text(no_of_dlfiles+" of "+no_of_files);
$("#decryption_status").show();
getFileObject(FilesURL[file_counter], function (fileObject) {
//
var outputFile = fileObject;
var reader = new FileReader();
reader.onloadend = function(e){
var decrypted_data = JSON.parse(CryptoJS.AES.decrypt(e.target.result, passkey, {format: CryptoJSAesJson}).toString(CryptoJS.enc.Utf8));
var byteArray = Base64Binary.decodeArrayBuffer(decrypted_data);
sourceBuffer.addEventListener('updateend', function(){
file_counter++;
// console.log(file_counter);
if(player.paused)
{
player.play();
}
if(file_counter == FilesURL.length - 1)
{
mediaSource.endOfStream();
}
WriteDatatoTemp();
});
try
{
while(!sourceBuffer.updating)
{
sourceBuffer.appendBuffer(byteArray);
}
}
catch(e)
{
console.log(e);
}
};
reader.readAsText(outputFile);
//
});
}
}
WriteDatatoTemp();
}
///
var getFileBlob = function (url, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "blob";
xhr.addEventListener('load', function() {
cb(xhr.response);
});
xhr.send();
};
var blobToFile = function (blob, name) {
blob.lastModifiedDate = new Date();
blob.name = name;
return blob;
};
var getFileObject = function(filePathOrUrl, cb) {
getFileBlob(filePathOrUrl, function (blob) {
cb(blobToFile(blob, 'vid.webm'));
});
};
</script>
答案 0 :(得分:0)
SourceBuffer.appendBufferAsync()
是返回Promise实例的函数。
您可以将await
与as一起使用,以允许附加过程结束其工作。由于出现错误,是因为在追加过程结束之前调用了另一个appendBuffer()
。
但是不幸的是,此过程仅在少数浏览器中可用(并且Chrome DESKTOP不是其中之一):-appendBufferAsync mdn
在Firefox上,您可以将其与media.mediasource.experimental.enabled = true
此解决方案Kida在嵌入Flutter App的音乐应用中与我合作,因为在这里我可以确保系统在Chrome移动版上运行。
如果您找到了可靠的解决方案,请更新,我了解我的解决方案不适合生产
在视频流中,我做了类似的操作,就像您在评论中提到的那样,但是我添加了2个视频元素,而其中一个的ObjectURL正在准备播放,另一个正在播放,反之亦然。为了防止黑屏,我只是将视频流的片段绘制到画布上,在每次流转换过程中,音频中特别明显的延迟仍然很少,但是与仅用一个视频所能做的相比,平滑得多元素。
不幸的是,即使有十多年了,MediaSource上也没有令人满意的文档。