FFmpeg:流音频播放列表,标准化响度并生成频谱图和波形

时间:2020-06-07 12:01:25

标签: audio ffmpeg waveform spectrogram

我想使用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过滤器。

对于频谱图,我打算使用showspectrumshowspectrumpic过滤器。由于我希望频谱图“可蒸”,因此我不确定如何执行此操作。也许有一种逐步输出细分的方法?也许有一种方法可以逐步输出某种表示形式(JSON或任何其他格式)?

对于波形,我打算使用showwavesshowwavespic滤波器。此处与频谱图相同,因为输出应为“可流式”。

使用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是否是要使用的正确功能。有提示吗?

1 个答案:

答案 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

请注意,loudnormasplit 过滤器组合成一个过滤器链。来自文档:

<块引用>

过滤器链由一系列连接的过滤器组成,每个过滤器都连接到序列中的前一个。过滤器链由以“,”分隔的过滤器描述列表表示。过滤器图由一系列过滤器链组成。过滤器链序列由以“;”分隔的过滤器链描述列表表示。 [1]

每个 -map 选项选择一个流并将其发送到下一个输出文件或流。所以在这种情况下,[ln] 流被发送到 rtp 流,[ss] 被发送到 ss.png,依此类推。