MediaRecorder 有什么办法在录制过程中动态添加/改变音频轨道吗?

361 天前
 qianzhu

我现在想实现一个需求:在录制前指定是否开启麦克风,在录制期间也可以开关麦克风。录制开始时,录制屏幕 + 选择的设备。

我的尝试:

方式一:先创建屏幕录制,然后在需要添加麦克风时 addTrack

  1. 先只创建屏幕录制,recorder
  2. 如果开启了麦克风,recorder.stream.addTrack(${audioTrack})
  3. 如果需要开启麦克风,使用上面同样的方式

代码大致如下:

const recorder = new MediaRecorder(
    new MediaStream([
        ...(await getUserScreenStream(this.id)).getVideoTracks()
    ])
)


// add audio track if needed
if (store.selectedAudioInput) {
	recorder.stream.addTrack((await getUserAudioStream(store.selectedAudioInput)).getAudioTracks()[0])
}

这种方式在 addTrack 调用时会自动触发 recorderstop 事件。也就是说如果我还继续想使用这个思路的话不可避免的需要考虑重新开启一个 recorder 然后将原来断的和新的 combine 一下。

方式二:使用 AudioContext 创建一个 MediaStream ,然后使用 MediaStream 去创建 recorder

  1. 根据 AudioContext 创建 mediaStreamAudioDestinationNode
  2. 根据 mediaStreamAudioDestinationNode.stream 中的音频和屏幕 stream 创建 recorder
  3. 如果开启了麦克风,使用 MediaStreamAudioSourceNode 对象去 connect mediaStreamAudioDestinationNode,从而实现 recorder 音频流的更新。
  4. 如果需要开启麦克风,使用上面同样的方式

但是这种方式有个问题。如果一开始创建时没有开启麦克风,也就是说没有 connect 音频流时 recorder 不会触发 ondataavailable 事件。也就是说没有正确的被录制。

而对于要实现的需求,一开始没有打开麦克风是有可能的。

大致代码如下:

this.audioContext = new AudioContext()
this.mediaStreamAudioDestinationNode = new MediaStreamAudioDestinationNode(this.audioContext)

const recorder = new MediaRecorder(
    new MediaStream([
        ...this.mediaStreamAudioDestinationNode.stream.getAudioTracks(),
        ...(await getUserScreenStream(this.id)).getVideoTracks()
    ])
)

// connect stream
if (store.selectedAudioInput) {
    const mediaStreamAudioSourceNode = new MediaStreamAudioSourceNode(this.audioContext, {
        mediaStream: await getUserAudioStream(devicesStore.selectedAudioInput)
    })

    mediaStreamAudioSourceNode.connect(this.mediaStreamAudioDestinationNode)
}

所以我的问题是,有没有什么简单的办法可以实现我的需求呢?目前这两种方式只有第一种可行,而在设计上感觉又不太合理。我还有一种想法是,将这两种流分开录制,最后再按照时间来进行合并。但是这样的工作量有点大。大家有什么解决思路或想法吗?

874 次点击
所在节点    JavaScript
2 条回复
chnwillliu
361 天前
换个思路,关闭麦克风音轨音量调成 0 ,打开再恢复行么?不一定要真的把 audioTrack 移除。

See GainNode
qianzhu
361 天前
@chnwillliu 哇,你好聪明!!非常感谢!我试试看!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/994607

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX