四个滤镜能把声音画成图:频谱、波形、相位、音高。 它们都是音频进、视频出,所以挂在中段,不能直接接视频链路。
3.2.2 讲怎么放得稳,这一节讲怎么把「听」变成「看」。 3.2.4 换个方向,讲 VLC 怎么把一个文件变成服务。
一、四个可视化滤镜
这四个都是 ffmpeg 内置的,不需要额外依赖:
滤镜 画出来是什么 看什么
showspectrum 频谱图,横轴时间纵轴频率 能量在哪些频段 showwaves 波形图,随时间起伏 响度包络、有没有削波 avectorscope 左右声道相位图 声道同相还是反相 showcqt 恒定 Q 变换谱 音高与和声结构
注意这四个的输入是音频、输出是视频——它在中间把通道类型换掉了。
所以用法不是 -vf 而是 -filter_complex,要自己写 [0:a]…[v] 这种标记。
第三行那个 avectorscope 值得单独说:它画的是两个声道的相位关系。
如果两个声道完全反相(比如接错线),图形会变成一条斜线——一眼就能看出问题。
二、静音段、响度、削波:三件不开窗口也能查的事
可视化的另一半价值在「不用人看」——这三个滤镜直接给日志:
想查什么 用什么 结果在哪
有没有静音段 silencedetect 日志里给起止时间 响度够不够 ebur128 给 LUFS 值 有没有削波 astats 给峰值与 RMS
这三个的价值在于可以放进自动化流水线:跑完看日志,不需要人盯屏幕。 批量检查几百个音频文件有没有静音段,靠耳朵是干不完的。
第一行的 silencedetect 有两个参数要知道:n 是噪声门限(分贝),d 是最短持续时长。
默认门限很保守,安静但有底噪的素材会漏检,通常要把 n 调到 -40 左右。
三、用它做实验:造一段纯音看看
最容易理解的例子是纯音:440 Hz 的正弦波,在频谱图上就该是一条水平亮线。 位置在纵轴的 440 那一行,宽度很窄——因为能量全集中在一个频率上。
换成真实音乐,那条线就变成一片——因为里面同时有几十个频率在响。 这就是「可视化」最直观的教学价值:把一个抽象参数(频率)变成看得见的位置。
下面 Demo 真的造了一段 440 Hz 纯音,并用 showspectrum 把它算成画面存下来。 注意这一步的输入是音频包、输出是视频帧——中间那次「通道类型切换」就是它的本质。
四、动手 Demo:把声音画成图
造一段 1 秒 440 Hz 立体声纯音,再用 showspectrum 把它算成频谱图。 输入是音频帧、输出是视频帧,这一步验证的是「音频进视频出」这条链路。
import os
import av
import numpy as np
# 造 1 秒 440 Hz 立体声
SR = 44100
t = np.arange(SR) / float(SR)
sig = (0.5 * np.sin(2 * np.pi * 440 * t) * 32767).astype(np.int16)
st = np.stack([sig, sig], axis=1).reshape(-1)
c = av.open(u"tone.m4a", u"w")
s = c.add_stream(u"aac", rate=SR)
s.layout = u"stereo"
fr = av.AudioFrame(format=u"s16", layout=u"stereo", samples=SR)
fr.sample_rate = SR
fr.planes[0].update(st.tobytes())
for pk in s.encode(fr):
c.mux(pk)
for pk in s.encode(None):
c.mux(pk)
c.close()
# 音频进、视频出:中间换了一次通道类型
c = av.open(u"tone.m4a")
g = av.filter.Graph()
src = g.add_abuffer(template=c.streams.audio[0])
sp = g.add(u"showspectrum", u"s=320x180:mode=combined:slide=scroll")
snk = g.add(u"buffersink")
src.link_to(sp)
sp.link_to(snk)
g.configure()
got = 0
for f in c.decode(audio=0):
g.push(f)
while True:
try:
vf = g.pull()
got += 1
except (av.BlockingIOError, av.EOFError):
break
if got >= 3:
break
vf.to_image().save(u"spectrum.png")
c.close()
print(u"产出 %d 帧 %dx%d,PNG %d 字节"
% (got, vf.width, vf.height, os.path.getsize(u"spectrum.png")))
实跑输出:
--------------------------------------------------------------------
ffplay 的数据可视化——把声音画成图
--------------------------------------------------------------------
**① 四个可视化滤镜,各画一种东西**
滤镜 画出来是什么 看什么
--------------------------------------------------------------------------
showspectrum 频谱图,横轴时间纵轴频率 能量分布在哪些频段
showwaves 波形图,随时间起伏 响度包络、有没有削波
avectorscope 左右声道相位图 声道是否同相、有没有抵消
showcqt 恒定 Q 变换谱 音高与和声结构
**这四行都是「音频进、画面出」,所以它们的输出是一路视频流。**
**用法就是 `ffplay 输入 -vf showspectrum`——边放边看,不落盘。**
**② 本机造一段 440 Hz 正弦波,看它落在哪个位置**
项 值
--------------------------------
样本数 44100(1 秒)
裸数据 176400 字节
AAC 压缩后 17360 字节
**压缩比 10.2 倍,解出 45 个音频帧。**
**一个 440 Hz 的纯音,在频谱图上应该是一条水平亮线——位置就在 440 那一行。**
**③ 把频谱图真的算出来,看它出的是什么**
项 值
----------------------------
产出视频帧 5 帧
画面尺寸 320x180
存成 PNG 1729 字节
**注意输入是音频、输出是视频——这个滤镜在中间把通道换掉了。**
**所以它必挂在中段,前后要分别接 abuffer 和 buffersink,不能直接接视频链路。**
**④ 这套东西真正的用处:不开播放器也能查音频**
想查什么 用什么 怎么读结果
-----------------------------------------------------------
有没有静音段 silencedetect 日志里直接给起止时间
响度够不够 ebur128 给 LUFS 值
有没有削波 astats 给峰值与 RMS
**这三行都不需要人看画面,命令行跑完看日志就行——适合放进自动化流水线。**
**所以 3.2.3 这一节的标题虽然叫「可视化」,实际价值一半在「让机器读懂音频」。**
add_abuffer 的 a 是 audio,buffersink 是通用出口。
中间那个 showspectrum 把音频帧吃进去、吐视频帧出来——所以这条链两头类型不同。
s=320x180 是输出画面尺寸,mode=combined 是把声道合并显示。
想看左右声道分别的频谱就换成 mode=separate,画面会被切成上下两半。
slide=scroll 是滚动模式,新的画在右边、旧的往左推。
所以最终那张 PNG 是一段时间的累积,不是某一瞬间的快照。
一条 440 Hz 的纯音画出来应该是一条几乎水平的亮线。 如果画出来是一片模糊,八成是采样率或频率参数填错了——这正是它的诊断价值。
30 秒实验
- 看频谱:
ffplay 音乐.mp3 -vf showspectrum=s=640x360,边听边看能量分布。 - 查静音:
ffmpeg -i 音频.wav -af silencedetect=n=-40dB:d=2 -f null -,日志里给静音起止。 - 查响度:
ffmpeg -i 音频.wav -af ebur128 -f null -,末尾给出整合响度 LUFS。
常见误区
- 用
-vf挂可视化滤镜。它们输入是音频、输出是视频,类型不匹配。要用-filter_complex自己写标记。 - 以为频谱图是一瞬间的快照。
slide=scroll模式下它是累积的,横轴是时间。 - silencedetect 用默认门限就下结论。默认很保守,有底噪的素材会漏检,通常要调到 -40dB 左右。
自测三问(点开对答案)
1. 为什么可视化滤镜不能用 `-vf` 挂? —— 因为它们输入是音频、输出是视频,`-vf` 那条链路两端都是视频。类型不匹配,必须用 `-filter_complex`。 2. 一条 440 Hz 纯音的频谱图应该长什么样? —— 一条几乎水平的亮线,位置在纵轴 440 附近。能量集中在一个频率上,所以线很窄。 3. 哪三个滤镜能不开窗口就查出音频问题? —— silencedetect 查静音段、ebur128 查响度、astats 查削波。它们都靠日志出结果,适合自动化。- ☐ (本节完,下一节 3.2.4 VLC 作为 RTSP 流媒体服务器)