别再傻傻分不清YUV和YCbCr了!搞懂这些格式,你的视频开发才算入门

发布时间:2026/6/5 22:14:13

别再傻傻分不清YUV和YCbCr了!搞懂这些格式,你的视频开发才算入门 别再傻傻分不清YUV和YCbCr了搞懂这些格式你的视频开发才算入门第一次接触视频开发时看到YUV、YCbCr、420、422、NV12这些术语是不是感觉头都大了别担心这几乎是每个视频工程师的必经之路。记得我刚入行时就因为搞混了YUV420和YUV422导致整个直播推流系统颜色异常被测试同事追着骂了一周。今天我们就来彻底搞懂这些让人抓狂的概念。1. YUV与YCbCr孪生兄弟还是远房亲戚很多人会把YUV和YCbCr混为一谈就像把双胞胎认成同一个人。实际上它们确实很像但应用场景却大不相同。YUV诞生于模拟电视时代的老将Y代表亮度Luma决定画面明暗UV代表色度Chroma携带颜色信息典型应用传统CRT电视、模拟视频信号传输YCbCr数字时代的进化版Y同样表示亮度Cb蓝色差值和Cr红色差值经过数学变换核心优势更适合数字压缩和传输关键区别YCbCr经过缩放和偏移处理的YUV就像把模拟信号数字化改造下表对比两者的典型应用场景特性YUVYCbCr信号类型模拟数字常见标准PAL/NTSCITU-R BT.601/709应用领域老式电视广播H.264/HEVC/JPEG编码存储效率较低较高2. 采样格式为什么直播都用YUV420当你用手机拍视频时系统默认使用YUV420而专业摄像机可能用YUV422或444。这背后的选择逻辑是什么2.1 采样格式的本质所有采样格式的核心思想都是人眼对亮度更敏感。通过让多个像素共享色度信息可以大幅减少数据量。YUV444土豪模式每个像素都有独立的YUV → 画质无损但体积最大 → 专业影视后期常用YUV422平衡之选# 水平方向每两个Y共享UV # 数据量比444减少1/3 # 广播电视常用格式YUV420移动端最爱# 每2x2的Y块共享一组UV # 数据量只有444的50% # 抖音/快手等直播App标配2.2 选错格式的惨痛教训去年我们团队就踩过一个坑在Android Camera2 API中错误配置了输出格式// 错误配置要求相机输出YUV422 surface.setDefaultBufferSize(width, height); imageReader ImageReader.newInstance( width, height, ImageFormat.YUV_422_888, // 问题出在这里 2 ); // 正确配置应该用YUV_420_888结果导致视频帧体积增大40%部分低端机型直接闪退直播延迟增加200ms3. 存储格式Planar和Packed到底差在哪就算搞懂了采样格式当你真正处理视频数据时还会遇到更头疼的问题——内存排列方式。这就好比知道了货物清单但不知道仓库的摆放规则。3.1 四大存储门派Planar平面式典型代表I420/YV12存储顺序YYYY...UUU...VVV优点处理方便OpenCV直接支持Semi-Planar半平面式典型代表NV12/NV21存储顺序YYYY...UVUV...Android相机默认输出格式Packed打包式典型代表YUYV/UYVY存储顺序YUVYUVYUV...常见于视频采集卡Tiled瓦片式典型代表某些GPU专用格式按16x16块存储解码效率最高但处理最复杂3.2 格式转换实战处理跨平台视频时经常需要转换格式。这里给出FFmpeg的经典转换命令# NV21转I420Android到iOS常见需求 ffmpeg -s 1920x1080 -pix_fmt nv21 -i input.yuv -pix_fmt yuv420p output.yuv # YUYV转NV12采集卡到推流场景 ffmpeg -s 1280x720 -pix_fmt yuyv422 -i /dev/video0 -pix_fmt nv12 output.mp4注意格式转换会消耗CPU资源在直播场景要慎用4. 位深进阶当8bit不够用时随着HDR内容普及传统的8bit YUV已经不够用了。这时就需要了解P010/P01610/16bit的YUV420Y210/Y21610/16bit的YUV422色深提升带来的变化文件体积成倍增长需要特殊硬件支持颜色渐变更平滑减少banding// 处理10bit YUV示例部分代码 uint16_t *y_plane (uint16_t *)frame-data[0]; uint16_t *uv_plane (uint16_t *)frame-data[1]; // 取值时需要右移6位因为实际存储用16bit表示10bit uint16_t y_value y_plane[pixel_index] 6;5. 避坑指南实际开发中的血泪经验Android相机开发新机型基本只支持NV21ImageFormat.YUV_420_888实际可能是NV21OpenCV处理# 正确读取NV12的方法 height 1080 width 1920 yuv_data np.fromfile(nv12.yuv, dtypenp.uint8) y yuv_data[:width*height].reshape(height, width) uv yuv_data[width*height:].reshape(height//2, width//2, 2)性能优化避免在Java层处理YUV数据使用RenderScript或Native代码考虑使用GLSL着色器处理测试验证使用FFmpeg生成测试样本# 生成彩条测试图 ffmpeg -y -f lavfi -i testsrcduration10:size1280x720:rate30 \ -pix_fmt yuv420p test.yuv记得第一次调试HDR视频时因为没注意P010格式的特殊性导致画面出现诡异的色块。后来发现是忘记处理padding bits10bit数据实际用16bit存储低6位要置零。这种细节问题在官方文档里往往只是一笔带过却可能让你调试好几天。

相关新闻