同时将音频和麦克风流录制为不同的 MediaRecorder 轨道
Record audio and microphone stream as different MediaRecorder tracks at the same time
我正在尝试记录用户对某些音频内容的响应(通过麦克风),这样我就可以以精确的方式分析用户对此音频的响应的客户端时间。理想情况下,我会沿着同一时间线录制两条轨道:(1) 来自用户的麦克风流; (2) 用户听到的音频流。
我对网络音频没有经验 API,但是使用以前的一些 SO 答案我得出了以下解决方案:我连接音频源 (source
) 和麦克风源 (stream
) 在单个流 (combinedStream
) 中,它被馈送到 MediaRecorder
.
我的问题:
这会录制 单个 轨道(即音频和麦克风信号必须使用 post 处理分开)。是否可以将它们录制到两个轨道中?例如粗略地作为立体声信号的两个通道?
我不清楚这是否是对延迟最敏感的方法,可能存在与连接流相关的开销,或者与实际音频播放相关的未捕获延迟客户端?任何建议将不胜感激 - 目前在音频源和播放之间有大约 10-20 毫秒的延迟(通过查看音频流和通过扬声器播放之间的延迟粗略测量,如麦克风流上拾取的那样)。
我不太了解HTML5音频,但也许有更好的解决方案?
谢谢!
...
// Audio for playback
var source = context.createBufferSource();
source.buffer = ...
source.connect(context.destination);
// Merge audio source with microphone stream
const mediaStreamDestination = audioContext.createMediaStreamDestination();
const sourceMic = jsPsych.pluginAPI.audioContext().createMediaStreamSource(stream);
sourceMic.connect(mediaStreamDestination);
source.connect(mediaStreamDestination);
let combinedStream = new MediaStream([...mediaStreamDestination.stream.getAudioTracks()]);
// Media recorder
mediaRecorder = new MediaRecorder(combinedStream);
mediaRecorder.ondataavailable = function(event) {
chunks.push(event.data);
};
...
看起来 MediaRecorder 不会这样做,至少 not in Chromium。
MediaSourceExtensions does allow control over the playing of multiple tracks from inside Matroska files. webm is a subset of Matroska. The current version of the webm standard does not allow multiple tracks. But MSE可以玩
可以想象您可以使用两个 MediaRecorder,然后使用 ebml 代码编写代码来破解两个 Matroska 容器并将它们组合成一个具有多个轨道的输出 Matroska 数据流。这是一项非常重要的编程任务。
要在两个不同的声道上录制两个不同的音频源(例如立体声文件中的左右声道),您可以使用 ChannelMergerNode。
基本上它与您的设置相同,不同之处在于当连接两个源时您将通过 connect( destination, input_channel, output_channel )
方法设置输出通道:
使用两个振荡器:
onclick = ()=>{
onclick = null;
const ctx = new AudioContext();
const osc1 = ctx.createOscillator();
const osc2 = ctx.createOscillator();
osc1.frequency.value = 300;
osc1.start(0);
osc2.start(0);
const merger = ctx.createChannelMerger();
const dest = ctx.createMediaStreamDestination();
merger.connect( dest );
osc1.connect( merger, 0, 0 );
osc2.connect( merger, 0, 1 );
// for nodes to output sound in Chrome
// they need to be connected to the destination
// ...
const mute = ctx.createGain();
mute.gain.value = 0;
mute.connect( ctx.destination );
osc1.connect( mute );
osc2.connect( mute );
const chunks = [];
const rec = new MediaRecorder( dest.stream );
rec.ondataavailable = e => chunks.push(e.data)
rec.onstop = e => {
output.src = URL.createObjectURL( new Blob( chunks ) );
};
rec.start();
setTimeout( () => rec.stop(), 5000 );
log.remove();
};
<p id="log">click to start recording of 5s sample</p>
<audio id="output" controls></audio>
我正在尝试记录用户对某些音频内容的响应(通过麦克风),这样我就可以以精确的方式分析用户对此音频的响应的客户端时间。理想情况下,我会沿着同一时间线录制两条轨道:(1) 来自用户的麦克风流; (2) 用户听到的音频流。
我对网络音频没有经验 API,但是使用以前的一些 SO 答案我得出了以下解决方案:我连接音频源 (source
) 和麦克风源 (stream
) 在单个流 (combinedStream
) 中,它被馈送到 MediaRecorder
.
我的问题:
这会录制 单个 轨道(即音频和麦克风信号必须使用 post 处理分开)。是否可以将它们录制到两个轨道中?例如粗略地作为立体声信号的两个通道?
我不清楚这是否是对延迟最敏感的方法,可能存在与连接流相关的开销,或者与实际音频播放相关的未捕获延迟客户端?任何建议将不胜感激 - 目前在音频源和播放之间有大约 10-20 毫秒的延迟(通过查看音频流和通过扬声器播放之间的延迟粗略测量,如麦克风流上拾取的那样)。
我不太了解HTML5音频,但也许有更好的解决方案?
谢谢!
...
// Audio for playback
var source = context.createBufferSource();
source.buffer = ...
source.connect(context.destination);
// Merge audio source with microphone stream
const mediaStreamDestination = audioContext.createMediaStreamDestination();
const sourceMic = jsPsych.pluginAPI.audioContext().createMediaStreamSource(stream);
sourceMic.connect(mediaStreamDestination);
source.connect(mediaStreamDestination);
let combinedStream = new MediaStream([...mediaStreamDestination.stream.getAudioTracks()]);
// Media recorder
mediaRecorder = new MediaRecorder(combinedStream);
mediaRecorder.ondataavailable = function(event) {
chunks.push(event.data);
};
...
看起来 MediaRecorder 不会这样做,至少 not in Chromium。
MediaSourceExtensions does allow control over the playing of multiple tracks from inside Matroska files. webm is a subset of Matroska. The current version of the webm standard does not allow multiple tracks. But MSE可以玩
可以想象您可以使用两个 MediaRecorder,然后使用 ebml 代码编写代码来破解两个 Matroska 容器并将它们组合成一个具有多个轨道的输出 Matroska 数据流。这是一项非常重要的编程任务。
要在两个不同的声道上录制两个不同的音频源(例如立体声文件中的左右声道),您可以使用 ChannelMergerNode。
基本上它与您的设置相同,不同之处在于当连接两个源时您将通过 connect( destination, input_channel, output_channel )
方法设置输出通道:
使用两个振荡器:
onclick = ()=>{
onclick = null;
const ctx = new AudioContext();
const osc1 = ctx.createOscillator();
const osc2 = ctx.createOscillator();
osc1.frequency.value = 300;
osc1.start(0);
osc2.start(0);
const merger = ctx.createChannelMerger();
const dest = ctx.createMediaStreamDestination();
merger.connect( dest );
osc1.connect( merger, 0, 0 );
osc2.connect( merger, 0, 1 );
// for nodes to output sound in Chrome
// they need to be connected to the destination
// ...
const mute = ctx.createGain();
mute.gain.value = 0;
mute.connect( ctx.destination );
osc1.connect( mute );
osc2.connect( mute );
const chunks = [];
const rec = new MediaRecorder( dest.stream );
rec.ondataavailable = e => chunks.push(e.data)
rec.onstop = e => {
output.src = URL.createObjectURL( new Blob( chunks ) );
};
rec.start();
setTimeout( () => rec.stop(), 5000 );
log.remove();
};
<p id="log">click to start recording of 5s sample</p>
<audio id="output" controls></audio>