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);
        }
    }
相关推荐
lizi8888827 分钟前
单组件的编写
java
java_heartLake30 分钟前
设计模式之代理模式
java·设计模式·代理模式
魏 无羡1 小时前
pgsql 分组查询方法
java·服务器·数据库
兩尛1 小时前
java--面向对象编程(中级部分)
java·开发语言
青柠视频云2 小时前
青柠视频云——记一次大华摄像头公网语音对讲失败的问题分析
音视频·webrtc·实时音视频·h.265·h.264
Xxxx. .Xxxx2 小时前
C语言程序设计实验与习题指导 (第4版 )课后题-第二章+第三章
java·c语言·开发语言
姜西西_2 小时前
[Spring]Spring MVC 请求和响应及用到的注解
java·spring·mvc
逸狼2 小时前
【JavaEE初阶】多线程6(线程池\定时器)
java·开发语言·算法
qq_35323353892 小时前
【原创】java+springboot+mysql科研成果管理系统设计与实现
java·spring boot·mysql·mvc·web
dawn1912282 小时前
SpringMVC 入门案例详解
java·spring·html·mvc