使用 SoX 更改音频文件中某个时间范围的音量级别
Posted
技术标签:
【中文标题】使用 SoX 更改音频文件中某个时间范围的音量级别【英文标题】:Using SoX to change the volume level of a range of time in an audio file 【发布时间】:2013-11-21 16:52:09 【问题描述】:我想使用 SoX 更改音频文件中特定时间范围/片段的音量。
现在,我必须:
-
将原文件修剪三遍得到:音效变化前的部分,变化中的部分(我正在改变声级的部分),以及之后的部分
执行效果以更改提取的“中间”音频块的声音级别,在其自己的文件中
将所有内容重新拼接在一起,考虑到 SoX 建议的淡入淡出/交叉淡入淡出 5ms 重叠
有没有更好的方法来做到这一点,而无需编写脚本来执行上述操作?
【问题讨论】:
您找到更好的解决方案了吗?刚刚得到了类似的任务,你描述的解决方案似乎是唯一可能的。 @jdevelop 不,遗憾的是:(我最终不得不做我上面描述的事情。编写解决方案的脚本最终没问题。 我意识到可以用 ffmpeg 和 -filter_complex 来完成 【参考方案1】:对于任何偶然发现这个排名靠前的主题的人,寻找一种避开音频文件中间的方法:
我已经使用 SoX 多年了,我构建的方法使用管道来处理每个部分 而不会创建所有这些临时文件!
结果是单行解决方案,尽管您需要设置时间等,除非您的淡入淡出时间对于所有文件都相同,否则使用算法生成行可能很有用。
我很高兴能够让管道正常工作,因为我知道这方面对其他人来说很困难。命令行选项可能很难正确设置。但是我真的不喜欢凌乱的附加文件作为替代方案。
通过使用混合功能并使用 pad 定位每个部分,然后对每个部分进行修剪和淡化,我们也可以避免在此处使用“拼接”。我真的不是粉丝。
一个有效的单行示例,在 SoX 14.4.2 Windows 中测试:
它在 2 秒时衰减(降低)-6dB,在 5 秒时恢复到 0dB(使用 0.4 秒的线性衰减):
sox -m -t wav "|sox -V1 inputfile.wav -t wav - fade t 0 2.2 0.4" -t wav "|sox -V1 inputfile.wav -t wav - trim 1.8 fade t 0.4 3.4 0.4 gain -6 pad 1.8" -t wav "|sox -V1 inputfile.wav -t wav - trim 4.8 fade t 0.4 0 0 pad 4.8" outputfile.wav gain 9.542
让我们将其分解为多个部分,使其更具可读性:
第 1 部分 = 全音量,第 2 部分 = 闪避,第 3 部分 = 全音量
sox -m
-t wav "|sox -V1 inputfile.wav -t wav - fade t 0 2.2 0.4"
-t wav "|sox -V1 inputfile.wav -t wav - trim 1.8 fade t 0.4 3.4 0.4 gain -6 pad 1.8"
-t wav "|sox -V1 inputfile.wav -t wav - trim 4.8 fade t 0.4 0 0 pad 4.8"
outputfile.wav gain 9.542
现在,非常彻底地分解它
'-m' .. 表示我们要混音(这会自动降低增益,请参阅最后一个参数)
'-t wav' .. 表示后面的管道命令将返回一个 WAV(似乎 WAV 标头在管道中丢失了)
然后.. FIRST 管道部分(鸭子之前的全音量)
'-V1' .. 表示忽略警告 - 当它正在输出时,会有一个关于不知道该特定部分的输出文件长度的警告,但应该没有其他警告操作
然后输入文件名
'-t wav' .. 强制输出类型
'-' .. 是将返回到 SoX 命令行的管道输出的标准名称
'fade t 0 2.2 0.4' .. 淡出整个音量部分。 t = 线性。 0 淡入。然后(因为我们希望交叉淡入淡出的中间点为 2 秒)我们淡出 2.2 秒,淡入淡出 0.4 秒(淡出参数用于淡入淡出结束的时间!)
'-t wav' .. 建议下一部分的类型 - 如上所述
然后.. 第二个管道部分(回避部分)
'-V1' .. 再次忽略输出长度警告 - 见上文 然后是相同的输入文件名
'-t wav' .. 强制输出类型,如上
'-' .. 对于管道输出,见上文
'trim 1.8' .. 因为这个中间部分将在 2 秒时到达过渡的中间,所以(使用 0.4 秒的交叉淡入淡出)闪避的音频文件将在此之前 0.2 秒开始
'fade t 0.4 3.4 0.4' .. 淡入闪避部分并再次淡出。所以 0.4 淡入。然后(最复杂的部分)因为下一个交叉淡入淡出将在 5.2 秒结束,我们必须将该数字减去该部分的修剪量,所以 5.2-1.8=3.4(这也是因为淡出位置处理淡出结束时间)
'gain -6' .. 是我们应该回避的量,以 dB 为单位
'pad 1.8' .. 必须与上面的修剪图相匹配,以便在开始时插入静音量以使其在混合部分时同步
'-t wav' .. 建议下一部分的类型 - 如上所述
然后.. 第三个管道部分(返回完整级别)
'-V1' .. 再次 - 见上文
然后输入相同的文件名
-t wav' .. 强制输出类型,如上
-' .. 对于管道输出,见上文
trim 4.8' .. 这最后一部分将从 5 秒开始,但(使用 0.4 秒交叉淡入淡出)音频将在此之前 0.2 秒开始
'fade t 0.4 0 0' .. 只是淡入到这个完整的音量部分。没有淡出
'pad 4.8' .. 必须与上面的修剪图相匹配,如上所述 然后输出文件名
'gain 9.542' .. 看起来很棘手,但基本上当您“-m”混合 3 个文件时,SoX 会将音量降低到 1/3(三分之一)以留出余量。
我们没有打败它,而是提升到 300%。我们用这个公式 20*log(3)/log(10) 得到 9.542 的 dB 量
如果您将单行复制并粘贴到您可以轻松看到的地方,它就没有解释那么可怕了!
虽然最终 - 我最初担心交叉淡入淡出是否需要对数而不是线性,但就我而言,从聆听结果来看,线性肯定给出了我预期的声音。
您可能想尝试更长的交叉淡入淡出,或者让过渡点早晚发生,但我希望单行给那些认为需要许多临时文件的人带来希望!
让我知道是否有更多的说明会有所帮助!
audacity waveform
【讨论】:
很棒的答案!谢谢:D 您可以在子命令中使用-p
代替-t wav -
,并删除子命令前的-t wav
。这也将消除警告,因此您不必忽略它们:sox -m "|sox inputfile.wav -p fade ..." "|sox inputfile.wav -p trim ..." ...
要真正将音量淡化以完成静音,上述代码sn-p中的增益应该从-6更改为-40。【参考方案2】:
好的,使用 ffmpeg 和过滤器就很简单了。
假设您有 2 首曲目,A 和 B。您想要裁剪其中的曲目并对音量进行一些处理。所以解决方案是:
ffmpeg -y -i 1.mp3 -i 2.mp3 i f454495482c151aea8761dda.mp3 -i f5544954796af4a171f11b57.mp3 -i f754495448788e35e6123679.mp3 -i f754495448788e35e6123679.mp3 -i f85449545e646dea98e5dd19.mp3 \
-filter_complex "[0]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,volume='if(between(t,129.00,129.20),0.15000*(t - 129.00) + 0.03,1)':eval=frame,volume='if(between(t,129.20,181.50),-0.00057*(t - 129.20) + 0.06,1)':eval=frame,volume='if(between(t,181.50,181.60),0.40000*(t - 181.50) + 0.03,1)':eval=frame,volume='if(between(t,181.60,183.50),-0.03684*(t - 181.60) + 0.07,1)':eval=frame,volume='if(between(t,183.50,188.00),0.00000*(t - 183.50) + 0.00,1)':eval=frame,atrim=0.00:56.00,adelay=129000|129000|129000|129000,apad[0:o];[1]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,volume='if(between(t,0.00,134.00),0.00000*(t - 0.00) + 0.06,1)':eval=frame,atrim=0.00:134.00,apad[1:o];[0:o][1:o]amix=inputs=28,atrim=duration=185.00" -shortest -ac 2 output.mp3
这将采用 2 个输入文件,将两个流转换为适当的 aformat,然后应用 volume 过滤器。
volume 的语法很简单:如果时间 t 是 介于 一些 start 和 end 时间 - 然后应用音量过滤器,基于所需的开始音量级别加上某个系数乘以开始时间和当前时间之间的差异t。
这会将音量从初始音量线性增加到某个范围内的所需值。
atrim 将在所有范围内调整音量后修剪音频块。
ffmpeg 真是太棒了,表达式可能非常复杂,表达式中可以使用许多数学函数。
【讨论】:
这种方法看起来很有趣,但它使用的是 ffmpeg,而且在命令行上看起来也很复杂。无论如何,我都会给你答案,但如果这个答案是用 shell 变量或其他东西扩展的,那么阅读起来会更好。无论如何感谢这里的答案!很高兴看到这个谜团终于结束了。 好吧,我花了 2 天时间才深入研究那个神秘的 -filter-complex 东西。我已经简化了命令行(您不想看到应用了复杂过滤器的 27 个 mp3 文件的样子 - 总共大约 10 KB :))如果您还有其他问题 - 请拍摄。以上是关于使用 SoX 更改音频文件中某个时间范围的音量级别的主要内容,如果未能解决你的问题,请参考以下文章