SoundSwitch CLI 命令行工具完全指南:开关音频设备、管理麦克风静音与配置文件

原创2026-10-03 14:19:02357 阅读
文章标签:桌面应用

SoundSwitch CLI 命令行工具完全指南:开关音频设备、管理麦克风静音与配置文件

SoundSwitch 是一款用于切换 Windows 默认播放/录音设备的 C# 桌面应用,而 SoundSwitch.CLI 是它的官方命令行接口,让用户无需打开图形界面即可完成设备切换、麦克风静音控制、配置文件管理与状态查询。本文将以 CLI 官方文档为主体,结合仓库源码深入讲解全部命令、参数、JSON 输出约定与底层 IPC 通信原理,读完即可在脚本、自动化任务中熟练驾驭 SoundSwitch。

概览:CLI 的定位与工作方式

SoundSwitch CLI 是一个独立的控制台程序,它本身不直接操作音频设备,而是通过 Windows 命名管道(Named Pipe)向正在运行的 SoundSwitch 主程序发送控制消息,由主程序代为执行真正的设备切换与状态查询。这意味着使用 CLI 前通常需要 SoundSwitch 主程序处于运行状态。

从 SoundSwitch.CLI.csproj 可以看出:

  • 目标框架为 net10.0,支持 Debug / Release / Beta / Nightly 多种构建配置;
  • 直接引用 SoundSwitch.IPC 项目,所有命令的请求/响应都经由 IPC 层完成;
  • 使用 Spectre.Console.Cli 解析命令行参数、Spectre.Console 渲染表格与进度状态,并用 MessagePack 在管道中做二进制序列化。

命令入口定义在 Program.cs:通过 CommandApp 注册了 switch、profile、settings、mute、status、devices 六个子命令,并附带各自的示例用法。

全局约定:--json 与退出码

所有命令都接受 --json 选项,用于输出机器可读的 JSON。该选项由公共基类 JsonCommandSettings 统一注册,各命令继承即可自动获得。

  • 成功时输出业务 JSON 并以退出码 0 结束;
  • 失败时统一输出一个包含 error 字段的 JSON 对象,并以退出码 1 结束:
{ "error": "Failed to retrieve status" }

JSON 输出统一由 JsonOutput 负责,它使用带缩进的 JsonSerializer 直接写入 Console.Out。源码注释特别强调:JSON 模式下绝不能使用 Spectre.Console 的进度动画或标记语法,因为它们会输出 ANSI 转义序列,污染管道输出——因此 --json 的结果可以安全地交给 jq 解析或捕获到变量中。

命令详解

switch:切换播放/录音设备

切换默认播放或录音设备,在 SoundSwitch 已选定的设备列表中循环:

SoundSwitch.CLI.exe switch --type Recording
SoundSwitch.CLI.exe switch --type Playback
SoundSwitch.CLI.exe switch --type Playback --json

参数 --type(等价写法 -t,也支持位置参数)取值对应 IPC 层的 AudioType 枚举,常用值为 Playback(播放)与 Recording(录音)。成功时输出 { "success": true, "type": "Playback" }:

{
  "success": true,
  "type": "Playback"
}

从 SwitchCommand.cs 的实现看,该命令构造 TriggerSwitchRequest { Type = settings.Type } 并经 NamedPipe.SendRequestAsync<TriggerSwitchResponse> 发送,只有响应 Success 为真才返回 0,否则输出 { "error": "Failed to switch ... device" } 并返回 1。非 JSON 模式下会显示一个带旋转动画的状态提示 Switching Playback device...,成功显示绿色提示,失败显示红色提示。

mute:麦克风静音控制

查询与设置默认麦克风的静音状态:

SoundSwitch.CLI.exe mute              # 显示当前静音状态
SoundSwitch.CLI.exe mute --state true # 静音麦克风
SoundSwitch.CLI.exe mute -s false     # 取消静音
SoundSwitch.CLI.exe mute --toggle     # 切换静音状态
SoundSwitch.CLI.exe mute --json       # 以 JSON 查询当前状态

参数说明:

参数 等价写法 说明
--state -s 布尔值 true/false,指定目标静音状态
--toggle -t 将当前状态取反(切换)
不传任何参数 — 仅查询并显示当前状态

注意 --state 的类型是可空布尔(bool?):不传时仅查询。--json 变体总是输出 { "deviceName": "...", "isMuted": true|false }:

{
  "deviceName": "Microphone (USB Audio Device)",
  "isMuted": false
}

