Java无法直接内录系统音频,因javax.sound.sampled仅支持物理输入设备;Windows“立体声混音”需驱动支持且Java底层WaveIn API识别不稳定;推荐用ffmpeg wasapi loopback或JNA调用Core Audio API实现。

Java 本身不提供直接捕获系统音频输出(即“内录”、录制扬声器声音)的 API。这是操作系统层面的限制,javax.sound.sampled 只能访问物理输入设备(如麦克风),无法访问虚拟播放流或混音后输出总线。
为什么 AudioSystem.getTargetDataLine() 找不到“立体声混音”或“What U Hear”设备
Windows 上的“立体声混音”(Stereo Mix)是 Realtek / Conexant 等厂商驱动提供的虚拟输入设备,需手动启用且不被 Java 的默认 Mixer.Info 枚举识别——因为 Java 使用的是底层 Windows WaveIn API,而该 API 对第三方虚拟设备支持不稳定,尤其在 Win10/Win11 后多数驱动已弃用该功能。
- 调用
AudioSystem.getMixerInfo()
列出所有 mixer,通常只看到DirectSound Audio Capture或真实麦克风,看不到“Stereo Mix” - 即使设备在系统录音设置中启用,Java 也无法通过标准 API 获取其
DataLine - 部分 OEM 笔记本(如 Dell、HP)根本不在驱动中提供 Stereo Mix 选项
可行替代方案:使用第三方本地库桥接
绕过 Java 声音 API,调用系统级录音能力。最稳定路径是借助 FFmpeg 或 Windows Core Audio API 封装工具:
- 用
ffmpeg.exe启动子进程,通过-f dshow -i audio="virtual-audio-capturer"(需安装 Screen Capture Recorder)或-f wasapi -i ":loopback"(Win10+ 原生 loopback 模式)采集输出 - Java 中用
ProcessBuilder
启动 ffmpeg,将 stdout 设为PIPE,读取原始 PCM 流(如-f s16le -ar 44100 -ac 2) - 避免用
AudioFormat.Encoding.PCM_SIGNED直接解析——ffmpeg 输出是裸数据,无 WAV 头,需自己按参数构造AudioInputStream -
macOS 需依赖
blackhole虚拟音频设备 +ffmpeg -f avfoundation -i ":0";Linux 可用pulseaudio的 monitor source(如pacmd list-sources | grep -A2 'monitor_of')
Java 调用 wasapi loopback 的最小可行代码片段(Windows 10+)
不依赖外部 exe,但需 JNI 或 JNA 调用 Windows Core Audio API。推荐使用 JNAerator 生成的 CoreAudio binding:
立即学习“Java免费学习笔记(深入)”;
final IAudioCaptureClient captureClient = renderClient.getAudioCaptureClient(); final int bufferFrameCount = renderClient.getBufferSize(); final Pointer pData; final IntByReference flags = new IntByReference(); int numFramesAvailable;while (running) { renderClient.getBuffer(bufferFrameCount, pData, numFramesAvailable, flags); if ((flags.getValue() & AUDCLNT_BUFFERFLAGS_SILENT) == 0) { // pData 指向 PCM16 数据,按 format.channelCount format.sampleRate 2 计算字节长度 processPcmData(pData, numFramesAvailable * format.getFrameSize()); } renderClient.releaseBuffer(numFramesAvailable); }
关键点:renderClient 必须由 IMMDevice 获取默认渲染设备后,用 IAudioClient::Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_LOOPBACK) 初始化——AUDCLNT_STREAMFLAGS_LOOPBACK 是内录开关,漏掉就变成录麦克风。
真正麻烦的不是代码,而是权限和兼容性:UAC 提权、Windows 音频会话控制(ISimpleAudioVolume)、不同声卡对 loopback 的实际支持程度差异很大。很多用户最终发现,用 ffmpeg -f wasapi -i ":loopback" 录 5 秒再解析 WAV 头,比手撸 JNA 稳定十倍。










