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

Posted

技术标签:

【中文标题】FFmpeg:流式音频播放列表,标准化响度并生成频谱图和波形【英文标题】:FFmpeg: stream audio playlist, normalize loudness and generate spectrogram and waveform 【发布时间】:2020-06-07 12:01:25 【问题描述】:

我想使用 FFmpeg 流式传输包含多个音频文件(主要是 FLAC 和 MP3)的播放列表。在播放过程中,我希望 FFmpeg 对音频信号的响度进行归一化,并分别生成音频信号的频谱图和波形。频谱图和波形应用作音频流监视器。最终的音频流、频谱图和波形输出将被发送到浏览器,浏览器播放音频流并连续渲染频谱图和波形“图像”。我还希望能够在播放期间从播放列表中删除和添加音频文件。

作为第一步,我想使用ffmpeg 命令来实现所需的结果,然后我将尝试编写以编程方式执行相同操作的代码。

(旁注:我发现 libgroove 基本上可以满足我的需求,但我想了解 FFmpeg 内部结构并编写自己的软件。目标语言是 Go 并使用 goavgo-libav 库可能会完成这项工作。但是,我最终可能会用 C 编写代码,然后从 C 创建 Go 语言绑定,而不是依赖于其中一个命名库。)

这里有一个小概述:

playlist (input) --> loudnorm --> split --> spectrogram --> separate output
                                    |
                                  split ---> waveform ----> separate output
                                    |
                                    +------> encode ------> audio stream output

对于响度归一化,我打算使用 loudnorm 滤波器,它实现了 EBU R128 算法。

对于频谱图,我打算使用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】:

你已经很接近了。我不认为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,以此类推。

【讨论】:

以上是关于FFmpeg:流式音频播放列表,标准化响度并生成频谱图和波形的主要内容,如果未能解决你的问题,请参考以下文章

将音频流式传输到多个 Web 浏览器

是否可以使用 ffmpeg 从 ASIO 设备捕获音频?

有没有办法分析视频以找出它的响度,然后将其纠正为 ebu r128

使用 FFMPEG 流式传输 YouTube 音频的示例

fluent-ffmpeg 使用流式提取音频

iOS利用FFmpeg解码音频数据并播放