javascript - 播放媒体的 AudioContext 平移音频

标签 javascript html audio html5-video media-player

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

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

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

我已经使用 SoundTransform 类在 Flash 中实现了这个功能 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。

最佳答案

由于目前还没有一个公认的答案,我仍然想帮助你。起初,上面答案中的规划器节点不太可用,因为它根据 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 是关于 safari 兼容性的 not sure。遗憾的是,由于网络音频 API 的行为,没有解决方法。比方说源,它只有一个输出,但内部包含两个 channel 。没有其他方法可以拆分这些 channel (起初我想像 source.connect(gainL, 0, 0);source.connect(gainR, 1, 0); 但由于数字与输入/输出的数量相关,而不是与这些行内的 channel 相关,所以这不起作用。

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

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

关于javascript - 播放媒体的 AudioContext 平移音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20287890/

相关文章:

javascript - 如何在javascript中慢慢隐藏div

javascript - 属性未定义

javascript - 如何隐藏状态栏中的URL加载?

javascript - 移动 Chrome 上的粘性侧边菜单

javascript - Jquery,选择并滚动下一个元素

twitter-bootstrap - Bootstrap 3 - 响应式 mp3 音频

ios - 将 2 个音轨(同时运行)导出到一个文件 m4a)

javascript - 如何暂停页面上所有播放的音频

javascript - 在 knockout.js 中嵌套 foreach

javascript - 将 lat/lng 坐标转换为给定 map 上的像素(使用 JavaScript)