视频AI预处理全解析:从MP4文件到模型张量的完整链路
前阵子有个做安防项目的朋友问我他们的视觉检测算法在图片上跑得挺好一到视频就抓瞎是不是模型不行我一看代码他直接把MP4文件路径塞给了模型模型当然报错。这个问题听起来有点基础但我在实际交流中发现很多人对“视频文件”和“算法输入”之间的那段距离缺乏体感。MP4在操作系统的文件管理器里就是一个普通文件但在视觉算法的世界里它根本不是一个可以直接食用的格式。算法要吃的是像素矩阵是张量是经过解码、抽帧、缩放、归一化之后的数值数组。而MP4是一个容器里面装的是经过高度压缩编码的视频流和音频流。从MP4文件路径到模型推理接口之间隔着解码器、像素格式转换、缩放器、批处理调度等一系列工序。这篇文章就把这条链路从头到尾拆一遍讲清楚为什么不能直接处理MP4以及一个生产级别的视频AI分析程序到底是怎么把视频文件“喂”给模型的。1. 内容整体设计与思路拆解1.1 视频文件与算法输入的本质差异要理解这个问题先要分清两个概念容器格式和编码格式。MP4是容器格式它的作用是“打包”。你可以把MP4想象成一个快递盒子盒子里面装的是视频流、音频流、字幕流还有各种元数据。盒子本身不关心里面装的是什么编码格式的视频只要符合规范H.264、H.265、MPEG-4、AV1都可以装进去。这就是为什么热词里有“h.264和mp4的区别”这种搜索——因为大家经常把两者混为一谈。H.264是编码标准MP4是封装格式就像“把书分类装进快递箱”和“快递箱”本身是两回事。而AI检测程序消费的是像素数据。无论是目标检测的YOLO系列、行为识别的SlowFast还是图像分类的ResNet输入接口无一例外都是多维数组形状通常是[B, C, H, W]或者[B, H, W, C]B代表批量大小C代表通道数H和W代表高和宽。这个数组里存的是数值通常是0到255之间的整数或者归一化后的0到1之间的浮点数代表每个像素点的颜色强度。问题来了MP4文件里的视频流是压缩编码后的二进制数据它不是一个一个像素的原始数据而是一系列编码指令。要拿到算法需要的像素矩阵必须先把视频流解码成原始帧这个过程叫解码。解码之后你还得对帧做尺寸调整、颜色空间转换、归一化才能送进模型。这个链条里任何一环断了模型都跑不起来。1.2 为什么不能直接把MP4喂给模型很多从图片检测转到视频检测的开发者会踩同一个坑图片可以单帧输入视频不就是一堆图片吗为什么不能直接处理理论上你说得对视频确实可以理解为连续播放的帧序列。但问题是MP4文件里存的是压缩后的帧而不是原始帧。视频压缩的核心思想是利用时空冗余。空间上一帧图像内部相邻像素有很强的相关性时间上前后帧之间有很强的相似性。编码器会把画面按宏块或编码树单元切分参考前面的帧做运动估计和运动补偿只记录“变化的部分”。这意味着你拿到一个MP4文件光靠文件本身在不解码的情况下是没有办法直接拿到某一帧的完整像素数据的。还有一个现实问题很多视频文件的编码参数五花八门。分辨率从360p到4K都有帧率可能是25、30、60色彩空间可能是BT.601、BT.709甚至BT.2020像素格式从YUV420到YUV444都有。这些参数直接影响解码后的像素排列方式。模型如果不对输入做标准化处理同样的视频在不同参数下解码出来的数据差异会很大检测效果自然不稳定。所以不是说“AI检测程序不能处理MP4”而是MP4必须经过一条完整的预处理流水线变成模型认识的张量格式才能真正进入推理环节。这个流水线就是本文要展开的核心内容。2. 视频压缩原理与解码的必要性2.1 从H.264看视频编码的本质说到视频压缩绕不开H.264。H.264是目前兼容性最广的视频编码标准你手机录的视频、网上下载的电影、监控摄像头输出的流绝大多数都是H.264编码。理解H.264就能理解为什么解码是绕不过去的一步。H.264编码的核心思路是帧内编码加帧间编码。帧内编码的帧叫I帧关键帧它完整编码了整幅画面相当于一张压缩过的JPEG图片可以独立解码。帧间编码的帧叫P帧和B帧P帧参考前面的帧B帧参考前后两个方向的帧。P帧和B帧只记录与参考帧的差异部分用运动矢量和残差数据来表达“画面怎么变了”。这就带来一个实际问题P帧和B帧本身的数据量很小但离开了参考帧它们就是一堆没有意义的残差。解码器必须从最近的I帧开始按照GOP画面组顺序逐步重建每一帧。比如一个GOP的结构是IBBPBBPBBPBB你要解码第10帧就必须先把第1个I帧、后面的B帧和P帧全部按序解码到第10帧一个都不能跳。我经常用一个生活类比来解释这件事I帧是教材的目录页P帧和B帧是往目录里补充的内容修订。你想看某一页的最终内容得先把前面堆积的修订全部处理完才能看到完整页面。视频解码就是这个道理。2.2 色彩空间与像素格式对AI的影响解码出来的原始帧在内存里的形态也不是模型直接能用的。大多数视频编码使用的是YUV色彩空间用一个亮度分量Y和两个色度分量U、V来表示颜色。YUV设计之初是为了兼容黑白电视只有Y分量就能显示黑白画面UV分量提供颜色信息。这种设计还有个好处人类视觉对亮度敏感度远高于色度敏感度所以视频编码可以大幅压缩色度分量而不容易被察觉。视频编码常用的像素格式是YUV420。这里的420是指色度采样率是亮度采样率的四分之一具体来说每2x2的亮度像素块共享一组UV值。这样做省流量但代价是解码后的像素数据并不是独立的RGB值。而深度学习模型绝大多数是在RGB图像上训练的输入通道的顺序是红、绿、蓝。所以解码之后你还必须做一次YUV到RGB的色彩空间转换。这个转换不是可选的是必须的。如果你直接拿YUV420的数据当作RGB数据送进模型颜色通道就完全错乱了画面会变成奇怪的偏色状态检测精度直接归零。这也是为什么有些开发者在本地单帧测试时效果不错一上视频就崩——大概率就是视频流输入时没做色彩空间转换或者转换参数不对。2.3 关键帧、帧率与时间戳的复杂性视频还有一个隐含维度时间。一张图片没有时间概念一段视频有帧率有每一帧的时间戳。帧率决定了模型每秒需要处理多少次时间戳决定了事件发生的先后顺序。做视频AI检测时帧率直接影响算力规划。一个25FPS的1080P视频要全帧分析模型推理速度至少要达到25毫秒每帧才能保持实时。如果模型单帧推理需要100毫秒那就只能跳帧处理比如每4帧抽1帧。如果不做跳帧策略而硬性全帧推理结果就是处理速度追不上视频播放速度程序内存里堆积的待处理帧越来越多最终OOM崩溃。时间戳还有另一层用武之地做轨迹跟踪和行为分析时需要根据时间戳计算物体运动速度、加速度、停留时长等时序特征。这些计算都要求帧的时间信息准确对应到现实时间。MP4容器里的视频流时间戳以时间的刻度为单位需要结合视频的时基和帧率换算成秒。这一环节处理不当会导致检测框和实际事件对不上时序结果错乱。3. 从MP4到算法输入的完整链路3.1 视频文件的解复用与流信息读取拿到一个MP4文件第一步操作是解复用。前面说过MP4是一个容器里面封装了视频流、音频流和元数据。程序要读取视频画面得先从容器中抽取视频流丢弃或者单独处理音频流。这个抽取过程就叫解复用FFmpeg里对应的是avformat_open_input和avformat_find_stream_info这套API。在实际项目中我习惯先用FFmpeg的ffprobe工具看一遍视频流信息确认编码格式、分辨率、帧率、像素格式再决定后续流程。这里有个小技巧ffprobe输出里的codec_name、width、height、r_frame_rate、pix_fmt这些字段每一个都对应后续解码环节的参数选择。如果codec_name是hevc也就是H.265而你的解码器不支持硬解H.265那就得考虑软解的性能开销如果pix_fmt是yuv420p10le说明是10bit色深的高动态范围视频转换成RGB时要注意位深处理直接按8bit转换会丢失颜色精度。命令行查看视频流信息的典型用法ffprobe -v error -show_streams -select_streams v:0 -show_entries streamcodec_name,width,height,r_frame_rate,pix_fmt,time_base input.mp4输出大概长这样codec_nameh264 width1920 height1080 r_frame_rate25/1 pix_fmtyuv420p time_base1/12800看到r_frame_rate25/1就知道帧率是25帧每秒time_base1/12800是容器时基后面做时间戳换算要用。这些信息在程序里可以通过FFmpeg的AVStream结构体拿到不需要手工解析。3.2 解码器的选择软解与硬解的取舍拿到流信息后下一步是初始化解码器。解码器分为软解和硬解两类。软解就是用CPU运行解码算法兼容性最好什么编码格式都能解缺点是CPU占用高。如果视频分辨率高、帧率大软解会成为整个AI流水线的性能瓶颈。我在一台只有4核CPU的机器上解码4K H.265视频做检测CPU直接打满模型推理反而没有资源可用整体延迟飙升到不可用的程度。硬解是利用GPU或者专用的视频解码单元来解码常见的方案是NVIDIA的NVDEC、Intel的Quick Sync Video、以及FFmpeg的VAAPI、VideoToolbox等。硬解不占用CPU核心资源解码性能和功耗都远优于软解特别适合视频AI这种“既要解码又要推理”的场景——GPU做推理的同时硬件解码器可以并行处理视频帧两不耽误。FFmpeg中启用硬解的方法因平台而异。NVIDIA平台上的常见做法是AVBufferRef *hw_device_ctx NULL; av_hwdevice_ctx_create(hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, NULL, NULL, 0); codec_ctx-hw_device_ctx av_buffer_ref(hw_device_ctx);用NVDEC硬解出来的帧可能还在GPU显存中要送入模型的预处理模块得先通过CUDA或者CV-CUDA库在GPU上完成缩放和色彩转换避免每帧数据反复在CPU和GPU之间拷贝。频繁的显存和内存拷贝是视频AI流水线里最容易被忽视的性能杀手一次拷贝的耗时可能比一次推理还高。我实测过一个1080P视频CPU和GPU之间来回拷贝每帧要花18毫秒左右如果50帧视频都这样传光拷贝就占了将近一秒完全不能接受。所以能保持在GPU上的数据就不要回传CPU。3.3 抽帧策略不是每帧都需要分析很多视频AI场景其实不需要逐帧分析。一个25FPS的人流统计任务每秒分析25次跟分析5次结果差距并不大但算力消耗差了5倍。这就涉及到抽帧策略的设计。常见的抽帧策略有几种均匀抽帧每隔N帧取一帧送入模型最简单也最常用。适用于目标检测、分类等对时间连续性要求不高的任务。N的选择取决于目标运动的快慢车辆检测可能需要N2或3人脸识别打卡N5也没问题。关键帧抽帧只分析I帧或者场景切换帧。这种策略适用于视频内容本身变化不频繁的场景比如监控摄像头对着一个静止区域大部分帧内容几乎一样分析重复帧纯属浪费算力。场景检测抽帧通过画面差异检测来自动决定什么时候抽帧。画面剧烈变化时多抽画面静止时少抽。适合视频摘要、智能剪辑这类需要捕捉关键内容的场景。我自己的经验是优先用均匀抽帧简单可预期调好参数后基本不会出问题。场景检测抽帧看起来高级但阈值不好调容易出现该抽的没抽、不该抽的抽了一堆的情况。如果你刚开始搭建视频AI系统不要急着上花哨的抽帧策略先用均匀抽帧跑通全链路再根据精度和性能数据决定要不要优化。3.4 帧处理与模型输入张量的构建抽出来的原始帧还要经过缩放、格式转换、归一化三步才能送进模型。缩放很好理解。模型输入尺寸通常是固定的比如YOLOv5用的是640x640ResNet系列是224x224。原始帧的分辨率可能高达1920x1080不能直接塞进去必须缩小或裁剪。这里要注意保持宽高比直接拉伸会导致目标形变检测框会不准。常见做法是先等比缩放使短边匹配目标尺寸再对边缘做填充或者直接中心裁剪。色彩空间转换前面提过YUV420要转成RGB。在OpenCV里cv::cvtColor一行代码搞定但你要明确输入帧的内存排列方式。FFmpeg解码出来的AVFrameY、U、V三个通道在内存里的位置是分开的OpenCV处理的BGR或RGB是交错排列的转换时要指定正确的参数否则颜色错乱。归一化是把像素值从0到255的整数范围映射到模型训练时的数值范围。不同模型归一化方式不同有的除以255映射到0到1有的是ImageNet均值方差标准化比如RGB三个通道各自减去均值再除以标准差。这一步做错了模型的输出置信度会整体偏低检测框会变得不稳定。完成这些处理后数据就要组装成张量。以PyTorch为例最终输入模型的张量形状是[1, 3, 640, 640]数据类型是float32内存连续在显存中存放。这个张量才是模型真正消费的输入。4. 工程落地中的关键优化与架构设计4.1 用流水线架构替换串行处理最初级的视频AI程序逻辑是这么写的读一帧解码预处理推理然后读下一帧。这是串行处理每一帧都要等前面的全部步骤完成才能开始。这种方式在单帧图片测试时没问题在视频上就暴露出性能问题解码慢的时候推理在空转推理慢的时候解码在空转整体吞吐量被最慢的环节卡住。更合理的架构是流水线模式。把解码、预处理、推理、后处理分别放到不同的线程或进程中每个环节之间通过队列传递数据。解码线程负责从MP4里持续解出原始帧塞进帧队列预处理线程从帧队列取帧做缩放和色彩转换塞进预处理队列推理线程从预处理队列取张量跑模型返回检测结果。这样每一个环节都在同时工作整条流水线的吞吐量不再被单一瓶颈限制而是取决于最慢环节的最大处理能力。我接触的不少开源视频分析项目都用了类似的消息队列架构比如GStreamer插件式流水线、DeepStream的Streammux和批处理机制都是为了让每个环节解耦并行。你要自己写多线程流水线的话需要处理队列的线程安全问题最简单的做法是用queue.Queue或者用带锁的环形缓冲区避免生产者和消费者之间的竞争。4.2 批处理提升GPU利用率GPU推理有个特点单张图片推理和批量图片推理虽然总耗时增加了但批处理能摊薄每张图片的固定开销。输入输出调度、内核启动这些操作的耗时在批量为1的时候占比很高批量增大后每一帧分摊到的调度成本就大幅下降。视频AI天然的时序特性其实对批处理不太友好。因为帧是按顺序到来的强行凑批次往往要等待后续帧到齐引入额外的延迟。所以批处理要看场景做离线视频分析可以一次性把抽出来的帧攒够一个批次再推理吞吐量最大化做实时视频流分析延迟比吞吐量更关键通常采用批大小为1或者很小的批保证单帧延迟可控。有个折中方案是“动态批处理”。维护一个批处理窗口比如50毫秒内积累到的所有帧组成一个批次超过窗口时间就走小批。窗口内帧多批次就大吞吐量高窗口内帧少批次就小延迟短。这种方案在NVIDIA Triton等推理服务器里有现成实现值得参考。4.3 模型替换与多模型级联的扩展空间视频AI检测程序做到底层其实就是一套“视频处理和模型推理的适配层”。一旦你把这层抽象做好了换模型、加模型都非常简单。比如你本来用YOLOv5做人脸检测后来想换成更轻量的YOLOv8n提升帧率只需要替换模型加载代码和预处理参数视频解码和流水线调度完全不用动。再比如你做人流密度分析先检测人再跟踪轨迹就需要检测模型和跟踪器的级联本质上是在推理环节多加一步前面的视频处理链路依然稳定复用。这种解耦设计的价值要在大规模落地时才体现出来。我见过不少项目一开始就图省事把视频解码和模型逻辑写在同一个大函数里等后续要优化解码性能或者换模型的时候改动波及范围极大最后只能重写。视频AI程序的开发节奏注定是解码链路、预处理链路、推理链路三条线并行演进一开始就分层清晰后面能省掉大量重构成本。5. 常见问题与排查技巧实录5.1 解码失败与格式兼容性排查实际项目里遇到最多的问题就是解码失败。表现是程序报错提示找不到解码器或者解码出来的帧是空的。排查这类问题我有一套固定的流程。先用ffprobe确认编码格式。如果编码格式是H.265或者AV1而你的解码器没有对应的软解或者硬解支持那就会失败。解决办法是升级FFmpeg确保编译时包含了对应的解码器或者换用支持该编码的解码库。注意区分“容器格式”和“编码格式”的报错。有些MP4文件虽然扩展名是mp4但视频流可能是某种私有编码比如某些老式监控摄像头输出的是MJPEG或者私有变种编码。这时候MP4容器没问题问题出在里面的视频流格式上。用ffprobe看一眼codec_name一切就清楚了。热词里提到的“为什么海康的MP4播放不了”这类问题也属于同类。海康部分录制文件的编码格式不是标准H.264而是带私有扩展的H.264或者封装格式不标准。通用播放器和AI程序解码时兼容性差容易出现花屏、无法解码的现象。这类文件通常需要用厂家提供的SDK做转封装或者转码或者用FFmpeg加-err_detect ignore_err参数强行解码但效果不一定好。稳妥做法是先转码成标准H.264的MP4再喂给AI程序。5.2 内存管理与帧堆积导致的崩溃视频AI程序长时间跑训练好的模型最常见的崩溃原因不是模型推理出错而是内存爆炸。原因大多是消费者处理不过来生产者解码线程还在拼命往队列里塞帧队列越长内存越大最终触发OOM。排查办法很简单给队列设置最大长度上限队列满时阻塞生产者或者直接丢帧。视频AI场景下丢帧影响往往不大跳几帧的分析结果并不影响整体事件判断总比进程崩溃好。我自己开发时会在队列的写入端加超时和丢弃策略宁可丢帧也不让内存无限制增长。另一个容易忽略的内存问题是GPU显存泄漏。每次推理分配的临时显存如果没有正确释放长时间运行后显存会慢慢耗尽。排查时可以监控显存占用趋势如果发现推理次数增加而显存回收不稳定检查模型前向传播代码看是否每次迭代都在重新创建中间输出张量。5.3 时间戳错乱与检测结果不同步在抽帧分析场景下检测结果需要回写到视频的原始时间点才能正确标注事件发生的时间。这里有典型的坑一旦抽帧检测结果关联的索引是“第N个被分析的帧”而不是“视频的第N帧”。拿均匀抽帧举例每5帧抽1帧那么分析结果的第10帧对应的是视频的第46到50帧之间具体是哪一帧取决于代码实现。如果后续你又要从检测结果反向定位视频画面的具体瞬间必须保存每个被分析帧的原始时间戳通过pts字段映射回视频时间轴。处理MP4的时间戳要特别注意容器的时基跟帧率的换算。常见错法是直接把pts当作帧号来用导致定位到错误的时间点。用FFmpeg的av_frame_get_best_effort_timestamp取时间戳再配合av_q2d做时基转换把PTS换算成秒准确性才有保障。这一行转换代码很不起眼但影响的是整个系统的时间精度值得多花几分钟写好。5.4 音视频分离与无声视频的异常处理AI检测程序一般只需要视频流不需要音频流所以解复用阶段通常会直接丢弃音频流。但如果视频本身没有音频轨某些解码库在初始化时会因为找不到音频流而返回异常导致整个程序退出。处理方式是解复用后在循环里主动查找视频流索引音频流不存在时跳过音频处理逻辑。如果你用的OpenCV的VideoCapture接口它内部自动处理了音频流的忽略一般不会碰到这个问题。但如果你用FFmpeg原生API这一段就得自己写别想当然地认为所有MP4都带声音轨。另外一个和音频相关的点是转码需求。热词里提到的“m3u8怎么转换mp4”、“m4s文件怎么合成mp4”本质上都不是AI检测程序的问题而是视频文件本身需要先转换成标准MP4才能被后续流程消费。这类转换用FFmpeg命令行就能解决ffmpeg -i input.m3u8 -c copy output.mp4-c copy表示流拷贝直接复制编码数据不改编码格式速度快且不损失画质。m4s文件通常是Dash或者HLS分片需要先按顺序拼接再转封装。这里要提醒一句如果原始视频流编码是H.265而你要让老设备或者兼容性有限的程序播放或处理需要转码ffmpeg -i input.m4s -c:v libx264 -crf 23 -preset fast -c:a aac output.mp4这条命令把视频流转成H.264音频转成AAC兼容性最好。代价是转码速度比流拷贝慢但要处理兼容性问题就没得选。6. 一些更底层的注意事项6.1 不同来源视频的“隐性参数”陷阱视频处理领域的坑往往不在明面上的参数而在“隐性参数”。两个MP4文件codec_name都是h264width和height都是1920x1080pix_fmt都是yuv420p看起来参数完全一致。但实际解码出来的帧有可能一个是上下颠倒的一个是左右镜像的。原因是视频流里可以带旋转元数据手机竖屏录制的视频会写一个rotate: 90的元数据告诉播放器要把画面旋转90度显示。播放器会自动处理这个旋转但很多解码器默认不处理直接输出原始未旋转的帧。如果你把这个未旋转的帧送进模型训练就相当于模型天天看歪着脖子的图片训练效果会非常奇怪。排查方法用ffprobe查看视频流的side_data_list关注rotation字段。处理上最简单的方式是解码后做一次旋转操作或者用FFmpeg在解码时加-autorotate参数。如果视频流本身带了旋转信息而你没处理AI检测的框和真实物体方向对不上准确率掉的不是一点半点。另一个隐性参数是像素长宽比DPAR。监控视频和一些非标准编码源的MP4像素不一定是正方形显示时需要做宽高比校正。模型输入用的是像素坐标如果视频的像素不是正方形你检测框的坐标就要先经过SAR和PAR的换算再映射回原视频坐标否则框的位置会偏。这类问题很难从画面上直接看出来但对精度要求高的工程影响很大。6.2 颜色空间转换容易出错的三个细节YUV转RGB这个操作听起来简单实际有三个容易被坑的细节。第一个是色域标准。同样的YUV数值用BT.601和BT.709两套矩阵转换出来的RGB结果有肉眼可见的差别。高清视频一般用BT.709标清视频用BT.601HDR视频可能用BT.2020。转换时选错矩阵图像整体偏色色偏并不明显但模型精度会下降因为模型学习的是RGB像素分布输入偏差会影响特征提取。第二个是范围问题。视频的YUV数据有两种范围有限范围也称视频范围Y通道取值16到235UV通道取值16到240完整范围也称PC范围取值0到255。如果源代码里用了错误的范围假设画面会出现对比度异常或者发灰。FFmpeg解码出来的AVFrame会通过color_range字段标注范围转RGB时要根据这个字段选择对应的转换逻辑。第三个是位深问题。10bit视频解码出来的YUV数据是16位存储的转8位RGB时要做位深压缩。直接截断高位会导致画面出现色带和噪点正确做法是先做缩放或者抖动处理保留更多亮度层次。视频AI项目如果要在同一个模型上同时处理8bit和10bit视频建议统一转到8bit模型训练和推理的输入分布才一致。6.3 用ffmpeg命令行做快速验证在动手写完整代码前我强烈建议先用FFmpeg命令行验证一遍视频能否正常解码、抽帧、转码。这一步能排除大量低级问题避免代码写到一半才发现视频源本身就有毛病。验证解码和抽帧很简单ffmpeg -i input.mp4 -f image2 -vf fps1 frame_%03d.jpg这条命令每秒抽一帧保存成JPEG看输出图片是否正常。如果输出的是花屏、绿屏、黑屏或者报错基本可以断定视频源有问题不用再往后面排查。验证视频流能否送往模型关键一步是确认解码后的像素格式。可以用ffmpeg输出原始RGB数据管道到Python做测试ffmpeg -i input.mp4 -f rawvideo -pix_fmt rgb24 - | python3 test_input.pytest_input.py里读标准输入把裸的RGB数据重新组织成[H, W, 3]的数组直接送模型跑一帧推理。这种做法可以把视频处理链路和模型推理链路分开验证哪里出问题一目了然。我在搭建新的视频AI项目时第一步永远是跑这条管道命令确认“视频能变成模型认识的RGB张量”再谈后续的检测精度。个人经验与最后的实践建议做视频AI和做图片AI工作重心完全不同。图片AI拼的是模型结构和训练数据视频AI拼的是工程底座。一个能稳定运行上千小时的视频检测系统代码量的大头都在解码、调度、内存管理、容错处理这些底层模块上模型本身反而只是其中一小块。我见过一些团队花大量精力调模型的mAP但视频流水线一跑就崩、一跑就卡投入产出比极低。如果你正在从图片检测往视频检测迁移我建议先别纠结模型选型先花两天时间把手里的视频转换成模型能吃的张量用最土的方式验证全链路跑通再一步步优化。这个链路里最值得投入时间的是解码器的选型和流水线架构的搭建这两件事决定了系统能扛多大的分辨率、多高的帧率、多少路视频并发。模型可以随时换好的视频处理底座可以一直复用。最后分享一个调试小技巧做视频AI开发一定要把可视化工具用好。除了用OpenCV的imshow显示处理结果我还会定期把抽帧结果和推理结果写到磁盘上边跑边看。有一次我排查视频检测框持续偏上的问题看代码和参数完全找不到原因后来把抽帧图片一张张翻出来才发现视频流带了2度左右的倾斜旋转元数据我做的自动旋转处理只支持90度的倍数小角度旋转被直接跳过了。如果不是用可视化检查这种问题大概会折腾好几天。视频AI的视觉问题最好的排查工具还是自己的眼睛。