ffmpeg音频处理-java实现

音频响度归一化

概述

FFmpeg的loudnorm滤镜 是一个实现了EBU R128标准的音频响度(loudness)归一化滤镜。在音频领域中,响度是指音频的感知音量水平,这与音量的技术度量(比如分贝)略有不同。响度归一化旨在调整音频轨道的响度,使得它们在不同的播放环境下提供一致的听觉体验。

使用loudnorm滤镜可以自动将音频调整到指定的响度目标,符合广播行业对响度的标准化要求。该滤镜特别有用于处理可能响度不一致的多个音频文件,比如电视节目、电影、广告和音乐。

EBU R128是欧洲广播联盟制定响度标准的推荐实践。该标准建议的流行音乐响度目标级别为-16 LUFS(Loudness Units Full Scale),而loudnorm滤镜能够根据此标准自动调节音频轨道。

loudnorm滤镜参数

loudnorm滤镜具有许多参数,可以对响度的整个归一化过程进行详细配置。以下是loudnorm常用参数:

  • I:设置集成响度(Integrated Loudness)目标,默认值为-24 LUFS。
  • LRA:设置响度范围(Loudness Range)目标,用于捕捉音频信号的动态范围,默认值为7 LU。
  • TP:设置真峰目标(True Peak),默认值为-2.0 dBTP(分贝相对于True Peak)。
  • measured_I、measured_LRA、measured_TP、measured_thresh:这些参数通常由第一次运行loudnorm滤镜时生成,用于在双遍响度归一化过程中的第二遍中使用。

代码

java 复制代码
    /**
     * 使用 FFmpeg 对音频文件进行标准化处理
     *
     * @param inputFilePath  输入音频文件路径
     * @param outputFilePath 输出音频文件路径
     * @param targetLoudness 目标响度级别,以 LUFS 为单位 (例如流行音乐 -16)
     * @param loudnessRange  响度范围调整 (例如 11)
     * @throws IOException 如果在执行 FFmpeg 命令时发生 IO 错误
     */
    public static void normalizeAudio(String inputFilePath, String outputFilePath, double targetLoudness, double loudnessRange) throws IOException {

        String command = String.format(
                "ffmpeg -i %s -f mp3 -af \"loudnorm=I=%.1f:LRA=%.1f\" %s",
                inputFilePath, targetLoudness, loudnessRange, outputFilePath
        );

        // 执行命令
        Process process = Runtime.getRuntime().exec(command);

        // 读取错误输出
        Thread errorThread = new Thread(() -> {
            try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                String line;
                while ((line = errorReader.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        errorThread.start();

        // 检查命令是否成功执行
        try {
            errorThread.join();
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                throw new IOException("FFmpeg 命令执行失败,退出代码: " + exitCode);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("FFmpeg 命令执行被中断", e);
        }
    }

加强音频人声频段

概述

FFmpeg的equalizer(均衡器)滤镜是一个强大的音频滤波器,用于调节音频信号中各个频率的增益。通过操控不同频率的增益,均衡器可以提升或衰减音频信号中特定频段的音量,从而改变音频的整体音色或突出某些频率范围。均衡器滤镜常用于音频处理,如增强人声、去除背景噪声或调整音乐音色,以达到更好的听觉效果。

equalizer滤镜参数

equalizer滤镜提供了多个参数,允许用户精确地调节音频频谱的各个部分。以下是equalizer滤镜的常用参数:

  • f:设置要调整的频率(以Hz为单位)。这个参数指定了希望增强或削弱的中心频率。
  • width_type:设置频率带宽的类型,可以选择q(品质因数)、h(赫兹)、或o(八度)。带宽决定了受影响的频率范围的宽度。
  • width:设置频率带宽的数值,取决于width_type的选择。对于o类型,width的值表示影响的八度数。
  • g:设置频率的增益(以dB为单位),正值表示增强该频率,负值表示削弱该频率。

代码

java 复制代码
   /**
     * 使用 FFmpeg 加强人声频段
     *
     * @param inputFilePath  输入音频文件路径
     * @param outputFilePath 输出音频文件路径
     * @throws IOException 如果在执行 FFmpeg 命令时发生 IO 错误
     */
    public static void enhanceVocalRange(String inputFilePath, String outputFilePath) throws IOException {
        // FFmpeg 命令,使用均衡器滤镜增强人声频段
        String command = String.format(
                "ffmpeg -i %s -af \"equalizer=f=300:width_type=o:width=2:g=5, " +
                        "equalizer=f=1000:width_type=o:width=2:g=10, " +
                        "equalizer=f=3000:width_type=o:width=2:g=10\" %s",
                inputFilePath, outputFilePath
        );

        // 执行命令
        Process process = Runtime.getRuntime().exec(command);

        // 读取错误输出
        Thread errorThread = new Thread(() -> {
            try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                String line;
                while ((line = errorReader.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        errorThread.start();

        // 检查命令是否成功执行
        try {
            errorThread.join();
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                throw new IOException("FFmpeg 命令执行失败,退出代码: " + exitCode);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("FFmpeg 命令执行被中断", e);
        }
    }

获取音频音量信息

概述

FFmpeg的volumedetect滤镜是一个用于检测音频文件中音量信息的滤镜。通过分析音频文件,volumedetect能够提供详细的音量统计数据,包括最大音量、平均音量和音量峰值等。这些信息对于音频处理和后期制作非常有用,可以帮助工程师了解音频文件的动态范围和响度水平,从而做出相应的调整,如音量归一化、动态范围压缩等。

volumedetect滤镜输出信息

volumedetect滤镜本身不需要复杂的参数配置,使用非常简便。以下是该滤镜的输出信息及其含义:

  • mean_volume:表示音频文件的平均音量(以dB为单位)。
  • max_volume:表示音频文件的最大音量(以dB为单位),即音频中响度最高的部分。
  • min_volume:表示音频文件的最小音量(以dB为单位),通常出现在音频文件的安静部分。
  • max_volume:表示音频文件的最大峰值(以dB为单位),这个值对于防止音频过载(剪切)非常重要。

代码

java 复制代码
    /**
     * 获取音频文件的音量信息
     *
     * @param filePath 音频文件路径
     * @throws IOException 如果在执行 FFmpeg 命令时发生 IO 错误
     */
    public static void printAudioVolumeInfo(String filePath) throws IOException {
        String command = String.format("ffmpeg -i %s -af volumedetect -f null -", filePath);

        Process process = Runtime.getRuntime().exec(command);

        Thread errorThread = new Thread(() -> {
            try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                String line;
                while ((line = errorReader.readLine()) != null) {
                    if (line.contains("Parsed_volumedetect")) {
                        System.out.println(line);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        errorThread.start();

        try {
            errorThread.join();
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                throw new IOException("FFmpeg 命令执行失败,退出代码: " + exitCode);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("FFmpeg 命令执行被中断", e);
        }
    }
相关推荐
考虑考虑5 小时前
Jpa使用union all
java·spring boot·后端
用户3721574261356 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊7 小时前
Java学习第22天 - 云原生与容器化
java
渣哥9 小时前
原来 Java 里线程安全集合有这么多种
java
间彧9 小时前
Spring Boot集成Spring Security完整指南
java
间彧9 小时前
Spring Secutiy基本原理及工作流程
java
Java水解10 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆12 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学13 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole13 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端