MediaRecorder 有什么办法在录制过程中动态添加/改变音频轨道吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
qianzhu
V2EX    Javascript

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

  •  
  •   qianzhu 2023-11-23 17:14:13 +08:00 1291 次点击
    这是一个创建于 688 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    我的尝试:

    方式一:先创建屏幕录制,然后在需要添加麦克风时 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) } 

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

    2 条回复    2023-11-24 13:30:15 +08:00
    chnwillliu
        1
    chnwillliu  
       2023-11-24 03:59:48 +08:00 via Android
    换个思路,关闭麦克风音轨音量调成 0 ,打开再恢复行么?不一定要真的把 audioTrack 移除。

    See GainNode
    qianzhu
        2
    qianzhu  
    OP
       2023-11-24 13:30:15 +08:00
    @chnwillliu 哇,你好聪明!!非常感谢!我试试看!
    关于     帮助文档         博客     API     FAQ     Solana     1645 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 16:20 PVG 00:20 LAX 09:20 JFK 12:20
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86