FFmpeg 音频采样格式(sample_fmt)完全手册:FLTP、S16、S32 到底在吵什么

目录

[一、sample_fmt 到底是什么?](#一、sample_fmt 到底是什么?)

[二、先分清:Packed vs Planar(音频里最容易被忽略)](#二、先分清:Packed vs Planar(音频里最容易被忽略))

Packed(交错)

Planar(平面)

[三、8bit 系列](#三、8bit 系列)

[S8 / U8](#S8 / U8)

四、S16(最经典的"能直接播"的格式)

AV_SAMPLE_FMT_S16(Packed)

AV_SAMPLE_FMT_S16P(Planar)

[五、S32(专业音频 / 高动态范围)](#五、S32(专业音频 / 高动态范围))

[AV_SAMPLE_FMT_S32 / S32P](#AV_SAMPLE_FMT_S32 / S32P)

[六、FLT / FLTP(AAC 解码默认)](#六、FLT / FLTP(AAC 解码默认))

[AV_SAMPLE_FMT_FLT(Packed float)](#AV_SAMPLE_FMT_FLT(Packed float))

[AV_SAMPLE_FMT_FLTP(Planar float)](#AV_SAMPLE_FMT_FLTP(Planar float))

[七、DBL / DBLP(双精度,基本只在滤波链里)](#七、DBL / DBLP(双精度,基本只在滤波链里))

八、各格式对比速查表

[九、Buffer 大小怎么算(新手必错)](#九、Buffer 大小怎么算(新手必错))

[十、Planar → Packed 实战(S16P → S16)](#十、Planar → Packed 实战(S16P → S16))

[十一、AAC 解码标准链路](#十一、AAC 解码标准链路)

十二、三个高频坑

[坑 1:SDL 播音炸裂](#坑 1:SDL 播音炸裂)

[坑 2:声道数变了但 format 没变](#坑 2:声道数变了但 format 没变)

[坑 3:linesize 不等于 sampleschbytes](#坑 3:linesize 不等于 sampleschbytes)

十三、总结


觉得有用,就请您帮忙点赞转发收藏吧,您的鼓励是我创作的动力,多谢看官。

由于能力水平有限,文中的错误或不严谨的地方在所难免,还请批评指正。

做音视频的人,几乎都在音频上栽过:AAC 解码出来是 fltp,SDL 播放劈里啪啦,自己 malloc 的 buffer,copy 完全是杂音;av_samples_get_buffer_size算出来的大小跟想的不一样; 混音时发现"数值怎么还有负数还带小数点",问题的根,90% 都在 sample_fmt(音频采样格式),本文就把 FFmpeg 里最常见、最容易混淆的音频采样格式聊一下。


一、sample_fmt 到底是什么?

视频有 pix_fmt,音频对应就是:

复制代码
enum AVSampleFormat;

命令行里叫:

复制代码
-sample_fmt s16

它决定两件事:

  1. 每个采样点用什么类型存(int8 / int16 / int32 / float)

  2. 多声道怎么排(planar or packed)

注意:它不决定采样率,也不决定声道数,只管"一个样本长什么样"。


二、先分清:Packed vs Planar(音频里最容易被忽略)

Packed(交错)

所有声道挤在一起:

复制代码
L R L R L R L R

代表:

  • AV_SAMPLE_FMT_S16

  • AV_SAMPLE_FMT_FLT

Planar(平面)

每个声道独占一块内存:

复制代码
LLLLLLLL
RRRRRRRR

代表:

  • AV_SAMPLE_FMT_S16P

  • AV_SAMPLE_FMT_FLTP

AAC / OPUS / MP3 解码器几乎都输出 Planar

SDL / OpenSL / 声卡 DMA 几乎都吃 Packed

所以你一定会做:

Planar → Packed


三、8bit 系列

S8 / U8

  • AV_SAMPLE_FMT_U8:0--255

  • AV_SAMPLE_FMT_S8:-128--127

早期 PCM、游戏音效、嵌入式喇叭。

动态范围小、量化噪声大,现代编码不用。


四、S16(最经典的"能直接播"的格式)

AV_SAMPLE_FMT_S16(Packed)

  • 16bit 有符号整型

  • 范围:-32768 ~ 32767

  • 布局:int16_t L R L R...

特点:

  • SDL2 默认

  • Linux ALSA 默认

  • WAV 文件常见

  • 不挑平台,性能最好

复制代码
int16_t *pcm = (int16_*)frame->data[0];

AV_SAMPLE_FMT_S16P(Planar)

  • 每个声道一个 int16_t*

  • data[0] = L, data[1] = R

FFmpeg 内部常见,但不能直接丢给声卡


五、S32(专业音频 / 高动态范围)

AV_SAMPLE_FMT_S32 / S32P

  • 32bit 整数

  • 范围:-2147483648 ~ 2147483647

  • 动态范围比 S16 大 48dB

用在:

  • 专业音频工作站

  • 多代混音(防止截断误差累积)

  • FFmpeg 某些滤波器内部

播放前要转 S16,否则声卡不认。


六、FLT / FLTP(AAC 解码默认)

AV_SAMPLE_FMT_FLT(Packed float)

  • 32bit IEEE float

  • 范围:-1.0 ~ 1.0

  • float L R L R...

AV_SAMPLE_FMT_FLTP(Planar float)

  • data[0] = float* L

  • data[1] = float* R

  • AAC / OPUS / Vorbis 默认解码输出

为什么用 float?

  • 滤波器数学运算方便

  • 不会溢出

  • 多代处理误差小

但是:

  • SDL 不能直接播

  • 写 WAV 要转 int

  • 存文件前必须 scale


七、DBL / DBLP(双精度,基本只在滤波链里)

  • AV_SAMPLE_FM_DBL/ DBLP

  • 64bit double

  • 极少见(科学计算、降噪研究)

  • 编解码器不使用


八、各格式对比速查表

sample_fmt 类型 范围 Planar? 典型用途
u8 / s8 int8 0~255 / ±127 老式 PCM
s16 int16 ±32767 SDL/WAV/ALSA
s16p int16 ±32767 FFmpeg 内部
s32 / s32p int32 ±2^31 专业音频
flt float -1~1 某些渲染器
fltp float -1~1 AAC/OPUS 解码
dbl / dblp double -1~1 滤波/科研

九、Buffer 大小怎么算(新手必错)

不要写:

复制代码
size = nb_samples * channels * 2;

要用 FFmpeg API:

复制代码
int buf_size = av_samples_get_buffer_size(
    NULL,
    frame->channels,
    frame->nb_samples,
    frame->format,
    1);  // align

Planar 时:

  • data[0..N]每个声道 nb_samples * bytes_per_sample

  • 总 buffer = 单声道大小 × 声道数(连续分配时)


十、Planar → Packed 实战(S16P → S16)

复制代码
// frame->format == AV_SAMPLE_FMT_S16P
int16_t *dst = out_buf;
for (int i = 0; i < frame->nb_samples; i++) {
    for (int ch = 0; ch < frame->channels; ch++) {
        dst[i * frame->channels + ch] =
            ((int16_t*)frame->data[ch])[i];
    }
}

FLTP → S16(带 clip):

复制代码
float f = ((float*)frame->data[ch])[i];
f = FFMAX(-1.0f, FFMIN(1.0f, f));
dst[i * ch + ch] = (int16_t)(f * 32767);

十一、AAC 解码标准链路

复制代码
AAC packet
   ↓
avcodec_send_packet
   ↓
avcodec_receive_frame
   → sample_fmt = fltp
   ↓
swr_convert (fltp → s16)
   ↓
SDL_QueueAudio (s16 packed)

SwrContext 设置:

复制代码
swr_alloc_set_opts2(&swr,
    &out_layout, AV_SAMPLE_FMT_S16, 48000,
    &in_layout,  AV_SAMPLE_FMT_FLTP, 44100,
    0, NULL);

十二、三个高频坑

坑 1:SDL 播音炸裂

解码是 fltp,直接当 s16播 → 爆音

必须 swr_convert

坑 2:声道数变了但 format 没变

swr 不自动帮你改 layout,要显式设 channel_layout

坑 3:linesize 不等于 sampleschbytes

音频 frame 也有 linesize[0],通常等于单平面字节数,别拿它当总大小。


十三、总结

S16 是"声卡语言",FLTP 是"解码器语言",Planar 是"FFmpeg 内部语言"。

工程里 80% 的音频 bug,都是这三者没接好。

相关推荐
乐橙开放平台6 小时前
养老 SaaS 笔记:setMessageCallback 事件桥接 + msgType 映射 P0/P1,先 ACK 再分流值班流
笔记·物联网·音视频·智能家居
H0311169857 小时前
关于当前主流知识库工具在分类整理学习资料场景下的选用参考
人工智能·信息可视化·音视频
tedcloud1237 小时前
Awesome DSH Plugin 怎么用?给 DeepSeek Harness 搭建自己的插件生态
大数据·linux·服务器·人工智能·音视频
2601_9615934210 小时前
视频放大模糊不清?Topaz Video AI v1.7.0 Mac 版高效修复
人工智能·macos·音视频
H03111698510 小时前
关于AI会议音视频转写与智能生成纪要工具的对比分析
人工智能·音视频
乐橙开放平台10 小时前
老旧社区双通道笔记:周界 hoveringAlarm / aiPerArea + 电梯 aiNonVehDetect,一套 callback 做 24h 防护
笔记·物联网·音视频·智能家居
视跃科技10 小时前
多路视频实时解码推理,是怎么做到“逐帧解码 + AI检测 + 目标框叠加上墙“的?
人工智能·目标跟踪·音视频
lbb 小魔仙10 小时前
图片、音频、文档怎么集中转换?群晖部署 VERT 自托管文件工具
音视频
chunmiao303211 小时前
阿里云Wan3.0视频大模型上线:单次生成30秒还能读文档
阿里云·云计算·音视频
bluesky96122212 小时前
一款可以在linux联调程序工具
音视频