我是一名音乐人,兼职做一些编程,所以能力有限,请见谅。
有时我需要多个音频文件的 LUFS 级别,最快的方法(对我来说......)是使用 ffmpeg 来计算,因为它可以在几秒钟内离线播放一个文件,而不必全部播放在 DAW 中进行读出。
这是我想出的脚本:
#!/bin/zsh
TempDirectory="~/Desktop/TEMP"
TempRAW="$TempDirectory/ffmpeg_LUFS_output_RAW.txt"
OutputCSV="$TempDirectory/ffmpeg_LUFS_output.csv"
for CurrentFile in "$@"
do
echo "File: "$(/usr/bin/basename "$CurrentFile") >>"$TempRAW"
/opt/homebrew/bin/ffmpeg -i "$CurrentFile" -hide_banner -af ebur128=framelog=verbose -f null - 2>>"$TempRAW"
done
# The next part extracts the info from the raw ffmpeg output file
# The output from ffmpeg is 55 lines
# Line 1: File: LSK Adore v18 [Dreamy] MIX ALL Stereo.wav
# ... snip ...
# Line 47: Integrated loudness:
# Line 48: I: -32.2 LUFS
# Line 49: Threshold: -42.6 LUFS
#
# The lines that interest me are Line 1 + 48:
while IFS= read -r line
do
if [[ "$line" =~ ^"File: " ]]; then
printf "$line," | sed 's/File: //' >>"$OutputCSV"
fi
if [[ "$line" =~ ^" I:" ]]; then
echo "$line" | sed 's/ I: //'>>"$OutputCSV"
fi
done < "$TempRAW"
Run Code Online (Sandbox Code Playgroud)
它有效,我的问题得到了解决,我的能力允许我解决它。
但我宁愿不必编写临时文件。
当我写这篇文章时,我搜索了至少 4 个小时的解决方案。他们中的大多数人解释了如何使用 awk 处理存储在变量中的 ffmpeg 输出。但是 awk 总是会为第一个条目创建双倍的结果(我可能做错了什么......)。
如果没有临时文件,我该如何编写呢?
以下是输出的更多示例行:
File: LSK Adore v18 [Dreamy] MIX ALL Stereo.wav
Guessed Channel Layout for Input Stream #0.0 : stereo
Input #0, wav, from '/Volumes/Project HDD/Leopard Skin/Themes/Bounces/LSK Adore v18 STEMS 78bpm/LSK Adore v18 [Dreamy] MIX ALL Stereo.wav':
Metadata:
encoded_by : Logic Pro X
originator_reference: aaO3N!Fzk7Rk
date : 2021-05-24
creation_time : 18:48:28
time_reference : 276258449
...
SNIP
...
size= 0kB time=00:00:00.00 bitrate=N/A speed=N/A
size=N/A time=00:01:49.21 bitrate=N/A speed= 766x
video:0kB audio:20481kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
[Parsed_ebur128_0 @ 0x153f0af90] Summary:
Integrated loudness:
I: -32.2 LUFS
Threshold: -42.6 LUFS
Loudness range:
LRA: 4.9 LU
Threshold: -52.7 LUFS
LRA low: -34.5 LUFS
LRA high: -29.6 LUFS
Run Code Online (Sandbox Code Playgroud)
这可以通过单个循环来完成。一种方法是:
for CurrentFile in "$@"; do
printf '%s,' "${CurrentFile##*/}"
ffmpeg -i "$CurrentFile" -hide_banner -af ebur128=framelog=verbose -f null - 2> >(sed -n 's/^[[:blank:]]*I:[[:blank:]]*//p')
done > "$OutputCSV"
Run Code Online (Sandbox Code Playgroud)