AudioContext平移播放媒体的音频

时间:2013-11-29 14:24:05

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

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

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

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

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

我认为SoundTransform与html相当的是AudioContext http://www.w3.org/TR/webaudio/#AudioContext-section

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

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

//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实现整个Audio API。

2 个答案:

答案 0 :(得分:4)

由于还没有接受这个答案,我还是想帮助你。首先,来自上面答案的计划者节点不能很好地使用,因为它根据(另一)方向上的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,所以我们' d更好地坚持并创造一个后备:

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

可能会修复iOS设备中的问题,因为我们should be able to use就是这样。尽管MDN对于Safari的兼容性是not sure。遗憾的是,由于Web音频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;
}

哦,btw var function = funcName(){}无效javascript(你使用的是一些改变这种行为的API)吗?

答案 1 :(得分:1)

我在我试图为游戏构建的一个页面上添加了环境音频。这是我对平移的实验,我稍后会在整个游戏中使用某些声音效果。永远意识到有这个好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()