Mirror one Windows playback device's volume onto another — so your volume keys / keyboard knob can drive the sound card you actually care about, while keeping the native Windows volume OSD. (English README: README.en.md)
把一个 Windows 播放设备的音量实时镜像到另一个播放设备的小工具。
Windows 的音量键(以及很多键盘上的音量旋钮 / 触控条 / 多媒体键)永远只调整「当前默认播放设备」。这会带来两类麻烦:
- 你的默认设备是虚拟声卡(Voicemeeter、VB-CABLE、各种虚拟音频设备)——它往往完全忽略自己端点的 Windows 音量。于是音量键按下去毫无效果,你甚至不知道它在调什么。
- 你只是想让音量键去控制另一张声卡(比如耳机而不是音箱)。Windows 没有提供这个选项。
VolumeMirror 的做法:不拦截、不吞掉任何按键,只是盯着「来源设备」的音量,一有变化就同步到「目标设备」。
因为不拦截,Windows 自带的音量 OSD 会照常弹出——这是它和「拦截音量键再重定向」那类方案的关键区别。
- 键盘/鼠标/触控条的音量控制只能调默认设备,而你想调另一张声卡。
- 默认设备是虚拟混音器(Voicemeeter 等),音量键形同虚设。
- 任何「用一个音量控制去驱动另一个设备」的场合。
flowchart LR
K["音量键 / 键盘旋钮"] -->|标准音量键| W["Windows"]
W -->|调整音量| S["来源设备<br/>(默认播放设备)"]
W -->|弹出| OSD["系统音量 OSD ✓"]
subgraph V["VolumeMirror(常驻后台)"]
P["每 PollMs 毫秒<br/>读取来源设备音量"] --> C{"和上次不同?"}
C -->|是| T["写入目标设备音量"]
C -->|否| P
end
S -.->|读取| P
T -.->|设置| D["目标设备<br/>(你真正想控制的声卡)"]
要点:
- 来源设备默认 = 当前系统默认播放设备(就是音量键会改的那个)。也可以显式指定。
- 目标设备 = 你想让音量键真正控制的设备。
- 全程只是读一个、写另一个,不碰键盘事件,所以 OSD / 系统行为完全不变。
- Windows 10 / 11
- .NET Framework 4.x(Windows 自带,含
csc.exe编译器,无需安装任何 SDK)
- 编译:双击
build.cmd→ 生成VolumeMirror.exe - 看设备名:运行
VolumeMirror.exe --list(*标记当前默认设备) - 配置:复制
config.ini.example为config.ini,把Target设成目标设备名里的一段唯一关键字 (或直接双击SelectTarget.cmd,它会列设备并帮你写配置) - 启动:双击
Start.cmd(后台运行,无窗口) - (可选)开机自启:双击
InstallAutostart.cmd;取消用UninstallAutostart.cmd
| 键 | 说明 |
|---|---|
Source |
要监听的设备。留空 = 跟随当前系统默认播放设备(推荐) |
Target |
要控制的设备。填设备名里一段唯一的关键字,例如 HECATE、Realtek USB Audio |
AlignOnStart |
1 = 启动时把来源设备音量对齐成目标设备当前音量(避免第一下跳变);0 = 不动 |
PollMs |
轮询间隔(毫秒,20–2000)。默认 60 |
设备名匹配规则:先精确全名匹配,再唯一子串匹配;若一个子串命中多个设备,工具会拒绝并在日志里列出候选,绝不替你猜。 所以
Target不要带括号 —— 写Realtek USB Audio,不要写扬声器 (Realtek USB Audio)。
VolumeMirror.exe --list :: 列出所有已启用的播放设备 + 当前音量(* = 当前默认)
VolumeMirror.exe --align :: 手动执行一次「来源对齐到目标」,然后退出
VolumeMirror.exe --version :: 版本
VolumeMirror.exe :: 启动常驻镜像(控制台隐藏,日志写 VolumeMirror.log)Q:为什么不用拦截音量键?那样不是更直接? A:拦截会吞掉按键,Windows 就不再弹音量 OSD 了,而且会干扰其它程序对音量键的处理。镜像方式不动任何按键,代价只是「来源设备的音量也会跟着变」——如果来源设备是虚拟声卡(通常忽略自己的端点音量),这个副作用等于零。
Q:目标设备没反应?
A:先看 VolumeMirror.log。常见原因:Target 写错或带了括号;命中多个设备(日志会列出候选);来源与目标被解析成同一个设备。
Q:能让多个声卡一起被调吗?
A:可以。跑多个实例、各自指向不同目录与 config.ini,或把 Target 指向一个把多张声卡聚合起来的虚拟设备(Voicemeeter 之类)。
Q:会不会改我的系统设置?
A:不会。它只调用 Windows CoreAudio 读写设备音量;不写注册表(除非你自己跑 InstallAutostart.cmd,那会在 HKCU\...\Run 里加一项)、不联网、无其它副作用。
- 轮询式同步(默认 60ms):极快速连续调节时可能丢掉中间帧,最终值一定一致。
- OSD 上显示的是来源设备的名字,数值与目标设备一致(来源=默认设备时的固有限制)。
- 只在「渲染(播放)」端点上工作,不处理录音设备。
- 不需要管理员权限。
build.cmd 实际执行的就是:
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe ^
/nologo /codepage:65001 /target:exe /out:VolumeMirror.exe src\VolumeMirror.cs单文件、零依赖、无 NuGet。想用 dotnet / Visual Studio 编译也可以,源码是普通 C#。
MIT — 见 LICENSE。