FFmpeg音视频,多媒体,编解码

FFmpeg 通过 showwavespic 获取音频的频谱图

2018-12-01  本文已影响18人  GeorgeMR

FFmpeg 的 showwavespic 滤镜如何得到频谱图

音频数据通常由波形图像表示。

FFmpeg 通过使用 showwavespic 可以得到音频数据的频谱图

ffmpeg -i input -filter_complex "showwavespic=s=640x120" -frames:v 1 output.png

运行上面一条命令之后,即可得到一张如下的图片:

output.png

那么 FFmpeg 是如何将音频数据转换为波形图的呢?

首先通过命令我们知道使用了名为showwavespic 的滤镜,根据名字大概猜想此滤镜就是生成频谱图的关键所在。

所以,我么直接定位到 showwavespic 的定义处:

// showwavespic 滤镜的输入
static const AVFilterPad showwavespic_inputs[] = {
    {
        .name         = "default",
        .type         = AVMEDIA_TYPE_AUDIO,
        .config_props = showwavespic_config_input, 
        .filter_frame = showwavespic_filter_frame, 
    },
    { NULL }
};

// showwavespic 滤镜的输出
static const AVFilterPad showwavespic_outputs[] = {
    {
        .name          = "default",
        .type          = AVMEDIA_TYPE_VIDEO,
        .config_props  = config_output,  // 配置下一个滤镜的相关参数(例如输出frame 的宽、高)
        .request_frame = request_frame,
    },
    { NULL }
};

AVFilter ff_avf_showwavespic = {
    .name          = "showwavespic", // 输入的音频转换为频谱图输出
    .description   = NULL_IF_CONFIG_SMALL("Convert input audio to a video output single picture."),
    .init          = init,          // 初始化方法
    .uninit        = uninit,        
    .query_formats = query_formats, // 滤镜支持的格式
    .priv_size     = sizeof(ShowWavesContext),
    .inputs        = showwavespic_inputs,
    .outputs       = showwavespic_outputs,
    .priv_class    = &showwavespic_class,
};

通过参考其他资源,理清楚滤镜的工作流程。花费几天的时间阅读 FFmpeg 的源码,生成波形图的原理 -- 解码音频文件得到音频裸数据 —> 通过 showwavespic 滤镜处理PCM数据得到波形图

showwavespic 滤镜是如何处理 PCM 数据得到波形图的呢?

PCM 数据

首先我们要了解什么是 PCM 音频数据:

PCM(Pulse Code Modulation)称为脉冲编码调制,PCM 音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准的数字音频数据。

存储格式

如果是单声道的音频文件,采样数据按时间的先后顺序依次存入(有时也会采用LRLRLR方式存储,只是另一个声道的数据为0),如果是双声道的话就按照LRLRLR的方式存储。

PCM音频数据存储格式.png
单声道
+------+------+------+------+------+------+------+------+------+
|  500 |  300 | -100 | -20  | -300 |  900 | -200 |  -50 |  250 |      
+------+------+------+------+------+------+------+------+------+

每个采样的整数的大小最小为 -32768,最大为 32768。根据采样数据的位置和值画一个图的话,就会得到像播放器上那样的波浪形图。

波形图.png

立体声的采样是每一个 frame 是一个 16bit 的采样点。左右声道的数据交叉存放。

那么采样数据的绝对值按照生成图片的高的比例即可得出振幅。频率通过生成图片的宽计算得到。

  1. 音频文件解码得到 PCM(音频裸数据), 统计音频的采样总数
  2. 以 采样总数 / 输出图片的宽度 为波形图统计频率
  3. 采样数据的绝对值 * 生成图片的高度 / 32768 计算得出振幅大小
showwavespic流程图.png
上一篇下一篇

猜你喜欢

热点阅读