Ubuntu 16.4下Java用AudioSystem播放WAV遇PulseAudio格式异常求助
我之前也碰到过类似的PulseAudio和Java AudioSystem兼容性问题,尤其是在老版本Ubuntu上,这种格式匹配的坑确实头疼。针对你遇到的情况——用AudioSystem.getClip()播放PCM_SIGNED, 22050 Hz, 16 bit, mono, 2 bytes/frame, little endian格式音频时,PulseAudio抛出Invalid Format Exception,只接受PCM_SIGNED, unknown sample rate, 16 bit, stereo, 4 bytes/frame, big endian格式,甚至重新采样文件也无效——给你几个可行的排查和解决方向:
强制Java使用ALSA而非PulseAudio
PulseAudio在Ubuntu 16.04对某些小众PCM格式的支持确实有局限,你可以尝试让Java绕过PulseAudio直接调用底层的ALSA音频驱动。启动Java程序时添加系统属性:java -Djavax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider -jar your-application.jar或者在Java代码初始化阶段提前设置:
System.setProperty("javax.sound.sampled.Clip", "com.sun.media.sound.DirectAudioDeviceProvider");调整PulseAudio的默认格式配置
直接修改PulseAudio的全局配置,让它默认适配你需要的音频格式。编辑/etc/pulse/daemon.conf文件,找到并修改以下参数(如果是注释状态就去掉#):default-sample-rate = 22050 default-sample-channels = 1 default-sample-format = s16le修改完成后重启PulseAudio服务:
pulseaudio -k && pulseaudio --start这样PulseAudio会优先使用你指定的格式,应该能解决格式拒绝的问题。
在代码中实时转换音频格式
如果重新采样音频文件无效,试试在Java代码里实时转换格式。利用AudioSystem的格式转换API,把原音频流转换成PulseAudio接受的格式后再播放:// 读取原音频文件 AudioInputStream originalStream = AudioSystem.getAudioInputStream(new File("your-audio-file.wav")); // 定义PulseAudio接受的目标格式 AudioFormat targetFormat = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED, AudioSystem.NOT_SPECIFIED, // 对应unknown sample rate 16, 2, // stereo 4, // 4 bytes/frame AudioSystem.NOT_SPECIFIED, true // big endian ); // 转换格式 AudioInputStream convertedStream = AudioSystem.getAudioInputStream(targetFormat, originalStream); // 播放转换后的音频 Clip clip = AudioSystem.getClip(); clip.open(convertedStream); clip.start();升级PulseAudio版本
Ubuntu 16.04默认的PulseAudio版本比较陈旧,可能存在格式支持的bug。你可以尝试升级到该系统版本支持的最新PulseAudio:sudo apt update && sudo apt upgrade pulseaudio升级完成后重启系统,再测试音频播放是否正常。
内容的提问来源于stack exchange,提问作者decades

