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

本文详细介绍了如何利用FFmpeg的showwavespic滤镜从音频数据中获取频谱图。首先,解释了PCM音频数据的存储格式,特别是单声道的情况。接着,阐述了showwavespic滤镜的工作原理,包括从音频解码到PCM数据,再到根据采样数据计算振幅和频率,最后生成波形图的整个过程。通过对滤镜处理流程的解析,读者可以理解如何利用FFmpeg生成音频的频谱图。
摘要由CSDN通过智能技术生成

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

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

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

ffmpeg -i input -filter_complex "showwavespic=s=640x120" -frames:v 1 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的方式存储。

在这里插入图片描述

单声道
+------+------+------+------+------+------+------+------+------+
|  500 |  300 | -100 | -20  | -300 |  900 | -200 |  -50 |  250 |      
+------+------+------+------+------+------+------+------+------+

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

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

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

  1. 音频文件解码得到 PCM(音频裸数据), 统计音频的采样总数
  2. 以 采样总数 / 输出图片的宽度 为波形图统计频率
  3. 采样数据的绝对值 * 生成图片的高度 / 32768 计算得出振幅大小
  • 滤镜处理流程
    在这里插入图片描述

  • 流程详情

    1. init – showwavespic 滤镜的初始化

      static av_cold int init(AVFilterContext *ctx)
      {
             
          // showwaves 滤镜的私有数据
          ShowWavesContext *showwaves = ctx->priv;
          if (!strcmp(ctx->filter->name, "showwavespic")) {
             
              // 如果是 showwavespic 滤镜
              showwaves->single_pic = 1;
              // 使用 cline 的绘图 mode
              showwaves->mode = MODE_CENTERED_LINE;
          }
      
          return 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值