为什么Safari或Firefox不能处理来自MediaElementSource的音频数据?

12

使用Web Audio API,Safari和Firefox均无法处理MediaElementSource的音频数据。

var audioContext, audioProcess, audioSource,
    result = document.createElement('h3'),
    output = document.createElement('span'),
    mp3 = '//www.jonathancoulton.com/wp-content/uploads/encodes/Smoking_Monkey/mp3/09_First_of_May_mp3_3a69021.mp3',
    ogg = '//upload.wikimedia.org/wikipedia/en/4/45/ACDC_-_Back_In_Black-sample.ogg',
    gotData = false, data, audio = new Audio();
 
function connect() {
  audioContext = window.AudioContext ? new AudioContext() : new webkitAudioContext(),
  audioSource  = audioContext.createMediaElementSource( audio ),
  audioScript  = audioContext.createScriptProcessor( 2048 );
 
  audioSource.connect( audioScript );
  audioSource.connect( audioContext.destination );
  audioScript.connect( audioContext.destination );
  audioScript.addEventListener('audioprocess', function(e){
    if ((data = e.inputBuffer.getChannelData(0)[0]*3)) {
      output.innerHTML = Math.abs(data).toFixed(3);
      if (!gotData) gotData = true;
    }
  }, false);
}
 
(function setup(){
  audio.volume = 1/3;
  audio.controls = true;
  audio.autoplay = true;
  audio.src = audio.canPlayType('audio/mpeg') ? mp3 : ogg;
  audio.addEventListener('canplay', connect);
  result.innerHTML = 'Channel Data: ';
  output.innerHTML = '0.000';
  document.body.appendChild(result).appendChild(output);
  document.body.appendChild(audio);
})();

近期是否有计划修补这个问题?或者是否有一些方法仍然可以为用户提供音频控件?对于苹果,是否可以在WebKit Nightlies中解决这个问题?还是我们必须等到Safari 8.0发布才能使HTML5的<audio>与Web Audio API良好地配合?自Safari 6.0以来,Web Audio API已经存在于Safari中,而我最初发布了这个问题是在Safari 7.0发布之前很久。有没有原因说明为什么还没有被修复?它会被修复吗?对于Mozilla,我知道你们仍在从旧的Audio Data API转换,但这是否是您的Web Audio实现中已知的问题,并且在Firefox下一个版本发布之前将得到修复?


<audio>已经播放了吗?iOS延迟加载<audio><video>,直到某些用户操作提示它们开始,因此也许问题是您想要使用的audioElement没有被加载。 - apsillers
这就是 audioElement.readyState < 3 ? audioElement.addEventListener('canplay', connect) : connect(); 的作用。虽然iOS也遇到了同样的bug,但我特别想知道桌面版本。 - idbehold
你能详细说明一下它是如何“失败”的吗?是否会产生错误消息,或者“onaudioprocess”回调函数根本没有运行? - Matt Diamond
@MattDiamond 我在帖子中链接了测试用例:http://jsfiddle.net/2cd73/ 音频播放,但是 ScriptProcessor 没有接收到除 0 值以外的任何内容。 - idbehold
2个回答

5
这个答案几乎完全引用了我对相关问题的回答:Firefox 25和AudioContext createJavaScriptNote不是函数

如果媒体遵守同源策略,Firefox确实支持MediaElementSource,但是当尝试使用来自远程源的媒体时,Firefox不会产生错误。

规范并没有真正说明这一点(意在双关),但我被告知这是一种预期行为,问题实际上出在Chrome上……Blink实现(Chrome,Opera)需要更新以要求CORS

MediaElementSource节点和跨域媒体资源

发件人: Robert O'Callahan <robert@ocallahan.org>
日期: 2013年7月23日 下午4:30
收件人: "public-audio@w3.org" <public-audio@w3.org>

HTML媒体元素可以播放来自任何来源的媒体资源。当元素从与页面不同的来源播放媒体资源时,我们必须防止页面脚本能够读取媒体内容(例如提取视频帧或音频样本)。特别是,我们应该防止ScriptProcessorNodes访问媒体的音频样本。我们还应该防止有关样本泄漏的其他方式(例如时间通道攻击)。目前Web Audio规范没有对此做出任何说明。

我认为我们应该通过防止任何非同源数据进入Web Audio来解决这个问题。这将最小化攻击面和对Web Audio的影响。

我的建议是使MediaElementAudioSourceNode将来自非同源流的数据转换为静音。

如果这个提案被纳入规范中,开发者几乎不可能意识到为什么他的MediaElementSource无法工作。目前的情况是,在Firefox 26中调用createMediaElementSource()<audio>元素上实际上会完全停止<audio>控件的工作,并且不会抛出任何错误。
从远程来源获取音频/视频数据有哪些危险?一般的想法是,如果未将同源策略应用于MediaElementSource节点,则一些恶意JavaScript可以访问用户应该拥有的媒体(会话、VPN、本地服务器、网络驱动器)并将其内容或某些表示发送给攻击者。
HTML5媒体元素默认没有这些限制。您可以通过使用<audio><img><video>元素在所有浏览器中包含远程媒体。只有当您想要操作或提取这些远程资源的数据时,同源策略才会起作用。
“这是因为同样的原因,你不能通过<canvas>跨域转储图像数据:媒体可能包含敏感信息,因此允许恶意站点转储和重新路由内容会带来安全问题。” - @nmaier

1
那么在Safari上处理音频数据我们还是束手无策吗? - Cabbibo
有一个 Firefox 的 bug,即使应该可以工作,它似乎也会阻止它的正常运行:https://bugzilla.mozilla.org/show_bug.cgi?id=937718 - aldel
这个例子的 jsfiddle(http://jsfiddle.net/9eGSp/1/)现在似乎在 Firefox 34 中可以正常工作(播放音频)。也许这个 bug 已经被修复了?有人知道吗? - Jordan Eldredge

1

createMediaElementSource()在Safari 8.0.5(可能还有更早的版本)中无法正常工作,但在Webkit Nightly 10600.5.17,r183978中已修复。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接