【发布时间】:2017-03-11 18:39:58
【问题描述】:
我正在使用 AudioContext 的 decodeAudioData 方法在 Chrome、Firefox 和 Opera 中播放音频。所有浏览器都成功解码和播放使用 Firefox 录制的音频。但是当使用 Chrome 或 Opera 录制音频时,只有 Firefox 成功解码并播放。在 Chrome 或 Opera 中解码音频时出现以下错误:
Uncaught (in promise) DOMException: Unable to decode audio data.
我尝试实施此处提到的 Ladislav Nevery 建议的修复: decodeAudioData returning a null error
已实现的代码成功执行了他的建议(遍历缓冲区以在音频流中查找起点),但在 Chrome 中对 Firefox 录制的音频进行解码仍然失败。
知道解码失败的原因吗?
function syncStream(node){ // should be done by api itself. and hopefully will.
var buf8 = new Uint8Array(node.buf);
buf8.indexOf = Array.prototype.indexOf;
var i=node.sync, b=buf8;
while(1) {
node.retry++;
i=b.indexOf(0xFF,i); if(i==-1 || (b[i+1] & 0xE0 == 0xE0 )) break;
i++;
}
if(i!=-1) {
var tmp=node.buf.slice(i); //carefull there it returns copy
delete(node.buf); node.buf=null;
node.buf=tmp;
node.sync=i;
return true;
}
return false;
}
export function loadAudio(deckId) {
store.audioPlayerDomain.audioLoading = true;
let activeRecord = getActiveRecordByDeckId(deckId);
let path = `${deckId}/${activeRecord.id}`;
let context = getAudioContext();
let processFn = function(node){
return context.decodeAudioData(node.buf, function (decoded) {
return decoded;
},
function(){ // only on error attempt to sync on frame boundary
if(syncStream(node)){
return processFn(node);
};
});
};
return AudioPlayerWebAPI.default.getAudio(path, context)
.then((buffer) => {
let node = {};
node.buf=buffer;
node.sync=0;
node.retry=0;
return processFn(node);
}).then(function(decodedData) {
store.audioPlayerDomain.audio = decodedData;
store.audioPlayerDomain.audioLoading = false;
return true;
});
}
....
getAudio(path, context) {
return fetch(`/api/public/audio/${path}`)
.then(processResponse)
.then(function(response) {
if(response.message && response.message === 'non-existent'){
return null;
}else{
return response.arrayBuffer();
}
})
},
【问题讨论】:
-
为什么不使用
.decodeAudioData().then()而不是尝试从.decodeAudioData(callbackFunction)的回调函数版本返回一个值?callbackFunction是异步的,是吗? -
难道不值得从相反的方向解决这个问题,并弄清楚为什么 Chrome 以不同的格式记录以及如何改变它?您可能想使用
ffprobe检查您的文件格式。您还可以使用ffmpeg或基于云的解决方案(有几个)对您的文件进行转码,以确保它始终可以播放。
标签: javascript html web-audio-api