Java Sound API通过AudioSystem.getMixerInfo()列出所有可用Mixer,但部分真实音频设备可能因系统权限、驱动限制或JDK版本差异未显示;需结合isLineSupported()验证实际音频能力,并用getDefaultMixer()定位默认设备。

Java Sound API怎么列出所有可用Mixer(音频设备)
Java Sound API 通过 Mixer.Info 和 AudioSystem.getMixerInfo() 获取系统级音频设备列表,但要注意:它返回的是 Mixer 抽象概念,不是“声卡”或“蓝牙耳机”这种直观设备名,且部分设备可能因权限、驱动或系统限制不可见。
-
AudioSystem.getMixerInfo()返回所有已注册 Mixer 的描述信息,包括默认设备(AudioSystem.getDefaultMixer()对应的那个) - 每个
Mixer.Info包含getName()、getDescription()、getVendor(),但不保证可读——Windows 上常是 “Primary Sound Driver”,macOS 可能是 “Built-in Output”,Linux ALSA 下可能是 “hw:0,0” - 某些后台 Mixer(如“Java Sound Sequencer”)不处理真实音频流,仅用于 MIDI 或合成,需结合
Mixer.isLineSupported()过滤
import javax.sound.sampled.*;
import java.util.Arrays;
public class ListMixers {
public static void main(String[] args) {
Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
System.out.println("共找到 " + mixerInfos.length + " 个 Mixer:\n");
for (Mixer.Info info : mixerInfos) {
Mixer mixer = AudioSystem.getMixer(info);
String name = info.getName().trim();
String desc = info.getDescription().trim();
String vendor = info.getVendor().trim();
// 判断是否支持基本音频线(粗筛真实音频设备)
boolean hasTarget = mixer.isLineSupported(new Line.Info(TargetDataLine.class));
boolean hasSource = mixer.isLineSupported(new Line.Info(SourceDataLine.class));
System.out.printf("名称:%s%n描述:%s%n厂商:%s%n支持播放:%s|支持录音:%s%n---%n",
name.isEmpty() ? "(未命名)" : name,
desc.isEmpty() ? "(无描述)" : desc,
vendor.isEmpty() ? "(未知)" : vendor,
hasSource, hasTarget);
}
}
}
为什么有些真实音频设备没出现在 getMixerInfo() 结果里
不是代码写错了,而是受底层限制:
- Windows:JDK 默认使用 DirectSound(旧)或 WASAPI(JDK 12+ 默认),但若系统禁用 WASAPI 共享模式、或 Java 进程未以正确权限运行,部分设备(尤其是 USB 音频接口、蓝牙 A2DP)可能被跳过
- macOS:Core Audio 设备通常都能列出来,但某些第三方驱动(如 BlackHole、Loopback)需确保已启用并被 Java 进程识别
- Linux:ALSA 后端依赖
/dev/snd/权限,普通用户若不在audio用户组中,会直接丢弃部分 Mixer;另外 PulseAudio 层有时会拦截 ALSA 调用,导致 Java 看到的是 PulseAudio Mixer 而非真实硬件 - JDK 版本差异:JDK 8u292 之前对 WASAPI 支持不完整;JDK 17+ 在 Linux 上对 PipeWire 支持仍有限,可能漏掉新设备
如何判断哪个 Mixer 对应当前系统默认播放/录音设备
不能只靠名字匹配,得靠行为验证:
- 用
AudioSystem.getDefaultMixer()拿到默认 Mixer,再调用mixer.getSourceLineInfo()和mixer.getTargetLineInfo()查看它实际支持哪些线路类型 - 尝试打开一条
SourceDataLine或TargetDataLine(哪怕只 open 不 start),能成功说明该 Mixer 可用;抛出LineUnavailableException很可能代表设备被占用或驱动异常 - 注意:
getDefaultMixer()返回的 Mixer 不一定在getMixerInfo()列表中(极少数 JDK 实现有缓存偏差),建议优先用它做主路径
try {
Mixer defaultMixer = AudioSystem.getDefaultMixer();
Mixer.Info defaultInfo = defaultMixer.getMixerInfo();
System.out.println("默认 Mixer 名称:" + defaultInfo.getName());
// 尝试获取播放能力
DataLine.Info lineInfo = new DataLine.Info(SourceDataLine.class,
new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false));
if (defaultMixer.isLineSupported(lineInfo)) {
SourceDataLine line = (SourceDataLine) defaultMixer.getLine(lineInfo);
line.open(); // 验证是否真可用
System.out.println("✅ 默认 Mixer 支持并可打开播放线路");
line.close();
}
} catch (LineUnavailableException e) {
System.out.println("❌ 默认 Mixer 当前不可用:" + e.getMessage());
}
Linux 下常见 Mixer 名称与对应硬件的映射关系
ALSA 后端下 Mixer 名称高度依赖 /proc/asound/cards 和 udev 规则,以下为典型情况(可通过 aplay -l 交叉验证):
立即学习“Java免费学习笔记(深入)”;
-
hw:0或Intel PCH→ 主板集成声卡(Realtek ALCxxx 系列) -
hw:1或USB Audio→ USB 声卡或麦克风(如 Blue Yeti、Focusrite Scarlett) -
plughw:0,0→ ALSA 插件层包装的硬件设备(带采样率转换,更兼容但延迟略高) -
default或PulseAudio→ PulseAudio Mixer,实际音频经其路由,Java 看到的是虚拟设备 -
sysdefault:CARD=XXXX→ systemd-udev 自动命名的设备,XXXX 是声卡 ID(如 “Generic_5”),较可靠
getName() 可能全都是 “USB Audio Device”。这时候得结合 getVendor() + getDescription() + 实际 open 测试,甚至需要解析 /sys/class/sound/ 下的设备属性。










