[FFMPEG]进行音频音量调整

news/2024/7/10 20:53:26 标签: FFMPEG, 音频, 音量, 调整, 平滑, loudnorm滤镜

一、前言

​ 由于我们个人使用的音频和视频数据都是从各个地方获取的,因此其中的音频音量大小不一。而互联网音乐平台如网易云音乐、qq音乐等,几乎所有的音乐音量大小都一致,可能就是使用了音量标准化的方式。

二、正文

​ 当前衡量一个音频音量的常用单位是分贝(db)

1.查看音频分贝

1.1.查看指令

ffmpeg -i 11025.mp3 -filter_complex volumedetect -c:v copy -f null /dev/null

1.2.指令结果

[Parsed_volumedetect_0 @ 0x55ef0a332740] n_samples: 5551838
[Parsed_volumedetect_0 @ 0x55ef0a332740] mean_volume: -17.5 dB
[Parsed_volumedetect_0 @ 0x55ef0a332740] max_volume: 0.0 dB
[Parsed_volumedetect_0 @ 0x55ef0a332740] histogram_0db: 92
[Parsed_volumedetect_0 @ 0x55ef0a332740] histogram_1db: 427
[Parsed_volumedetect_0 @ 0x55ef0a332740] histogram_2db: 1213
[Parsed_volumedetect_0 @ 0x55ef0a332740] histogram_3db: 3159
[Parsed_volumedetect_0 @ 0x55ef0a332740] histogram_4db: 7153

1.3.结果分析

​ 最高分贝(max_volume)为0.0 b,平均分贝(max_volume)为-17.5db

2.音量调整

2.1.基于当前音量倍数处理

<1>将当前音量降低一半:

ffmpeg  -i input.mp3 -filter:a "volume=0.5" output.mp3

<2>将当前音量提升一倍。这种处理相对粗暴,会使音频出现失真现象:

ffmpeg  -i input.mp3 -filter:a "volume=2" output.mp3 

2.2.基于分贝数值的处理

​ 上面基于倍数的处理可能会导致音频失真,而基于分贝数值的处理则相对会保留音频的原声效果

<1>音量提升5分贝(db):

ffmpeg  -i input.mp3 -filter:a "volume=5dB" output.mp3 

<2>音量降低5分贝(db):

ffmpeg  -i input.mp3 -filter:a "volume=-5dB" output.mp3 

3.音量的标准化

​ ffmpeg具备对音量标准化的处理功能,即削峰填谷,使整个音频音量变得平滑

ffmpeg -i input.mp3 -filter:a "loudnorm=i=-14:tp=0.0" output.mp3 

FFMPEGAPI_50">4.调用FFMPEG代码API实现问题记录

4.1.报错“Changing audio frame properties on the fly is not supported”的问题

[in @ 0x7f06f00b0b40] Changing audio frame properties on the fly is not supported.
[in @ 0x7f06f00b0b40] filter context - fmt: s32p r: 8000 layout: 3 ch: 2, incoming frame - fmt: s32p r: 48000 layout: 3 ch: 2 pts_time: NOPTS

​ 问题原因出现在于音频转码时参数被修改了,包括sample_rate,sample_fmt,channel_layout,channels等,我的环境为将采样率由8khz修改为48khz。再看看打印信息“filter context - fmt: s32p r: 8000 layout: 3 ch: 2, incoming frame - fmt: s32p r: 48000 layout: 3 ch: 2 pts_time: NOPTS”,说明设置的filter上下文参数为“fmt: s32p r: 8000 layout: 3 ch: 2”,但实际进来的帧参数为“fmt: s32p r: 48000 layout: 3 ch: 2 pts_time: NOPTS”,可见是filter上下文的采样率®设置错误。
​ 参考FFMPEG源码transcoding.c中设置filter上下文的源码如下:

snprintf(args, sizeof(args),
        "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,
        dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate,
        av_get_sample_fmt_name(dec_ctx->sample_fmt),
        dec_ctx->channel_layout);

​ 什么意思呢?也就是说filter上下文参数和解码参数保持一致,因此将dec_ctx->sample_rate修改为enc_ctx->sample_rate即可解决,其他参数也是一样以此类推。
滤镜信息:
在这里插入图片描述

4.2.报错“more samples than frame size (avcodec_encode_audio2)”

