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

lae*_*des 5 javascript firefox wav html5-audio web-audio-api

我有一个网页,由于某些原因解码波形文件.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);
Run Code Online (Sandbox Code Playgroud)

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

编辑 感谢Michael Chaney的大量贡献,我能够实现一些处理wave的javascript,以便它可以在Firefox中播放.代码修剪了16个字节的"fmt"块的任何部分.代码位于: 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);
Run Code Online (Sandbox Code Playgroud)

谢谢迈克尔.

小智 5

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

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


Mic*_*ney 4

它可能是文件开头的垃圾块。您可以通过 sox 运行它来清除无关的块,如下所示:

sox Malice_Bass.wav Malice_Bass_simple.wav
Run Code Online (Sandbox Code Playgroud)

这是我的个人解析器对该文件的描述:

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)
Run Code Online (Sandbox Code Playgroud)

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