javascript - decodeAudioData - Unable to decode audio data - Stack Overflow

I am using AudioContext's decodeAudioData method to play back audio in Chrome, Firefox, and Opera.

I am using AudioContext's decodeAudioData method to play back audio in Chrome, Firefox, and Opera. All browsers successfully decode and play audio that was recorded using Firefox. But when the audio was recorded using Chrome or Opera, only Firefox successfully decodes and plays it back. I get the following error when decoding the audio in Chrome or Opera:

Uncaught (in promise) DOMException: Unable to decode audio data.    

I attempted to implement Ladislav Nevery's suggested fix mentioned here: decodeAudioData returning a null error

The implemented code executes his suggestion successfully (traversing through the buffer to find start points in the audio stream), but the decoding still fails in Chrome for the Firefox-recorded audio.

Any ideas why decoding is failing?

    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();
        }
      })
    },

I am using AudioContext's decodeAudioData method to play back audio in Chrome, Firefox, and Opera. All browsers successfully decode and play audio that was recorded using Firefox. But when the audio was recorded using Chrome or Opera, only Firefox successfully decodes and plays it back. I get the following error when decoding the audio in Chrome or Opera:

Uncaught (in promise) DOMException: Unable to decode audio data.    

I attempted to implement Ladislav Nevery's suggested fix mentioned here: decodeAudioData returning a null error

The implemented code executes his suggestion successfully (traversing through the buffer to find start points in the audio stream), but the decoding still fails in Chrome for the Firefox-recorded audio.

Any ideas why decoding is failing?

    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();
        }
      })
    },
Share Improve this question edited May 23, 2017 at 11:54 CommunityBot 11 silver badge asked Mar 11, 2017 at 18:39 Jacob MyersJacob Myers 331 gold badge1 silver badge6 bronze badges 2
  • Why do you not use .decodeAudioData().then() instead of trying to return a value from callback function version of .decodeAudioData(callbackFunction)? callbackFunction is asynchronous, yes? – guest271314 Commented Mar 11, 2017 at 18:49
  • Wouldn't it be worth tackling this from the opposite direction and figure out why Chrome records in a different format and how to change that? You might want to luse ffprobe to check your file format. You can also use ffmpeg or a cloud based solution (there are several) to trans-code your file to make sure that it is always playable. – Marc Rohloff Commented Mar 11, 2017 at 23:13
Add a ment  | 

1 Answer 1

Reset to default 3

Until very recently, decodeAudioData could not decode the result of Chrome's MediaRecorder. Try a Chrome canary or beta to see if this is fixed. If you still have a problem, provide a more plete (but simple) example of what's not working.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745042867a4607917.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信