【发布时间】:2022-01-12 16:05:39
【问题描述】:
我的 Java 应用程序需要一些帮助。它的目的是阅读某个网站,所以我需要连续播放很多音频文件。 JAR 是使用 Java 8 编译的。我使用 Windows 11 和 Java 16.0.1 测试了我的应用程序,一切正常。然后我使用了最新的 Ubuntu Linux 和 Java 11.0.13 以及 Java 8:它播放一些音频,但不是每个文件。
我编写了一个测试类,结果是——无论我以何种顺序播放音频——只播放前(完全正确!)62 个文件。每个下一个文件(即使是最初成功播放的文件)都会产生我的代码在此位置抛出的异常:
if (mixerSelected != null) {
audioClip0 = AudioSystem.getClip(mixerSelected);
} else {
throw new IllegalArgumentException("File is not compatible: '" + audioFilePath + "'.");
}
我确保每个音频文件都是.WAV
- 8k 采样率,
- 平均每秒 16k 字节,
- 16 位,并且
- pcm_s16le 编解码器。
我的应用程序构建为 JAR 文件,包括资源目录中的音频文件。
这是我的代码:
public class PlayAudio {
/**
* plays an audio file
*
* @param audioFilePath String: path to the audio file
* @param speed double: speed applied to the audios
*/
public boolean singleFile(String audioFilePath, double speed) {
//audioFilePath = "audio" + File.separator + audioFilePath;
audioFilePath = "audio" + "/" + audioFilePath;
AudioInputStream audioStream0;
//create new file using path to the audio
try {
//load files from resources folder as stream
ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(audioFilePath);
InputStream bufferedInputStream = new BufferedInputStream(inputStream);
if (bufferedInputStream == null) {
throw new IllegalArgumentException("File not found: '" + audioFilePath + "'.");
} else {
//create new AudioStream
audioStream0 = AudioSystem.getAudioInputStream(bufferedInputStream);
}
} catch (IllegalArgumentException e) {
//handle
return false;
} catch (IOException e) {
//handle
return false;
} catch (UnsupportedAudioFileException e) {
//handle
return false;
}
try {
//create new AudioFormat
AudioFormat audioFormat0 = audioStream0.getFormat();
//create new Info
DataLine.Info info0 = new DataLine.Info(Clip.class, audioFormat0);
//initialize new Mixer
Mixer.Info mixerSelected = null;
for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
Mixer mixer = AudioSystem.getMixer(mixerInfo);
if (mixer.isLineSupported(info0)) {
mixerSelected = mixerInfo;
break;
}
}
//create new Clip
Clip audioClip0;
if (mixerSelected != null) {
audioClip0 = AudioSystem.getClip(mixerSelected);
} else {
//THIS EXCEPTION GETS THROWN!!!
throw new IllegalArgumentException("File is not compatible: '" + audioFilePath + "'.");
}
//open created Clips via created AudioStream
audioClip0.open(audioStream0);
//start the play of audio file
audioClip0.start();
//wait until play completed
double waitTime = (double)((((double)audioClip0.getMicrosecondLength()/1000.0)/speed + 50.0) * 0.8);
Thread.sleep((long)waitTime);
return true;
//handle exceptions
} catch (LineUnavailableException e) {
//handle
return false;
} catch (IOException e) {
//handle
return false;
} catch (InterruptedException e) {
//handle
return false;
} catch (IllegalArgumentException e) {
//THIS EXCEPTION GETS THROWN!!!
//handle invalid audio clips
System.out.println(e);
e.printStackTrace();
return false;
}
}
/**
* plays multiple audio files in the order they are stored in an ArrayList
*
* @param fileNames ArrayList<String>: list with filenames of audio files to play
* @param speaker String: speaker to use for playing the audios (can be 'm' or 'w')
* @param speed double: speed applied to the audios
* @return boolean: true if playing audios completed successfully, otherwise false
*/
public static boolean multiFiles(ArrayList<String> fileNames, String speaker, double speed) {
PlayAudio player = new PlayAudio();
//play every audio file in the array of file names
for (int i = 0; (i < fileNames.toArray().length); i ++) {
//generate file names
String fullFileName = speaker + "_" + fileNames.toArray()[i];
//play audio
player.singleFile(fullFileName, speed);
}
return true;
}
}
我已经尝试了什么?
- 我在另一台也运行 Ubuntu Linux 的计算机上进行了尝试。
- 每次播放新音频时,我都会创建一个
PlayAudio()的新实例。 - 我在每个音频之后都使用
audioClip0.stop();。 - 我将每个音频后的睡眠毫秒数增加到音频长度加上 1 秒。
- 我重建了项目......近 1k 次。
如何重现错误?
我只需要在 Linux Ubuntu 下播放超过 62 个运行我的 JAR 文件的音频文件。
你能帮我什么忙?
我不知道如何处理这个问题。在 Linux 上播放 .WAV-files 有什么问题?
有没有一种通用的方法来解决这个问题?
(我不允许使用除 OracleJDK 和 OpenJDK 之外的任何库。)
【问题讨论】:
-
您抛出的异常似乎是由
//initialize new Mixer周围的代码故障引起的。或许你应该为第 63 个音频文件调试这部分代码。 -
感谢您的提示,@Bodo。我将尝试在我的虚拟机上安装 IntelliJ 并在 Linux 中调试我的程序。
-
将所有捕获更改为第一个
e.printStackTrace()。原样的代码会丢弃有价值的信息。我通常会在上面看到的版本上使用AudioSystem.getAudioInputStream(URL)。 -
您正在打开资源(输入流,可能是与音频系统相关的其他资源),但没有关闭它们,可能您遇到了一些打开的句柄限制。请使用try-with-resources 确保在完成所有资源后关闭它们。
-
只是为了详细说明@AndrewThompson 的提示:通过使用
InputStream而不是URL,您丢弃了文件扩展名AudioSystem的有价值提示。没有它,系统必须解析您的流并猜测文件类型才能对其进行解码。使用应该在 URL 中的.wav文件扩展名,这要容易得多。
标签: java linux ubuntu jar javasound