FLV文件头固定9字节,须严格校验签名“FLV”、版本、标志位及大端headerSize(恒为9);之后4字节PreviousTagSize0必须为0,首个tag起始位置为13。

FLV文件头结构和解析关键点
FLV文件头固定为9字节,不是可选或可变长度——跳过它或读错字节序会导致后续所有tag解析失败。必须严格按规范读取:signature(3字节“FLV”)、version(1字节,通常为0x01)、flags(1字节,bit0=hasAudio, bit2=hasVideo)、headerSize(4字节,大端,实际值恒为9,但必须读取并校验)。
常见错误是直接用fread(buf, 1, 9, fp)后硬解构,却忽略headerSize字段的大小端要求。若该字段被误当小端解析,后续所有offset计算全错。
用C++读取并校验FLV头的最小可行代码
不要依赖第三方库做头解析——纯C++ FILE + 手动字节处理最可控。核心是:分配9字节缓冲区、检查签名、用ntohl()转headerSize、验证是否等于9。
-
fread(header, 1, 9, fp)后立刻检查返回值是否为9,否则文件不完整或已到EOF -
header[0] == 'F' && header[1] == 'L' && header[2] == 'V'必须全满足,不能只比前两字节 -
uint32_t size = ntohl(*reinterpret_cast<uint32_t>(&header[5]))</uint32_t>,注意起始偏移是5(索引从0开始),且header[5..8]是连续4字节 - 若
size != 9,说明不是标准FLV(可能是伪造头或损坏),应拒绝继续解析
为什么不能用std::ifstream::read()直接读struct
因为FLV头没有自然对齐,且C++ struct默认内存布局受编译器padding影响。struct FlvHeader { char sig[3]; uint8_t ver; uint8_t flags; uint32_t size; };在多数平台会因size前插入3字节padding,导致sizeof(FlvHeader) == 12而非9,直接read()进struct会错位。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
正确做法是读原始字节数组,再用reinterpret_cast或memcpy提取字段——避免隐式内存布局陷阱。
解析后如何定位第一个tag的位置
FLV头之后紧跟一个4字节的PreviousTagSize0(恒为0),然后才是第一个tag。所以第一个tag起始偏移 = 9(头长) + 4 = 13。这个值不能靠计算,必须从文件中实际读出第9~12字节并确认为0x00000000。
容易被忽略的是:有些“伪FLV”文件省略了PreviousTagSize0,直接跟tag;标准解析器必须检查这4字节,若非零则说明文件异常,不应假设为tag起始。
复杂点在于,FLV规范允许头后有任意填充(虽不推荐),但实际播放器基本不支持——所以生产环境遇到非零PreviousTagSize0,大概率是文件损坏或非标生成器产出,需记录日志而非强行跳过。

















