使用 HTMLMediaElement 向后播放音频

Posted

技术标签:

【中文标题】使用 HTMLMediaElement 向后播放音频【英文标题】:Playing audio backwards with 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 那么这个规范是否还没有被大多数浏览器实现? 好像是这样。这里有一个“解决方法”:***.com/questions/16045812/… 谢谢,不过看来这个解决方法只适用于视频,不适用于音频。 【参考方案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)

【讨论】:

以上是关于使用 HTMLMediaElement 向后播放音频的主要内容,如果未能解决你的问题,请参考以下文章

使用AVAudioPlayer播放音乐文件无声音

播放提示音(与默认消息铃声相同)

在android中播放音轨中的音频

抖音怎么小窗口播放

AVQueuePlayer 在 iOS5 后台播放多个音轨

仿抖音上下滑动播放视频