为什么某些.wav文件无法在Firefox中解码

时间:2014-10-02 21:07:15

标签: javascript firefox html5-audio wav web-audio

我有一个网页,由于某些原因解码波形文件。 Chrome和Safari似乎运行良好。 Firefox偶尔无法解码文件并提供错误:"传递给decodeAudioData的缓冲区包含无法成功解码的无效内容。"我创建了一个jsfiddle来说明问题:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
function getData() {
  source = audioCtx.createBufferSource();
  request = new XMLHttpRequest();
  request.open('GET', 'https://mpclubtest.s3.amazonaws.com/Malice_Bass.wav', true);
  request.responseType = 'arraybuffer';
  request.onload = function() {
    var audioData = request.response;
    audioCtx.decodeAudioData(audioData, function(buffer) {
        source.buffer = buffer;
        source.connect(audioCtx.destination);
      },
      function(e){"Error with decoding audio data" + e.err});
  }
  request.send();
}
getData();
source.start(0);

谁能告诉我这是什么问题,是否有办法绕过?非常感谢。

修改 感谢Michael Chaney的大量贡献,我能够实现一些处理wave的javascript,以便它可以在Firefox中播放。代码修剪了" fmt"的任何部分。超过16个字节的块。代码位于:jfiddle

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
function getData() {
  source = audioCtx.createBufferSource();
  request = new XMLHttpRequest();
  request.open('GET', 'https://mpclubtest.s3.amazonaws.com/Malice_Bass.wav', true);
  request.responseType = 'arraybuffer';
  request.onload = function() {
      var audioData = request.response;
      var dv = new DataView(audioData);
      var junk = 0;
      var position = 12;
      do {
          var header = String.fromCharCode.apply(null, Uint8Array(audioData, position, 4));
          var length = dv.getUint32(position + 4, true);
          if (header.trim() === 'fmt') {
              junk = junk + length - 16;
          }
          position = position + 8 + length;
      }while(position < audioData.byteLength);
      var productArray = new Uint8Array(audioData.byteLength - junk);
      productArray.set(new Uint8Array(audioData, 0, 12));
      var newPosition = 12;
      position = 12;
      var fmt_length_spot;
      do {
          var header = String.fromCharCode.apply(null, Uint8Array(audioData, position, 4));
          var length = dv.getUint32(position + 4, true);
          if (header.trim() === 'fmt') {
              productArray.set(new Uint8Array(audioData, position, 24), newPosition);
              fmt_length_spot = newPosition + 4;
              newPosition = newPosition + 24;
          }
          else {
              productArray.set(new Uint8Array(audioData, position, length + 8), newPosition);
              newPosition = newPosition + 8 + length;
          }
          position = position + 8 + length;
      }while(position < audioData.byteLength);
      audioData = productArray.buffer;
      dv = new DataView(audioData);
      dv.setUint32(4, audioData.byteLength - 8, true);
      dv.setUint32(fmt_length_spot, 16, true);
      audioCtx.decodeAudioData(audioData, function(buffer) {
          source.buffer = buffer;
          source.connect(audioCtx.destination);
        },
        function(e){"Error with decoding audio data" + e.err});
    }
    request.send();
}
getData();
source.start(0);

谢谢Michael。

3 个答案:

答案 0 :(得分:3)

它可能是文件开头的JUNK块。您可以通过sox运行它来清除这样的无关块:

sox Malice_Bass.wav Malice_Bass_simple.wav

以下是我的个人解析器对该文件的说法:

RIFF - WAVE (36467192 bytes)
   JUNK (92)
   bext (602)
         Description:       
         Originator:        Pro Tools
         Originator Ref:    jicj!dad1ofaaaGk
         Origination Date:  2014-09-09
         Origination Time:  20:46:43
         Time Ref Low:      0
         Time Ref High:     0
         BWF Version:       0
         SMPTE UMID Bytes:  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
         Coding History:    
   fmt (40)
         Format Tag:        1
         Channels:          2
         Samples per sec:   48000
         Avg bytes per sec: 192000
         Block align:       4
         Bits per sample:   16
   minf (16)
   elm1 (214)
   data (36466048)
   regn (92)
   umid (24)

当我使用sox Firefox清理它时,会退出抱怨,但仍然无法播放它。我确认它加载了文件,但似乎没有播放它。

答案 1 :(得分:2)

我最近遇到这个问题,Firefox没有使用浏览器的音频api读取wav文件,发现问题是音频文件的位深度不应超过16位才能被Firefox识别。我也发现这是一个8岁的Firefox“bug”,这是非常令人惊讶的(https://bugzilla.mozilla.org/show_bug.cgi?id=524109

我的灵魂是通过这样的sox命令行将32位深度的任何wav文件降级到16位:sox input.wav -b 16 output.wav。您显然可以使用ffmpeg或任何其他可以在Linux下执行此操作的应用程序。 希望有所帮助。

答案 2 :(得分:1)

该wav文件在前20秒内保持静音。我刚刚下载了它:

wget https://mpclubtest.s3.amazonaws.com/Malice_Bass.wav

我尝试使用镀铬而小提琴是沉默的,最初我想 因为我只是使用笔记本电脑扬声器。 使用大胆的FFT表示它在20秒静音后开始的频率非常低。

Web Audio API使用计算机的默认采样率,即 通常为44.1kHz由于文件使用的是48 kHz,因此是您的机器 配置48 kHz的宽松率?如果你重新采样48 kHz到44.1kHz的文件,这是典型计算机的采样率,它可能会有效。