MuteCommand.cs 的实现揭示了它的智能逻辑:

  1. 先发送 MicrophoneStateRequest 查询当前状态;
  2. 若未指定 --state 且未指定 --toggle,直接输出当前状态并返回 0;
  3. 计算目标状态(--toggle 时取当前值反相,否则取 --state 的值);
  4. 若目标状态与当前一致,不做任何修改,直接输出当前状态(幂等);
  5. 否则发送 MuteRequest { Mute = targetState } 执行变更。

这一设计保证重复执行 mute --state true 不会产生无意义的管道往返。若系统没有设置默认麦克风,或主程序无法响应,命令会以退出码 1 报错。

profile:配置文件管理

配置文件(Profile)是 SoundSwitch 将一组播放/录音设备绑定到某个场景(如游戏、会议)的功能。CLI 支持列出全部配置和触发指定配置。

列出所有可用配置文件:

SoundSwitch.CLI.exe profile --list
SoundSwitch.CLI.exe profile --list --json

--list(等价写法 -l)的 JSON 输出是一个配置文件对象数组,每个对象包含 name、playbackDevice、playbackCommunicationDevice、recordingDevice、recordingCommunicationDevice 五个字段:

[
  {
    "name": "Gaming",
    "playbackDevice": "Speakers (Realtek(R) Audio)",
    "playbackCommunicationDevice": "Headset Earphone (HyperX Cloud II)",
    "recordingDevice": "Microphone (USB Audio Device)",
    "recordingCommunicationDevice": "Headset Microphone (HyperX Cloud II)"
  }
]

触发(激活)指定配置文件:

SoundSwitch.CLI.exe profile --name "Profile Name"

--name(等价写法 -n)配合 --json 时,成功输出 { "success": true, "profile": "Profile Name" }:

{
  "success": true,
  "profile": "Gaming"
}

ProfileCommand.cs 的校验逻辑:若未指定 --list 且 --name 为空,直接输出 { "error": "Profile name is required unless --list is specified" } 并返回 1。非 JSON 模式下 --list 渲染为五列表格(Profile / Playback / Playback Comm / Recording / Recording Comm),绿色标识播放类设备、红色标识录音类设备。

settings:打开设置窗口

在 GUI 中打开 SoundSwitch 设置窗口:

SoundSwitch.CLI.exe settings
SoundSwitch.CLI.exe settings --json

JSON 输出为:

{
  "success": true
}

实现上发送 OpenSettingsRequest,成功返回 0;失败输出 { "error": "Failed to open settings" } 并返回 1。

status:查询当前状态

显示当前激活的配置文件与默认音频设备:

SoundSwitch.CLI.exe status              # 人类可读的表格输出
SoundSwitch.CLI.exe status --json       # 机器可读的 JSON 输出

JSON 输出包含五个字段:activeProfile、playbackDevice、recordingDevice、playbackCommunicationDevice、recordingCommunicationDevice。不存在的设备序列化为空字符串 "":

{
  "activeProfile": "Gaming",
  "playbackDevice": "Speakers (Realtek(R) Audio)",
  "recordingDevice": "Microphone (USB Audio Device)",
  "playbackCommunicationDevice": "Headset Earphone (HyperX Cloud II)",
  "recordingCommunicationDevice": "Headset Microphone (HyperX Cloud II)"
}

重要语义说明: “Active Profile” 显示的是最后一次由用户操作或触发规则显式激活的配置文件,它不会反映 SoundSwitch 之外对系统的更改(例如直接在 Windows 声音设置里切换设备)。因此脚本在判断“当前生效配置”时应理解这一限制。表格式输出中,无激活配置时 activeProfile 显示为 None。

devices:列出可切换设备

列出当前在线且在 SoundSwitch 设置中被选中的设备(即 SoundSwitch 循环切换时会用到的设备集合):

SoundSwitch.CLI.exe devices
SoundSwitch.CLI.exe devices --json

JSON 输出为 { "playbackDevices": [...], "recordingDevices": [...] }:

{
  "playbackDevices": [
    "Speakers (Realtek(R) Audio)",
    "Headset Earphone (HyperX Cloud II)"
  ],
  "recordingDevices": [
    "Microphone (USB Audio Device)"
  ]
}

注意该命令与 status 的区别:status 报告当前正在使用的默认设备,devices 报告 SoundSwitch 切换时会遍历的设备集合。实际返回内容由 DevicesCommand.cs 通过 GetSwitchableDevicesRequest 从主程序获取。

实战示例

以下 8 个示例覆盖了 CLI 的典型使用场景,可直接复制到 PowerShell / CMD / 批处理脚本中:

# 1. 切换到下一个播放设备
SoundSwitch.CLI.exe switch --type Playback

