Java案例如何实现录音?

wen python案例 2

本文目录导读:

Java案例如何实现录音?

  1. 核心思路
  2. 完整代码示例
  3. 使用示例(主程序)
  4. 运行效果
  5. 注意事项
  6. 扩展方向

在Java中实现录音功能,最常用的方式是使用 javax.sound.sampled 包,它是Java标准库自带的音频处理API,无需额外引入第三方库即可完成基本的录音和播放功能。

下面是一个完整的Java录音案例,包含录音、保存音频文件(WAV格式)以及播放录音的功能。


核心思路

  1. 获取音频输入设备:通过 AudioSystem.getTargetDataLine() 获取麦克风等音频输入设备。
  2. 定义音频格式:设置采样率、采样位数、声道数等参数。
  3. 开始录音:打开数据线,启动音频数据读取线程,将数据写入内存或直接写入文件。
  4. 停止录音:关闭数据线,停止线程。
  5. 保存文件:将捕获的音频数据写入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("未知命令");
            }
        }
    }
}

运行效果

  1. 启动程序。
  2. 输入 start → 录音开始,麦克风开始采集音频。
  3. 输入 pause → 暂停采集,输入 resume 恢复。
  4. 输入 stop → 停止录音,在当前目录生成 recording.wav 文件。
  5. 可以使用任意播放器(如 Windows Media Player、VLC)播放该WAV文件。

注意事项

问题 说明
权限 运行程序时需要允许Java进程访问麦克风(部分操作系统会弹窗询问)
格式 保存为WAV格式是未压缩的PCM数据,文件体积较大(44.1kHz, 16位单声道约为5MB/分钟)
线程安全 volatileinterrupt 保证了录音线程能正确响应停止指令
文件覆盖 如果多次录音使用同一个文件名,之前的文件会被覆盖
中文路径 建议使用英文路径,避免编码问题

扩展方向

  • 压缩格式:可使用 javax.sound.sampled 结合 JLayer(MP3)或 Java FLAC 等第三方库实现MP3/FLAC格式保存。
  • 实时播放:同时使用 SourceDataLine 在录音时直接播放(回声/耳返功能)。
  • 图形界面:结合Swing/JavaFX开发可视化录音应用。
  • 音频处理:对录制的音频数据进行频谱分析、降噪、变声等处理。

这个案例提供了完整、可运行的Java录音实现,适用于桌面应用、语音识别、语音聊天等场景。

抱歉,评论功能暂时关闭!