资讯动态

UVG 4K视频数据集:高帧率YUV序列与编码器评测实战指南

发布时间:2026/10/23 10:42:16 来源:尧图企业网站定制
简介UVG 4K视频数据集介绍论文系统整理了芬兰坦佩雷大学超视频组发布的十六个超高清测试序列分辨率均为3840×2160帧率覆盖50/120fps提供8位与10位色深的YUV原始格式素材源于索尼摄像机拍摄的自然场景以非商业知识共享许可向学界公开。资源面向视频编码算法研究者和标准制定者也适合超高清流媒体与实时视频通信开发人员重点弥补现有4K测试集在高帧率场景下的素材缺口可作为HEVC/H.265与VVC/H.266编码性能评估的统一基准。论文逐一介绍各序列的画面内容与运动特性给出空间/时间感知信息、率失真曲线、编码复杂度及主观实验设计并与参考编解码器进行横向对比论证该数据集能有效补充新一代VVC标准化测试集。下载包共1个PDF文件容量为931KB保留完整图表与参考文献已有141人学习使用适合作为视频编码方向论文选题、实验对比与算法验证的权威参考资料。1. UVG 4K视频数据集为什么50/120fps才是它的真正价值做视频编码的开发者手里几乎都备着一两份高清测试序列。可一旦要验证高帧率场景——体育转播、游戏录屏、无人机航拍——常规的24/30fps序列就不够用了。UVG 4K视频数据集Ultra Video Group就是为这种诉求准备的一组未压缩的4K原始YUV序列原生提供50fps和120fps两档高帧率场景覆盖人物特写、高速运动、自然微距和户外街景等典型纹理分布是HEVC/VVC编码器率失真分析、码控调参和端到端系统验证的高频选择。它解决的问题很具体用统一、可复现的输入源把不同编码器放在同一把尺子上量。适合做编码器研发、流媒体参数优化和视频质量评测的从业者上手也适合刚接手视频压缩方向的学生快速建立实验基线。2. 数据集构成与格式把UVG的YUV原始文件弄明白2.1 场景与帧率分布高纹理、强运动的样本设计逻辑UVG的数据集不像普通演示视频那样“挑好看的”它的序列选择有明显的编码分析意图。常见实验集里包含人物特写、蜜蜂微距、赛马起跑、人群冲刺、游艇海岸、水花高速飞溅等场景。这些内容分别对应皮肤渐变纹理、自然物体细密纹理、剧烈全局运动、复杂局部运动、水面反光和高频噪点。编码器在平坦区域、边缘区域和高纹理区域的失真表现差异很大没有这样的样本分布单测一两段素材很难暴露问题。帧率方面数据集按50fps和120fps两档存放。120fps的序列时间冗余大相邻帧之间的位移小运动补偿和分级B帧更容易发挥作用50fps则更接近广电和体育制作中常用的高帧率档位运动矢量跨度更大对运动估计质量的要求更苛刻。两档配合恰好覆盖了编码器在时间维度上两种截然不同的工作条件。做对比实验时一个常见的误区是只看分辨率不看帧率把两种帧率序列混在一起求平均码率结果往往被某一档拉偏。2.2 未压缩10bit 4:2:0的单帧体积存储底线怎么算UVG提供的是未压缩的原始YUV不是压缩过的MP4或MXF。原始格式意味着没有量化噪声、没有块效应、没有码控波动编码器输入的就是传感器或渲染管线直接产出的画面。这样才能把率失真测量中的变量收敛到编码器本身。存储代价很高但这是编码研究的正常成本。格式方面序列普遍采用4K分辨率、4:2:0色度采样、10bit位深。Y平面尺寸为3840x2160两个色度平面各为960x1080。每个样本用两个字节存放采用小端序。单帧体积可以精确算出来Y平面占3840乘2160乘2字节U和V平面加起来正好是Y平面的一半单帧合计约24,883,200字节也就是23.7MiB左右。如果一段序列截取600帧用于实验体积大约是13.9GiB。按一组7条序列估算全量拉下来一百多GB是常态磁盘规划必须前置。10bit位深不是噱头。编码对比实验里如果源是8bit暗部渐变区域在编码前就已经有可见色阶断层量化损失会被误判为编码器的问题换成10bit源之后皮肤、天空这类低频渐变区域的条带效应才能真实反映编码器的量化特性。加上4:2:0是视频编码标准里最常用的像素格式编解码器、播放器、质量评价工具都默认支持做实验选型时不需要额外适配。2.3 为什么编码分析离不开未压缩源率失真测量的前提很多刚接触编码评测的人会直接拿蓝光原盘或者平台压好的片子做测试源这会带来一个隐蔽问题源本身就带压缩伪影。测PSNR时这些伪影会叠加到编码器的失真里测SSIM时纹理细节已经被前一代编码器抹掉一部分编码器“实际恢复的细节”会被低估。用UVG这类未压缩YUV作为输入相当于把编码器的起点拉到一致不同编码器之间的差异才是可比较的。另一个容易忽略的点是帧率元数据不存在于文件内部。YUV文件没有封装头没有帧率字段没有色彩范围标志。fps、像素格式、分辨率这些信息全部要靠使用者通过命令行参数手动指定。这既是灵活性的来源也是翻车的高发区。拿到文件先别急着编码先把参数理顺否则后面每一步都是错。3. 把UVG序列接入本地流程下载规划、校验命令与最小播放方案3.1 存储规划先行单序列体积公式与目录布局我一般会在下载之前先跑一个小脚本确认总规模而不是等磁盘满了再清理。YUV文件不像压缩视频删掉一段就得重新下载后悔药不好买。下面这段脚本按格式参数直接算出预期体积python3 - PY w, h 3840, 2160 frames 600 bytes_per_sample 2 # 10bit 用2字节不是1.25字节 y_plane w * h * bytes_per_sample uv_planes y_plane // 2 # 4:2:0 两个色度平面合计为 Y 的一半 frame_size y_plane uv_planes print(f单帧: {frame_size / 1024**2:.2f} MiB) print(f{frames}帧合计: {frame_size * frames / 1024**3:.2f} GiB) PY这段逻辑的关键是把10bit样本当成2字节算。很多人在这一步想当然用1.25字节那样算出来的体积直接小一半规划必然失守。实际存放时Y平面之后紧跟U平面最后是V平面没有对齐填充帧与帧之间也没有间隔seek时可以直接按固定帧大小跳转。目录结构我习惯分成三层raw放原始YUVclips放截取出来的片段enc放编码输出和日志。原始文件很大不一定要复制多份用符号链接就能把同一份源映射到多个项目目录里。mkdir -p ~/uvg4k/raw ~/uvg4k/clips ~/uvg4k/enc ln -s /data/video_corpus/Beauty_120fps.yuv ~/uvg4k/raw/beauty_120fps.yuv ln -s /data/video_corpus/YachtRide_50fps.yuv ~/uvg4k/raw/yachtride_50fps.yuv符号链接在高帧率高分辨率测试里特别有用。同一个YUV文件可能要同时喂给HM、VTM、x265和x266做对比每个工具目录下都放一份物理副本既占空间又拖慢备份。链接之后多份逻辑路径共享一份物理数据出问题也好排查。3.2 用ffprobe正确读取UVG强制pix_fmt、分辨率与帧率原始YUV没有文件头直接丢给ffprobe会得到“Invalid data”之类的报错因为它连宽度都不知道。正确做法是把所有格式信息当作参数喂进去ffprobe -f rawvideo -pix_fmt yuv420p10le -s 3840x2160 -r 120 \ -i Beauty_120fps.yuv输出会显示类似 “Video: rawvideo, yuv420p10le, 3840x2160, 120 fps” 的信息。注意这里有几个坑。第一像素格式要写成 yuv420p10le带 le 后缀表示小端序写成 yuv420p10 会按大端序读取画面会偏色。第二与帧率必须显式给出否则ffprobe只能按默认值猜。看到的 Duration 是根据帧数和指定帧率算出来的不是文件里真实存在的时长标签。第三如果文件是50fps版本把 -r 改成50即可其他参数不用动。在正式编码之前我建议先用这条命令把所有序列过一遍确认每个文件的分辨率和帧率与命名一致。数据集传输过程中偶尔会出现文件名对不上内容的情况提前发现比等到实验跑完再校验成本低得多。ffprobe对rawvideo的解析不校验文件大小即使文件不完整也可能正常显示所以还要结合文件大小和帧数公式做交叉验证帧数等于文件字节数除以单帧字节数。3.3 按帧号截取片段不建索引的rawvideo如何裁剪很多实验不需要跑完整序列比如只要测试码控响应截取300到499帧就够。在封装格式里可以用ss快速seek但原始YUV没有索引表seek做不到精准跳帧。要么先算出字节偏移直接读取要么用帧选择过滤器逐帧解码并挑选ffmpeg -f rawvideo -pix_fmt yuv420p10le -s 3840x2160 -r 120 \ -i Beauty_120fps.yuv \ -vf selectbetween(n,300,499) \ -f rawvideo -pix_fmt yuv420p10le clip_300_499.yuv这条命令会把每一帧都解出来然后只保留帧号在300到499之间的部分再封装成新的原始YUV。帧号从0开始数所以between(n,300,499)得到的是第301帧到第500帧。由于没有索引它的耗时和整个文件都解码一遍相近但胜在精确。如果想跳过大文件直接读取某一帧可以用Python按固定偏移做随机访问frame_bytes 24883200 with open(Beauty_120fps.yuv, rb) as f: f.seek(300 * frame_bytes) frame f.read(frame_bytes)这段代码基于YUV帧大小固定的事实算出目标帧在文件中的字节位置直接跳跃读取。对做帧级特征提取的人来说这是比ffmpeg更省时间的做法。需要注意seek的单位是字节不是帧号计算偏移时务必乘上frame_bytes。如果项目里有人改动过截取逻辑但忘了更新这个常量踩坑概率极高。4. 用UVG做编码器对比实验QP序列、fps分组与结果判读4.1 x265最小可复现命令从YUV直接产生码流拿到UVG序列之后最常用的一步是用编码器直接吃YUV出码流。以x265为例命令行参数相对直观适合做实验基线x265 --input-csp i420 --input-res 3840x2160 --input-depth 10 --fps 120 \ --input Beauty_120fps.yuv --frames 600 --qp 32 --keyint 120 \ --min-keyint 24 --bframes 4 --rc-lookahead 40 --preset medium \ --tune psnr --psnr --csv beauty_qp32_120fps.csv --csv-log-level 2 \ --output beauty_qp32_120fps.hevc逐个看参数含义。input-csp i420对应4:2:0当输入是yuv420p10le时这里必须是i420。input-depth 10告诉编码器样本位深。fps 120不仅影响输出封装的时间基还会影响x265内部的时间层级和GOP结构必须和输入序列真实帧率一致。keyint 120表示120帧一个GOP对120fps序列刚好是1秒对50fps序列如果还设120就变成了2.4秒做对比时要把这个因素考虑进去。bframes 4决定B帧数量和层级复杂度rc-lookahead控制码率控制前瞻窗口这两项直接影响运动补偿效率。tune psnr和psnr选项打开失真统计输出码流的同时记录每帧PSNR。注意这里没有指定码率而是用固定QP。固定QP模式下编码行为更接近失真受控适合先看编码器本身的编码效率码控调优阶段再换用bitrate或ABR模式。输出文件是裸HEVC码流没有MP4容器后续可以用ffmpeg加容器也可以直接用码流分析器打开。4.2 多QP扫描并记录日志留下可回溯的实验脚印单点QP只能看一个工作点无法画出率失真曲线。常规做法是拿同一序列在多个QP下各跑一遍然后把码率和失真汇总到一张表里。这里有一个实验卫生问题每次跑完的日志和码流要能对应上否则回头写报告时根本分不清哪条曲线是哪条命令产生的。我习惯用循环批量跑并把每个QP的日志文件名写明确for qp in 22 27 32 37 42; do x265 --input-csp i420 --input-res 3840x2160 --input-depth 10 --fps 120 \ --input Beauty_120fps.yuv --frames 600 --keyint 120 --bframes 4 \ --qp $qp --preset medium --tune psnr --psnr \ --csv-log-level 2 --csv beauty_120fps_qp${qp}.csv \ --output beauty_120fps_qp${qp}.hevc done循环本身不复杂但有个隐藏坑CSV日志文件名里如果漏掉了fps不同帧率的同一QP结果会被覆盖。之前有同事跑完5个QP才发现所有CSV都写进了同一文件统计阶段完全无法区分只能重跑。文件名里把序列名、帧率、QP三个要素都写进去即使隔一个月回头查也能一眼看懂。跑完后可以用下面命令快速看码流大小stat -c %n %s bytes beauty_120fps_qp*.hevcPSNR数据在CSV里x265默认会输出Y、U、V三个分量的每帧PSNR以及合计值。做率失真分析时通常取Y分量PSNR因为人眼对亮度敏感而且不同编码器的色度处理差异会干扰对比。4.3 50fps与120fps分开统计时间分辨率如何稀释帧间增益这是整个实验设计里最容易被忽视的一环。120fps序列每秒有120帧时间冗余大帧间预测残差小同QP下码率自然比50fps高但这不说明编码器差只说明帧率高。把两种帧率的结果混在一起求平均码率或平均PSNR会让某个编码器在120fps下的优势被另一组50fps的数据稀释甚至颠倒结论。正确的处理方式有两种。第一种是按帧率分组汇报50fps的序列单独出表120fps的序列单独出表只在讨论整体趋势时横向对比。第二种是做归一化把码率换算成每像素比特数也就是bit per pixelbpp bitrate / (width * height * fps)其中bitrate是每秒比特数width、height是分辨率fps是实际帧率。除以帧率之后不同帧率序列的码率被拉到了同一量纲画率失真曲线时横坐标就能对齐。还要注意GOP结构的可比性。如果120fps序列用keyint 12050fps序列也用keyint 120两个序列的关键帧间隔不相等GOP长度引入了额外变量。常见做法是把keyint设为帧率的整数倍比如120fps用12050fps用50保证GOP时长都是1秒左右。否则50fps序列的关键帧比例更高码率会比较吃亏。5. UVG实战避坑从下载到编码最常见的6个具体问题5.1 花屏条纹被默认为8bit 4:2:0现象用ffplay或播放器直接打开.yuv文件画面是雪花状或绿色条纹完全看不出原始内容。原因原始YUV没有封装头播放器不知道分辨率、像素格式、位深默认按8bit 4:2:0处理。10bit数据被当成8bit解析后字节边界错位画面自然花掉。解决显式告诉播放器格式参数。最简单的方式是用ffplayffplay -f rawvideo -pix_fmt yuv420p10le -s 3840x2160 -r 120 Beauty_120fps.yuv这里任何参数缺失都会导致显示异常。尤其是pix_fmt写成yuv420p10le之外的值即使分辨率正确也会偏色或花屏。5.2 时长显示0:00或异常巨大fps参数丢失现象ffprobe读出来的时长是0或者离谱的几十小时后续转码时输出视频速度忽快忽慢。原因rawvideo流没有时间基准ffprobe只能根据给定的帧率计算时长。如果不指定-r某些版本会用默认帧率去套导致时长和音视频同步全乱。解决任何工具读取UVG时都要同时给fps。转码时也要给否则ffmpeg默认按25fps处理120fps的源输出的视频相当于被拉长了5倍肉眼可见的慢放。编码器参数里的fps往往不参与帧间预测但影响输出时间基和码率计算不能省。5.3 磁盘跑满没算清单序列体积现象跑到第三个序列时磁盘提示空间不足编码中断前面的数据也连带受到影响。原因一个600帧的4K 10bit序列接近14GiB7个序列全量下载加转码临时文件轻松超过150GiB。很多人只预估了压缩视频的大小完全没意识到未压缩YUV的膨胀率。解决下载前用2.1节的方式逐序列算体积确认剩余空间够两倍后再拉数据。原始文件和中间文件放在不同挂载点避免同一个分区同时承担源数据、剪辑片段和编码输出。磁盘实在紧张时只挑4到5个代表性的序列做实验不要追求全量。5.4 混用fps导致统计结论翻车现象某编码器在50fps组表现好在120fps组表现差合并统计后反而得到“两者差不多”的错误结论。原因fps是混淆变量。高帧率序列时间冗余大帧间编码收益天然高混在一起会掩盖编码器本身在运动估计和码控上的差异。解决按fps分组统计或者把码率换算成bpp之后再比较。GOP也按帧率比例统一120fps用120帧GOP50fps用50帧GOP。如果实验目的是对比“同一个编码器在不同帧率下的效率”那就固定除了fps之外的所有参数单独看帧率带来的变化。5.5 裁剪不精准rawvideo没有seek索引现象用ffmpeg的-ss参数从YUV里截取片段结果截出来的画面不是目标帧号甚至花屏。原因常规封装格式里-ss通过索引快速跳到目标位置。rawvideo没有索引seek只能从头解码某些版本的ffmpeg会给出错误帧或空帧。解决用select过滤器按帧号选择前一章的脚本就是可靠做法。或者直接用Python按帧大小计算字节偏移读取速度最快。不要依赖-seek在原始YUV上的表现它的精确性没有保证。5.6 颜色偏灰或过艳色彩范围和转换矩阵被忽略现象转出MP4后用播放器看画面灰蒙蒙或饱和度异常和原始YUV观感不一致。原因YUV文件本身没有色彩范围标志。大多数播放器默认按有限范围处理如果源数据实际是全范围就会把0到1023的满量程压缩到64到940画面发灰。反之把有限范围数据按全范围解色彩就会过艳。解决转码时显式声明色彩参数例如在ffmpeg命令里加上ffmpeg -f rawvideo -pix_fmt yuv420p10le -s 3840x2160 -r 120 \ -i Beauty_120fps.yuv -color_range tv \ -colorspace bt709 -color_primaries bt709 -color_trc bt709 \ -c:v libx265 -crf 24 beauty_preview.mkv这样播放器就知道按有限范围BT.709处理。如果要用PSNR等指标做数值对比建议直接对比YUV域而不要在转码链路上引入额外的色彩转换误差。6. 把UVG沉淀成个人测试集固定清单与回归验证两件事第一次跑通之后UVG的用法慢慢会固化成一套固定动作。与其每次临时想参数不如把序列信息和编码配置写进一个清单文件让整个实验流程可回溯。这个习惯对长期做编码器研究的人特别重要。6.1 建立固定测试清单序列路径与参数写进JSON我先维护一份JSON清单记录每个序列的路径、fps、实际帧数和编码参数。内容大致是这个结构{ name: uvg_dev_set_v1, x265_common: { preset: medium, keyint: fps, bframes: 4, rc-lookahead: 40, tune: psnr }, sequences: [ {name: beauty, fps: 120, frames: 600, path: raw/beauty_120fps.yuv}, {name: honeybee, fps: 120, frames: 600, path: raw/honeybee_120fps.yuv}, {name: readysetgo, fps: 50, frames: 600, path: raw/readysetgo_50fps.yuv}, {name: yachtride, fps: 50, frames: 600, path: raw/yachtride_50fps.yuv} ] }keyint写成fps不是真的让编码器读这个字符串而是提醒自己在生成命令行时把keyint换算成fps的数值。这样120fps序列的GOP是12050fps序列的GOP是50GOP时长保持一致。相比之下如果用固定keyint 120时间基准不同的序列之间比较就会失真。每次跑正式实验前我会写一个Python脚本读这份JSON批量生成x265命令并执行。脚本本身不复杂但价值在于把参数来源统一避免手工敲命令时的拼写差异。实验记录里的命令、CSV、码流文件全部以清单为基准后续核对时有据可查。6.2 回归验证两次编码结果应在位级一致固定工具版本和输入的前提下x265的编码结果应当是可复现的。如果同一命令跑两次输出码流的SHA256不一致要么是工具链版本变了要么是多线程调度引入了不确定性。拿UVG做回归测试时我用这个习惯来验证实验环境是否干净sha256sum beauty_120fps_qp32.hevc beauty_120fps_qp32.csv对比两个时间点跑出的hash如果码流一致说明编码器行为稳定率失真曲线的差异可以归因于参数或版本变化。如果hash不一致先复查编译选项和线程数再检查是否用了不稳定的汇编优化路径。之前我就遇到过一台机器用了不同编译版本的x265导致同一命令输出码流和PSNR都有微小差异最后是靠hash对比定位出来的。这套流程还有一个衍生用途调参后验证没有破坏既有质量。在固定测试集上跑回归PSNR波动超过0.01dB就要回去查改动。UVG序列的高帧率特性对这类回归尤其敏感时间层结构调整会在120fps序列上暴露得比普通24fps序列快得多。把UVG用顺之后你会发现它对编码器变化的反馈非常灵敏这就是高时间分辨率素材在研发流程里的价值。我做码控调参时曾经把50fps和120fps的序列混在一个表格里算平均结论刚好相反。后来把序列按fps分组把QP曲线分开画才真正看到哪个编码器在高帧率下更省码率。现在这套UVG实验流程已经成了我的默认动作先定JSON清单再跑QP扫描最后验hash。希望这套思路帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