使用HTMLMediaElement向后播放音频

时间:2015-03-24 16:56:00

标签: javascript html5 audio streaming html5-audio

我正在尝试成功加载并播放Chrome中的音频文件,但我无法向后播放:

      audio = new Audio('http://mathweirdo.com/bingo/audio/buzzer.mp3');
      audio.playbackRate = -1;
      audio.currentTime = audio.duration; // I have tried ommiting this line
      audio.play()

这不会产生任何声音,只会发生一次timeupdate事件。

1 个答案:

答案 0 :(得分:6)

目前不支持使用负值,因此您必须手动加载和反转缓冲区。

请注意,这将需要启用CORS的音频源(示例中的音频源不是,所以我无法设置实时演示)。这是一种方法:

  • 通过AJAX加载数据(这需要为音频文件启用CORS)
  • 让浏览器将缓冲区解析为音频缓冲区
  • 获取频道缓冲区(参考)
  • 反转缓冲区
  • 初始化音频缓冲区并播放

这当然会限制你,因为你不能再使用Audio元素了。您必须通过手动添加控件和代码来支持所需的功能。

// load audio as a raw array buffer:
fetch("http://mathweirdo.com/bingo/audio/buzzer.mp3", process);

// then process the buffer using decoder
function process(file) {
  var actx = new (window.AudioContext || window.webkitAudioContext);
  actx.decodeAudioData(file, function(buffer) {

      var src = actx.createBufferSource(),      // enable using loaded data as source
          channel, tmp, i, t = 0, len, len2;

      // reverse channels
      while(t < buffer.numberOfChannels) {      // iterate each channel
        channel = buffer.getChannelData(t++);   // get reference to a channel
        len = channel.length - 1;               // end of buffer
        len2 = len >>> 1;                       // center of buffer (integer)
        for(i = 0; i < len2; i++) {             // loop to center
            tmp = channel[len - i];             // from end -> tmp
            channel[len - i] = channel[i];      // end = from beginning
            channel[i] = tmp;                   // tmp -> beginning
        }
      }

      // play
      src.buffer = buffer;
      src.connect(actx.destination);
      if (!src.start) src.start = src.noteOn;
      src.start(0);
    },
    function() {alert("Could not decode audio!")}
  )
}

// ajax loader
function fetch(url, callback) {
  var xhr = new XMLHttpRequest();
  try {
    xhr.open("GET", url);
    xhr.responseType = "arraybuffer";
    xhr.onerror = function() {alert("Network error")};
    xhr.onload = function() {
      if (xhr.status === 200) callback(xhr.response);
      else alert(xhr.statusText);
    };
    xhr.send();
  } catch (err) {alert(err.message)}
}