【问题标题】:AudioContext panning audio of playing mediaAudioContext 平移播放媒体的音频
【发布时间】:2013-11-29 14:24:04
【问题描述】:

我想知道是否有办法使用 JavaScript 平移视频的音频。

与调节音量的方法相同,我需要从左到右或从右到左平移立体声音频。

此功能对于多语言活动非常有用,您可以使用立体声制作两种语言的视频,例如,将英语音频平移到左侧,将德语翻译平移到右侧。然后播放器可以根据用户的选择将立体声轨道转换为单声道静音其中一种语言。

我已经在 Flash 中使用 SoundTransform 类 http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/SoundTransform.html#pan 实现了这个功能。

我猜 SoundTransform html-equivalent 是 AudioContext http://www.w3.org/TR/webaudio/#AudioContext-section

我可以访问正在播放的视频的音频上下文吗?

更新:经过深入研究,我找到了解决方案。 这是我用来开发videojs插件videjs-stereopanner的一些javascript代码:

//Init AudioContext
var context = new AudioContext();
var gainL = context.createGainNode();
var gainR = context.createGainNode();
gainL.gain.value = 1;
gainR.gain.value = 1;
var merger = this.context.createChannelMerger(2);
var splitter = this.context.createChannelSplitter(2);

//Connect to source
var source = context.createMediaElementSource(node);
//Connect the source to the splitter
source.connect(splitter, 0, 0);
//Connect splitter' outputs to each Gain Nodes
splitter.connect(gainL, 0);
splitter.connect(gainR, 1);

//Connect Left and Right Nodes to the Merger Node inputs
//Assuming stereo as initial status
gainL.connect(merger, 0, 0);
gainR.connect(merger, 0, 1);

//Connect Merger output to context destination
merger.connect(context.destination, 0, 0);

//Disconnect left channel and connect right to both stereo outputs
var function = panToRight(){
    gainL.disconnect();
    gainR.connect(merger, 0, 1);
};

//Disconnect right channel and connect left to both stereo outputs
var function = panToLeft(){
    gainR.disconnect();
    gainL.connect(merger,0,0);
}

//Restore stereo
var function = panToStereo(){
    gainL.connect(merger, 0, 0);
    gainR.connect(merger, 0, 1);
}

这仅在 Chrome 中对我有用。如果我尝试在 iPad/Safari 上执行此脚本,我会听到令人讨厌的声音,几乎让我耳聋。我正在等待 Safari 实现整个音频 API。