​ 这个问题我遇见过两次,分别为<1>音频mp3转码acc时;<2>使用loudnorm滤镜时。意思是给的采样数量和实际需要的数量不匹配。

4.2.1.音频mp3转码acc时报错

​ 参考文件transcode_aac.c里面的程序,应该很容易能提取出增加fifo来处理的程序,此处不详细展开;

4.2.2.使用loudnorm滤镜

​ 该问题可以采用av_buffersink_set_frame_size来重新设置frame_size来解决,参考ffmpeg.c源码后,写出了以下代码:

	AVFilterGraph *graph=(*filter_ctx)[i].graph;
	if (graph  &&AVMEDIA_TYPE_AUDIO==(*filter_ctx)[i].codec_type) {
		ms_debug("nb_filters:%d", graph->nb_filters);
		int filters_index=0;
		for(filters_index=0;filters_index<graph->nb_filters;filters_index++){
			AVFilterContext *filters=graph->filters[filters_index];
			ms_debug("filters:%s", filters->name);
			if(ms_strncmps_neq(filters->name, "in")&&ms_strncmps_neq(filters->name, "out")){
				if (!(enc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)){
					av_buffersink_set_frame_size(filters, enc_ctx->frame_size);
				}
			}
		}
	}

http://www.niftyadmin.cn/n/1335889.html

相关文章

hibernate 查询字段是重复名字的处理方法

目前遇到了三种情况: 一:当表的字段是数字类型(int,long .....) select name,ifnull(conpih.uh_id,0) from user; 将重复的字段如上修改用ifnull()这个函数. 二:当表的字段是字符串类型(String) SELECT con.*,IFNULL(acceptd.doctname,) from user; 将重复的字段如上修改. 三:…

netplan说明

1.介绍 ​ 发行版安装程序、云实例化、特定设备的镜像或任何其他部署操作系统的方法&#xff0c;都会将其网络配置放入YAML配置文件中。在启动初期&#xff0c;netplan的“network renderer”将读取/{lib,etc,run}/netplan/*.yaml文件&#xff0c;并将配置写入/run&#xff0c…

从零实现Vue的组件库(六)- Hover-Tip 实现

常用于展示鼠标 hover 时的提示信息。 该组件的痛点在于&#xff1a; 纯CSS实现&#xff1b;如何利用slot使组件易扩展&#xff0c;能够适应多种场景。 1. 实例 代码 <!-- 基础用法 --> <fat-hovertip><template slot"hover-part"><fat-button&…

UBUNTU时间同步

从UBUNTU16.04开始&#xff0c;就开始使用timedatectl/timesyncd服务进行时间同步&#xff0c;而不是常用的ntpdate/ntp。如果安装了chrony&#xff0c;那么timedatectl将会让位于chrony&#xff0c;避免两个同步服务出现竞争&#xff0c;这也同样适用于ntpd。 ntpdate已被time…

Win10 Docker 安装mysql8.0

2019独角兽企业重金招聘Python工程师标准>>> 1. 打开 PowerShell 2.搜索mysql镜像 docker search mysql3.下载mysql镜像(默认最新版本) docker pull mysql4. 运行镜像&#xff0c;设置root账号初始密码&#xff08;system123456&#xff09;&#xff0c;映射本地宿主…

最长公共子序列LCS,最长递增子序列LIS

最长公共子序列&#xff1a; 如abcdefg acqweg&#xff0c;最长公共子序列就是aceg&#xff0c;长度为4。子序列是不需要连续的。 详情可看HDU1159。 我们可以根据递推的方式得到最长的长度&#xff0c;如果想得到子序列也只需要记忆化一下每个点是从哪个点递推得到的即可。…

linux(02)基础shell命令

Linux(02)之shell命令 一&#xff0c;Linux命令行的组成结构 在我们的linux启动&#xff0c;登陆成功之后会显示&#xff1a; 这就是linux的命令行的组成结构 二&#xff0c;常见命令 1&#xff0c;Linux系统命令操作语法格式 命令空格参数空格【文件或路径】需要处理的内容rm …

OpenStack DVR 原理深入分析

一、DVR实验环境 一套vlan模式的openstack环境&#xff0c;interface_driver使用openvswitch&#xff0c;并在计算节点添加br-ex&#xff0c;用于计算节点虚拟机出外网。 二、DVR配置 1、控制节点 a、编辑/etc/neutron/neutron.conf[DEFAULT]router_distributed True b、重启n…