【问题标题】:Playing audio backwards with HTMLMediaElement使用 HTMLMediaElement 向后播放音频
【发布时间】:2015-03-24 16:55:59
【问题描述】:

我正在尝试在 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 事件。

【问题讨论】:

  • 这里似乎有相互矛盾的信息。 This page(在底部)声明 Negative values don't currently play the media backwards,但是 HTMLMediaElement docs 表示 If the playbackRate is negative, the media is played backwards
  • 那么这个规范是否还没有被大多数浏览器实现?
  • 好像是这样。这里有一个“解决方法”:stackoverflow.com/questions/16045812/…
  • 谢谢,不过看来这个解决方法只适用于视频,不适用于音频。

标签: javascript html audio streaming html5-audio


【解决方案1】:

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

请注意,这将需要启用 CORS 的音频源(示例中的音频源不是,因此我无法设置现场演示)。这是执行此操作的一种方法:

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

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

// 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)}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多