【问题讨论】:

    标签: javascript html audio html5-video media-player


    【解决方案1】:

    由于对此还没有公认的答案,我仍想为您提供帮助。首先,上面答案中的规划器节点不太好用,因为它根据(另一个)方向的 3 维位置、方向和速度来计算体积和平移。正如 Mantiur 已经说过的,您可以使用 channelSplitter 来获得所需的结果。你可以这样设置:

    var element = document.getElementById('player');
    Var source = context.createMediaElementSource(element);
    var splitter = context.createSplitter(2);
    source.connect(splitter);
    var left = context.createGain();
    var right = context.createGain();
    splitter.connect(left);
    splitter.connect(right);
    

    您现在可以将左侧或右侧节点连接到context.destination,具体取决于用户需要哪一个。 请记住,只有 chrome 和 Firefox 支持网络音频 api。

    更新的答案:(更新的问题)

    您的代码看起来不错,但将左右的增益设置为 0 或 1 比断开和连接它们要好得多。对于当前问题,您将遇到单耳问题,但是您最好不要使用合并,而只是将音频直接推送到目的地(或通过额外的增益节点来设置最终音量。另请注意,您的代码可能在 chrome 上工作,但在我使用的版本上不起作用,因为在 context.createGain()context.createGainNode() 中存在命名问题。official document 使用 .createGain,所以我们最好坚持下去并创建一个后备:

    context.createGain = context.createGain||context.createGainNode;
    

    可能解决了 iOS 设备中的问题,因为我们在那里 should be able to use 这个。尽管 MDN 是 not sure 关于 safari 的兼容性。遗憾的是,由于网络音频 API 的行为,没有解决方法。假设源,它只有一个输出,但内部包含两个通道。没有其他方法可以拆分这些通道(一开始我在想source.connect(gainL, 0, 0);source.connect(gainR, 1, 0); 但这不起作用,因为数字与输入/输出的数量有关,而不是与那些里面的通道有关行)。

    所以我建议把代码改成这样:

    //Init AudioContext
    window.audioContext = window.audioContext||window.webkitAudioContext; //fallback for older chrome browsers
    var context = new AudioContext();
    context.createGain = context.createGain||context.createGainNode; //fallback for gain naming
    var gainL = context.createGain();
    var gainR = context.createGain();
    
    var splitter = this.context.createChannelSplitter(2);
    
    //Connect to source
    var source = context.createMediaElementSource(audioElement);
    //Connect the source to the splitter
    source.connect(splitter, 0, 0);
    //Connect splitter' outputs to each Gain Nodes
    splitter.connect(gainL, 0);
    splitter.connect(gainR, 1);
    
    //Connect Left and Right Nodes to the output
    //Assuming stereo as initial status
    gainL.connect(context.destination, 0);
    gainR.connect(context.destination, 0);
    
    
    //Mute left channel and set the right gain to normal
    function panToRight(){
        gainL.gain.value = 0;
        gainR.gain.value = 1;
    }
    
    //Mute right channel and set the left gain to normal
    function panToLeft(){
        gainL.gain.value = 1;
        gainR.gain.value = 0;
    }
    
    //Restore stereo
    function panToStereo(){
        gainL.gain.value = 1;
        gainR.gain.value = 1;
    }
    

    哦,顺便说一句,var function = funcName(){} 不是有效的 javascript(你是否使用了一些改变这种行为的 API)?

    【讨论】:

    • 谢谢@MarijnS95,这几乎就是我想要的。我更新了我的问题,添加了一些关于我最终遇到的解决方案的详细信息。
    • @cgcladera 我更新了问题,包括对 iOS 问题的“答案”,尽管我不确定。
    • 哇!再次感谢@MarijnS95!我将从底部开始:是的,我从 API 中提取了代码示例,因此对于格式不正确深表歉意。其次,我连接和断开通道是有原因的。当我向右或向左平移时,我希望能够在两个扬声器中收听音频。那是因为我将此功能用于多语言现场活动,并且我们允许制作人使用左右来同时流式传输两种语言。因此,我希望用户感觉他们可以切换语言而不是左右平移音频。
    • 就在我发表评论后,我尝试了您的代码并看到了您的意思,真可惜!抱歉 :( 顺便说一句,我仍然遇到 Mac/iOS Safari 的问题。代码不起作用。虽然 Safari 不会触发异常或错误,但它的行为并不符合预期。
    • @cgcladera 我正在考虑使用buffers (great example),但当然你正在使用视频。您是否有机会将视频与音频分开? (仍然很难同步声音)。所以 Mantriur 在这一点上是对的,实施还没有完成,而且很难达到预期的结果。我还有几个小时就要考试了,但在那之后我可能会想出一些东西。
    【解决方案2】:

    我在尝试为游戏构建的一个页面上添加了环境音频。这是我稍后将在整个游戏中用于某些声音效果的平移实验。花了很长时间才意识到createStereoPanner 有这么好的东西,它显着简化了整个过程。我用视频对其进行了测试,效果也一样。

    var ambientAudio = new Audio('./ambientVideo.mp4');
    
    document.addEventListener('keydown', ambientAudioControl)
    function ambientAudioControl(e) {
      if (e.keyCode === 37) panToLeft()
      if (e.keyCode === 39) panToRight()
      if (e.keyCode === 40) panToStereo()
    }
    
    const ambientContext = new AudioContext();
    const source = ambientContext.createMediaElementSource(ambientAudio);
    const ambientPan = ambientContext.createStereoPanner()
    
    function panToLeft(){ ambientPan.pan.value = -1 }
    function panToRight(){ ambientPan.pan.value = 1 }
    function panToStereo(){ ambientPan.pan.value = 0 }
    
    source.connect(ambientPan)
    ambientPan.connect(ambientContext.destination)
    ambientAudio.play()

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 2016-02-15
    • 1970-01-01
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多