Skip to content

About

Mirror one Windows playback device volume onto another - keeps the native volume OSD

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

VolumeMirror

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 的音量键(以及很多键盘上的音量旋钮 / 触控条 / 多媒体键)永远只调整「当前默认播放设备」。这会带来两类麻烦:

  1. 你的默认设备是虚拟声卡(Voicemeeter、VB-CABLE、各种虚拟音频设备)——它往往完全忽略自己端点的 Windows 音量。于是音量键按下去毫无效果,你甚至不知道它在调什么。
  2. 你只是想让音量键去控制另一张声卡(比如耳机而不是音箱)。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/>(你真正想控制的声卡)"]
Loading

要点:

  • 来源设备默认 = 当前系统默认播放设备(就是音量键会改的那个)。也可以显式指定。
  • 目标设备 = 你想让音量键真正控制的设备。
  • 全程只是读一个、写另一个,不碰键盘事件,所以 OSD / 系统行为完全不变。

环境要求

  • Windows 10 / 11
  • .NET Framework 4.x(Windows 自带,含 csc.exe 编译器,无需安装任何 SDK)

快速开始

  1. 编译:双击 build.cmd → 生成 VolumeMirror.exe
  2. 看设备名:运行 VolumeMirror.exe --list(* 标记当前默认设备)
  3. 配置:复制 config.ini.example 为 config.ini,把 Target 设成目标设备名里的一段唯一关键字 (或直接双击 SelectTarget.cmd,它会列设备并帮你写配置)
  4. 启动:双击 Start.cmd(后台运行,无窗口)
  5. (可选)开机自启:双击 InstallAutostart.cmd;取消用 UninstallAutostart.cmd

配置项(config.ini)

键 说明
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。

About

Mirror one Windows playback device volume onto another - keeps the native volume OSD

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages