本文目录导读:

在Java中实现录音功能,最常用的方式是使用 javax.sound.sampled 包,它是Java标准库自带的音频处理API,无需额外引入第三方库即可完成基本的录音和播放功能。
下面是一个完整的Java录音案例,包含录音、保存音频文件(WAV格式)以及播放录音的功能。
核心思路
- 获取音频输入设备:通过
AudioSystem.getTargetDataLine()获取麦克风等音频输入设备。 - 定义音频格式:设置采样率、采样位数、声道数等参数。
- 开始录音:打开数据线,启动音频数据读取线程,将数据写入内存或直接写入文件。
- 停止录音:关闭数据线,停止线程。
- 保存文件:将捕获的音频数据写入WAV文件(需自行处理WAV文件头)。
完整代码示例
import javax.sound.sampled.*;
import java.io.*;
/**
* Java录音案例:支持录音、暂停、停止,保存为WAV文件
*/
public class AudioRecorder {
// 音频格式参数
private static final int SAMPLE_RATE = 44100; // 采样率:44.1kHz
private static final int BITS_PER_SAMPLE = 16; // 采样位数:16位
private static final int CHANNELS = 1; // 声道数:单声道
private static final boolean SIGNED = true; // 有符号
private static final boolean BIG_ENDIAN = false; // 小端序
private TargetDataLine targetDataLine;
private AudioInputStream audioInputStream;
private volatile boolean isRecording = false;
private volatile boolean isPaused = false;
private ByteArrayOutputStream byteArrayOutputStream;
private Thread recordingThread;
/**
* 开始录音
* @param audioFile 要保存的WAV文件路径(如果为null则暂存内存)
*/
public void startRecording(File audioFile) {
if (isRecording) {
System.out.println("录音正在进行中...");
return;
}
try {
// 1. 定义音频格式
AudioFormat audioFormat = new AudioFormat(
SAMPLE_RATE,
BITS_PER_SAMPLE,
CHANNELS,
SIGNED,
BIG_ENDIAN
);
// 2. 获取音频输入设备(麦克风)
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
if (!AudioSystem.isLineSupported(dataLineInfo)) {
System.err.println("不支持该音频格式或没有麦克风输入设备");
return;
}
targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
targetDataLine.open(audioFormat);
targetDataLine.start();
// 3. 创建音频输入流
audioInputStream = new AudioInputStream(targetDataLine);
// 4. 准备输出流
byteArrayOutputStream = new ByteArrayOutputStream();
isRecording = true;
isPaused = false;
// 5. 启动录音线程
recordingThread = new Thread(() -> {
try {
byte[] buffer = new byte[4096];
int bytesRead;
while (isRecording && !Thread.currentThread().isInterrupted()) {
if (!isPaused) {
bytesRead = audioInputStream.read(buffer);
if (bytesRead > 0) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
}
} else {
Thread.sleep(100); // 暂停时休眠,避免CPU空转
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "RecordingThread");
recordingThread.start();
System.out.println("录音已开始...");
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
/**
* 暂停录音
*/
public void pauseRecording() {
if (isRecording && !isPaused) {
isPaused = true;
System.out.println("录音已暂停");
}
}
/**
* 恢复录音
*/
public void resumeRecording() {
if (isRecording && isPaused) {
isPaused = false;
System.out.println("录音已恢复");
}
}
/**
* 停止录音并保存到文件
* @param audioFile 保存的WAV文件路径
*/
public void stopRecordingAndSave(File audioFile) {
if (!isRecording) {
System.out.println("录音尚未开始");
return;
}
isRecording = false;
// 等待录音线程结束
try {
if (recordingThread != null) {
recordingThread.interrupt();
recordingThread.join(2000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭资源
if (targetDataLine != null) {
targetDataLine.stop();
targetDataLine.close();
}
try {
if (audioInputStream != null) {
audioInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
// 保存WAV文件
if (byteArrayOutputStream != null && byteArrayOutputStream.size() > 0) {
try {
byte[] audioData = byteArrayOutputStream.toByteArray();
AudioFormat format = new AudioFormat(
SAMPLE_RATE, BITS_PER_SAMPLE, CHANNELS, SIGNED, BIG_ENDIAN
);
ByteArrayInputStream bais = new ByteArrayInputStream(audioData);
AudioInputStream saveStream = new AudioInputStream(
bais, format, audioData.length / format.getFrameSize()
);
AudioSystem.write(saveStream, AudioFileFormat.Type.WAVE, audioFile);
saveStream.close();
System.out.println("录音已保存到: " + audioFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 停止录音但不保存(丢弃数据)
*/
public void stopRecording() {
stopRecordingAndSave(null);
}
}
使用示例(主程序)
import java.io.File;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
AudioRecorder recorder = new AudioRecorder();
Scanner scanner = new Scanner(System.in);
System.out.println("Java录音示例");
System.out.println("输入 'start' 开始录音");
System.out.println("输入 'pause' 暂停/恢复");
System.out.println("输入 'stop' 停止并保存");
System.out.println("输入 'quit' 退出\n");
while (true) {
System.out.print("> ");
String command = scanner.nextLine().trim().toLowerCase();
switch (command) {
case "start":
recorder.startRecording(new File("recording.wav"));
break;
case "pause":
// 简单切换暂停/恢复
recorder.pauseRecording();
break;
case "resume":
recorder.resumeRecording();
break;
case "stop":
recorder.stopRecordingAndSave(new File("recording.wav"));
break;
case "quit":
System.out.println("退出程序");
scanner.close();
return;
default:
System.out.println("未知命令");
}
}
}
}
运行效果
- 启动程序。
- 输入
start→ 录音开始,麦克风开始采集音频。 - 输入
pause→ 暂停采集,输入resume恢复。 - 输入
stop→ 停止录音,在当前目录生成recording.wav文件。 - 可以使用任意播放器(如 Windows Media Player、VLC)播放该WAV文件。
注意事项
| 问题 | 说明 |
|---|---|
| 权限 | 运行程序时需要允许Java进程访问麦克风(部分操作系统会弹窗询问) |
| 格式 | 保存为WAV格式是未压缩的PCM数据,文件体积较大(44.1kHz, 16位单声道约为5MB/分钟) |
| 线程安全 | volatile 和 interrupt 保证了录音线程能正确响应停止指令 |
| 文件覆盖 | 如果多次录音使用同一个文件名,之前的文件会被覆盖 |
| 中文路径 | 建议使用英文路径,避免编码问题 |
扩展方向
- 压缩格式:可使用
javax.sound.sampled结合 JLayer(MP3)或 Java FLAC 等第三方库实现MP3/FLAC格式保存。 - 实时播放:同时使用
SourceDataLine在录音时直接播放(回声/耳返功能)。 - 图形界面:结合Swing/JavaFX开发可视化录音应用。
- 音频处理:对录制的音频数据进行频谱分析、降噪、变声等处理。
这个案例提供了完整、可运行的Java录音实现,适用于桌面应用、语音识别、语音聊天等场景。