ShareX 多音轨录制:从单源到多源的代码改造
【免费下载链接】ShareXShareX is a free and open-source application that enables users to capture or record any area of their screen with a single keystroke. It also supports uploading images, text, and various file types to a wide range of destinations.项目地址: https://gitcode.com/GitHub_Trending/sh/ShareX
录教程视频时,最典型的需求是把麦克风讲解和系统声音收进同一个文件,这就是多音轨录制的场景。ShareX 当前的录屏音频链路建立在 FFmpeg 的 dshow 设备输入上,配置层只保存一个音频设备,因此一次只能选一个源。接下来直接看代码,确认这条链路上哪里卡住了。
从设置窗口到 FFmpeg 命令:一条只传单值的链路
设置窗口里的单选槽位
入口在 FFmpegOptionsWindow.axaml.cs。RefreshSourcesAsync()先跑设备枚举,再把结果写进下拉框:
bool wasLoaded = _settingsLoaded; _settingsLoaded = false; VideoSourceComboBox.ItemsSource = videoSources; AudioSourceComboBox.ItemsSource = audioSources; VideoSourceComboBox.SelectedItem = videoSources.First(x => EqualsSource(x, options.VideoSource)); AudioSourceComboBox.SelectedItem = audioSources.First(x => EqualsSource(x, options.AudioSource)); _settingsLoaded = wasLoaded;问题在SelectedItem上就能看出来:整个面板只给音频源留了一个选择槽位,写回的options.AudioSource是单值。配置层 FFmpegOptions.cs 里的AudioSource确实就是一个string,数据模型层面就没预留第二个。
设备枚举的两个桶
枚举逻辑在 FFmpegCLIManager.cs。GetDirectShowDevices()先跑一次ffmpeg -list_devices true -f dshow -i dummy,再把输出逐行分类:
if (isAudio) { devices.AudioDevices.Add(deviceName); } else { devices.VideoDevices.Add(deviceName); }平铺地分成视频、音频两个桶。它不区分麦克风和立体声混音,因为下游只消费一个设备名,没动力去区分。
命令拼装里没有第二个输入位
链路最后一步是 ScreenRecordingOptions.cs 的命令拼装。GetFFmpegArgs()的纯音频分支把一路音频输入写进参数串(gdigrab 和 ddagrab 分支里也是同样这两行):
else if (FFmpeg.IsAudioSourceSelected) { AppendInputDevice(args, "dshow", true); args.Append($"-i audio={Helpers.EscapeCLIText(FFmpeg.AudioSource)} "); }AppendInputDevice会为这一路输入补-f dshow、-thread_queue_size 1024、-rtbufsize 256M和-audio_buffer_size 80这组缓冲参数。从这里往后就是-c:a编码器、-t时长这类输出参数。整个文件没有一处-filter_complex——第二个-i audio=...塞得进去吗?目前没有位置。
为什么当前架构不做多音轨录制
先把目标命令摆出来。想让两个音频源进同一个文件,手写的 FFmpeg 命令长这样:
ffmpeg -f gdigrab -i desktop -f dshow -i audio="麦克风" -f dshow -i audio="立体声混音" -filter_complex amerge=inputs=2 out.mp4关键点在amerge滤镜这一环:先合并多路流,再交给编码器。现在的实现里没有这个环节。这其实是个设计取舍,不是疏忽:单输入时,命令拼装可以保持线性字符串拼接,配置面板只需要一个下拉框;支持多源后,"一个设备一组参数"的结构就得重新定义,面板复杂度也跟着涨。当前版本选了简单。
| 能力维度 | 现状 | 缺什么 |
|---|---|---|
| 设备选择 | 单选 ComboBox | 多个音频源的多选 |
| 命令拼装 | 单路-i audio=... | 第二路输入与amerge合并环节 |
| 数据模型 | AudioSource单个字符串 | 多个音频设备的列表 |
两条先绕过去的办法
🎙️办法一:虚拟声卡。装一个虚拟混音设备(VB-Cable、VoiceMeeter 这类工具,原理是把多路系统音频路由成一块虚拟设备),然后在 ShareX 里选它:
- 安装虚拟音频混音工具
- 系统设置里把麦克风和立体声混音都路由到虚拟设备
- 在 ShareX 的录屏音频源中选中该虚拟设备
代码里其实留了伏笔:FFmpegCaptureDevice.cs 预留了VirtualAudioCapturer这个常量,官方也在往这条路上走。
办法二:两轨录制后期合成。分别录一份带声音的屏幕和一份麦克风音频,再用剪辑工具或手动跑一次 FFmpeg 把音轨混进去。适合不赶时间的离线场景。
注意:虚拟设备会引入约 10~30ms 的额外延迟,对直播类实时场景要提前评估。
想提 PR 的话,改三处
🔧 改动集中在三个文件,范围都是"在现有结构里加一个第二值":
- FFmpegOptions.cs:给
AudioSource增加第二个音频源字段,或改成列表。 - ScreenRecordingOptions.cs:
GetFFmpegArgs()中为每个选中的设备各拼一路-i audio=...,并在编码器参数前插入-filter_complex amerge=inputs=N合并环节;AppendInputDevice要按输入路数各调用一次。 - FFmpegOptionsWindow.axaml.cs 及对应 axaml:把音频源区从单选 ComboBox 改成多选,
RefreshSourcesAsync()回写多值。
对录屏工具来说,讲解声和系统声同轨是教程类内容的基本需求,这个功能值得做。等改动落地,想一次收两路声音的人就不用再绕虚拟声卡了。
【免费下载链接】ShareXShareX is a free and open-source application that enables users to capture or record any area of their screen with a single keystroke. It also supports uploading images, text, and various file types to a wide range of destinations.项目地址: https://gitcode.com/GitHub_Trending/sh/ShareX
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考