如何使用 AudioInputStream 中间记录到文件 x 秒,然后继续流?
How to use middle of AudioInputStream to record to file for x seconds, and continue stream?
我有一个 Java 桌面程序 (Sphinx4),它 连续 在麦克风上监听关键字。然后我希望它用音频 跟随 关键字录制到文件(WAVE,bigEndian),并将其发送到外部网络 api 进行处理。好消息是我的关键字可以正常工作,并且我创建了一个在我需要的时候开始记录到文件的方法,但是当它处于音频输入流的中间时我无法停止输出而不会中断整个流。
我可以使用以下方法成功输出文件:
AudioSystem.write(inputStream, AudioFileFormat.Type.WAVE, new File("test3.wav"));
但是这是线程阻塞,并且会永远持续下去(因为这是连续监听)。看了几个小时后,我希望有人能提供一个简单的解决方案,希望我错过了。
起初,我以为我需要做的就是将其视为普通输入流,但如果不设置元信息,文件将无法播放:
byte[] buffer = new byte[1024];
FileOutputStream out = new FileOutputStream("test.wav");
while ((read = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
out.close();
基本上,我的计划是在 while 循环中添加一个布尔变量来检测何时停止然后关闭它,虽然它确实创建了一个文件,但它无法播放。
音频流启动如下:
AudioFormat format =
new AudioFormat(sampleRate, sampleSize, 1, signed, bigEndian);
try {
line = AudioSystem.getTargetDataLine(format);
line.open();
} catch (LineUnavailableException e) {
throw new IllegalStateException(e);
}
inputStream = new AudioInputStream(line);
那么我该怎么做才能在流中间获取音频文件并录制 "x" 秒?
称之为
new Timer().schedule(new TimerTask() {
@Override
public void run() {
inputStream.close();
this.cancel();
}
}, TIME_TO_RECORD,20000);
调用前
AudioSystem.write(inputStream, AudioFileFormat.Type.WAVE, new File("test3.wav"));
这基本上是在一段时间后关闭输入流。您可能需要根据需要调整延迟时间。
在尝试了各种方法后,终于找到了解决办法。我的目标是从 AudioInputStream 录制一个音频文件,但在它上面调用 "close()" 基本上破坏了整个应用程序,因为其他各种 类 也需要输入流。在我的用例中,关闭和启动新流是不切实际的。
我决定研究克隆 一个输入流,这正是我所需要的。总之,真正需要的只是从 AudioInputStream 创建一个 ByteArrayOutputStream,然后根据需要写出字节。完成后,关闭 ByteArrayOutputStream 并执行任何需要的处理。通过这样做,原始输入流不必以任何方式被触及或中断。希望这对遇到同样问题的其他人有所帮助:
int numBytesRead;
byte[] data = new byte[line.getBufferSize()];
while (isrecording) {
numBytesRead = line.read(data, 0, data.length);
baos.write(data, 0, numBytesRead);
}
try {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(baos.toByteArray());
AudioInputStream stream = new AudioInputStream(byteArrayInputStream, format, baos.toByteArray().length);
AudioSystem.write(stream, AudioFileFormat.Type.WAVE, new File("test.wav"));
baos.close();
byteArrayInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
我有一个 Java 桌面程序 (Sphinx4),它 连续 在麦克风上监听关键字。然后我希望它用音频 跟随 关键字录制到文件(WAVE,bigEndian),并将其发送到外部网络 api 进行处理。好消息是我的关键字可以正常工作,并且我创建了一个在我需要的时候开始记录到文件的方法,但是当它处于音频输入流的中间时我无法停止输出而不会中断整个流。
我可以使用以下方法成功输出文件:
AudioSystem.write(inputStream, AudioFileFormat.Type.WAVE, new File("test3.wav"));
但是这是线程阻塞,并且会永远持续下去(因为这是连续监听)。看了几个小时后,我希望有人能提供一个简单的解决方案,希望我错过了。
起初,我以为我需要做的就是将其视为普通输入流,但如果不设置元信息,文件将无法播放:
byte[] buffer = new byte[1024];
FileOutputStream out = new FileOutputStream("test.wav");
while ((read = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
out.close();
基本上,我的计划是在 while 循环中添加一个布尔变量来检测何时停止然后关闭它,虽然它确实创建了一个文件,但它无法播放。
音频流启动如下:
AudioFormat format =
new AudioFormat(sampleRate, sampleSize, 1, signed, bigEndian);
try {
line = AudioSystem.getTargetDataLine(format);
line.open();
} catch (LineUnavailableException e) {
throw new IllegalStateException(e);
}
inputStream = new AudioInputStream(line);
那么我该怎么做才能在流中间获取音频文件并录制 "x" 秒?
称之为
new Timer().schedule(new TimerTask() {
@Override
public void run() {
inputStream.close();
this.cancel();
}
}, TIME_TO_RECORD,20000);
调用前
AudioSystem.write(inputStream, AudioFileFormat.Type.WAVE, new File("test3.wav"));
这基本上是在一段时间后关闭输入流。您可能需要根据需要调整延迟时间。
在尝试了各种方法后,终于找到了解决办法。我的目标是从 AudioInputStream 录制一个音频文件,但在它上面调用 "close()" 基本上破坏了整个应用程序,因为其他各种 类 也需要输入流。在我的用例中,关闭和启动新流是不切实际的。
我决定研究克隆 一个输入流,这正是我所需要的。总之,真正需要的只是从 AudioInputStream 创建一个 ByteArrayOutputStream,然后根据需要写出字节。完成后,关闭 ByteArrayOutputStream 并执行任何需要的处理。通过这样做,原始输入流不必以任何方式被触及或中断。希望这对遇到同样问题的其他人有所帮助:
int numBytesRead;
byte[] data = new byte[line.getBufferSize()];
while (isrecording) {
numBytesRead = line.read(data, 0, data.length);
baos.write(data, 0, numBytesRead);
}
try {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(baos.toByteArray());
AudioInputStream stream = new AudioInputStream(byteArrayInputStream, format, baos.toByteArray().length);
AudioSystem.write(stream, AudioFileFormat.Type.WAVE, new File("test.wav"));
baos.close();
byteArrayInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}