我想使用FFmpeg播放包含多个音频文件(主要是FLAC和MP3)的播放列表。在播放期间,我希望FFmpeg标准化音频信号的响度,并分别生成音频信号的频谱图和波形。频谱图和波形应充当音频流监视器。最终的音频流,频谱图和波形输出将被发送到浏览器,该浏览器播放音频流并连续呈现频谱图和波形“图像”。我还希望能够在播放期间从播放列表中删除和添加音频文件。
第一步,在尝试编写以编程方式执行相同操作的代码之前,我想使用ffmpeg
命令获得所需的结果。
(旁注:我发现libgroove
基本上可以满足我的要求,但是我想了解FFmpeg的内部原理并编写自己的软件。目标语言是Go,并使用{{ 3}}或goav
库可以完成此工作,但是,我最终可能会用C编写代码,然后从C创建Go语言绑定,而不是依赖于其中一个命名库。
这里有一些概述:
playlist (input) --> loudnorm --> split --> spectrogram --> separate output
|
split ---> waveform ----> separate output
|
+------> encode ------> audio stream output
对于响度归一化,我打算使用实现EBU R128算法的loudnorm
过滤器。
对于频谱图,我打算使用showspectrum
或showspectrumpic
过滤器。由于我希望频谱图“可蒸”,因此我不确定如何执行此操作。也许有一种逐步输出细分的方法?也许有一种方法可以逐步输出某种表示形式(JSON或任何其他格式)?
对于波形,我打算使用showwaves
或showwavespic
滤波器。此处与频谱图相同,因为输出应为“可流式”。
使用ffmpeg
命令来实现我想要的功能有点麻烦。这是我到目前为止的内容:
ffmpeg \
-re -i input.flac \
-filter_complex "
[0:a] loudnorm [ln]; \
[ln] asplit [a][b]; \
[a] showspectrumpic=size=640x518:mode=combined [ss]; \
[b] showwavespic=size=1280x202 [sw]
" \
-map '[ln]' -map '[ss]' -map '[sw]' \
-f tee \
-acodec libmp3lame -ab 128k -ac 2 -ar 44100 \
"
[aselect='ln'] rtp://127.0.0.1:1234 | \
[aselect='ss'] ss.png | \
[aselect='sw'] sw.png
"
当前,出现以下错误:
Output with label 'ln' does not exist in any defined filter graph, or was already used elsewhere.
此外,我不确定aselect
是否是要使用的正确功能。有提示吗?
答案 0 :(得分:1)
你已经很接近了。我认为 aselect
不正确;它选择帧发送到输出,而不是流。试试这个:
ffmpeg \
-re -i input.flac \
-filter_complex "
[0:a] loudnorm , asplit=3 [a][b][ln];
[a] showspectrumpic=size=640x518:mode=combined [ss];
[b] showwavespic=size=1280x202 [sw]
" \
-map '[ln]' -acodec libmp3lame -ab 128k -ac 2 -ar 44100 -f rtp 'rtp://127.0.0.1:1234' \
-map '[ss]' ss.png \
-map '[sw]' sw.png
请注意,loudnorm
和 asplit
过滤器组合成一个过滤器链。来自文档:
过滤器链由一系列连接的过滤器组成,每个过滤器都连接到序列中的前一个。过滤器链由以“,”分隔的过滤器描述列表表示。过滤器图由一系列过滤器链组成。过滤器链序列由以“;”分隔的过滤器链描述列表表示。 [1]
每个 -map
选项选择一个流并将其发送到下一个输出文件或流。所以在这种情况下,[ln]
流被发送到 rtp
流,[ss]
被发送到 ss.png
,依此类推。