# 2. 切换到下一个录音设备
SoundSwitch.CLI.exe switch --type Recording

# 3. 列出所有可用配置文件
SoundSwitch.CLI.exe profile --list

# 4. 触发指定配置文件
SoundSwitch.CLI.exe profile --name "Headphones + Mic"

# 5. 打开设置窗口
SoundSwitch.CLI.exe settings

# 6. 静音/取消静音麦克风
SoundSwitch.CLI.exe mute -t             # 切换静音状态
SoundSwitch.CLI.exe mute -s true        # 静音
SoundSwitch.CLI.exe mute --state false  # 取消静音

# 7. 查看当前音频状态
SoundSwitch.CLI.exe status
SoundSwitch.CLI.exe status --json

# 8. 列出选中用于切换的设备
SoundSwitch.CLI.exe devices
SoundSwitch.CLI.exe devices --json

与 jq 组合可写出更智能的自动化逻辑,例如:

# 只有当前激活配置不是 Gaming 时才切换到 Gaming
if [ "$(SoundSwitch.CLI.exe status --json | jq -r '.activeProfile')" != "Gaming" ]; then
  SoundSwitch.CLI.exe profile --name "Gaming"
fi

错误处理

CLI 在以下场景会给出明确报错(均以退出码 1 结束):

  • SoundSwitch 主程序未运行:管道客户端在 5 秒连接超时(CONNECTION_TIMEOUT,见 NamedPipe.cs)内无法连上命名管道;
  • 配置文件名称无效:profile --name 指定的名称在主程序中不存在,或未提供名称且未加 --list;
  • 连接问题:管道连接中断、响应超时或服务端返回 ErrorResponse;
  • 无效命令或选项:Spectre.Console.Cli 会拒绝未注册的命令与非法参数值;
  • 未设置默认麦克风(仅影响 mute 命令):无法确定要查询/操作的目标设备。

所有命令均支持 --help 查看完整的参数说明与示例:

SoundSwitch.CLI.exe switch --help
SoundSwitch.CLI.exe --help

底层原理:IPC 管道与 MessagePack

CLI 的全部能力依赖 SoundSwitch.IPC 提供的命名管道基础设施,理解它有助于排查“CLI 无响应”类问题。

管道命名规则: PipeConstants.cs 定义管道名为 "SoundSwitch" + Environment.UserName,即按 Windows 用户名区分,同一用户会话下的主程序与 CLI 共用同一条管道。

消息协议: NamedPipe.cs 的 SendRequestAsync 是 CLI 所有命令的公共调用链:

  1. 创建/复用 NamedPipeClientStream 并连接(超时 5 秒);
  2. 用 MessagePack 序列化请求对象,先写入 4 字节长度前缀再写入负载;
  3. 读取响应长度(上限 1 MiB),按长度读取并反序列化;
  4. 若收到 ErrorResponse,抛出 PipeRequestException,命令层捕获后转为 JSON 错误输出。

每个 CLI 命令与对应的 IPC 消息一一对应:switch → TriggerSwitchRequest(TriggerSwitchRequest.cs)、profile --list → GetProfileListRequest、status → GetActiveDevicesRequest、devices → GetSwitchableDevicesRequest、mute → MicrophoneStateRequest/MuteRequest、settings → OpenSettingsRequest,请求对象均带 [MessagePackObject(keyAsPropertyName: true)] 特性以属性名作为键。

由于采用了长度前缀 + MessagePack 的紧凑协议,CLI 的每次交互只产生几百字节到几 KB 的管道流量,非常轻量,适合高频调用。若主程序 15 秒内未响应,客户端会抛出超时异常并重建连接(见 NamedPipe.cs)。

适用前提与限制

  • 平台:SoundSwitch 是 Windows 专属应用,CLI 依赖 System.IO.Pipes 命名管道与 Windows 音频栈,仅在 Windows 上运行;
  • 前置条件:使用前需构建或安装 CLI,并确保 SoundSwitch 主程序正在运行;
  • 配置联动:switch 与 devices 的行为受 SoundSwitch 设置中“已选中设备”的影响——只有被选中的在线设备才会参与循环切换;
  • 状态语义:status 的 activeProfile 反映的是 SoundSwitch 内部记录的最近一次显式激活,不代表系统层面未经 SoundSwitch 干预的实时设备状态。

掌握以上命令与语义,你就可以把 SoundSwitch 无缝接入自己的脚本、快捷键工具或自动化工作流,实现一键切换耳机/音箱、会议前自动静音麦克风等场景。

登录后查看全文
SoundSwitch