news 2026/9/16 17:13:10

Rerun 视频数据可视化指南:AssetVideo 原语与 VideoFrameReference 的配合使用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rerun 视频数据可视化指南:AssetVideo 原语与 VideoFrameReference 的配合使用

Rerun 视频数据可视化指南:AssetVideo 原语与 VideoFrameReference 的配合使用

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

AssetVideo是 Rerun 中用于承载视频二进制数据(Video binary)的核心原语(Archetype),负责将视频文件内容及其媒体类型写入数据存储;而要让视频真正"动起来",还需要为每一帧额外记录一个VideoFrameReference。本文以 Rerun 仓库内的 AssetVideo 参考文档 为主线,结合类型定义、SDK 生成代码与官方示例,完整讲解该原语的字段模型、媒体类型识别机制、与帧引用原语的协作方式,并给出 Python / Rust / C++ 三种语言可直接运行的实战代码。读完你将掌握"如何把一个 MP4 视频资产 + 逐帧时间戳正确写入 Rerun,并在 2D/3D 视图中回放"的完整技术方案。

AssetVideo 是什么:一个承载视频二进制的数据原语

按官方文档的定义,AssetVideoA video binary(一个视频二进制资产)。它本身不做解码、不负责播放,只负责把视频文件的原始字节与媒体类型作为组件(Component)写入 Rerun 数据存储,供渲染端按需解码。文档明确了两条核心约束:

  • 目前只支持 MP4 容器Only MP4 containers are currently supported),仓库类型定义中的TODO(#7354): Only mp4 is supported for now.(见 asset_video.def.rs)也印证了这一点;
  • 要显示视频,必须同时为每一帧记录一个VideoFrameReference(见 video_frame_reference.md)。也就是说AssetVideo只提供"视频内容",帧的呈现时机完全由VideoFrameReference决定。

该原语由 re_type_definitions 中的类型定义统一声明,再由re_types_builder代码生成器产出 Rust / Python / C++ 三种语言的绑定。生成后的 Rust 结构体位于 crates/store/re_sdk_types/src/archetypes/asset_video.rs,其字段模型与文档完全一致。

字段模型:blob + media_type

AssetVideo共两个字段,在类型系统中被区分为"必需"与"推荐"两级:

字段级别组件类型说明
blob必需(Required)Blob视频文件的原始字节内容
media_type推荐(Recommended)MediaType媒体类型(MIME),目前仅支持video/mp4

生成代码中以REQUIRED_COMPONENTS/RECOMMENDED_COMPONENTS两个静态数组精确登记了这两级组件(见 asset_video.rs),并提供了new(blob)with_blob(...)with_media_type(...)等构造/链式方法。其中media_type的可选语义在源码注释里写得很清楚:

Supported values:video/mp4. If omitted, the viewer will try to guess from the data blob. If it cannot guess, it won't be able to render the asset.

即:media_type 可以省略,省略后 Viewer 会在渲染期尝试从数据本身猜测;若猜不出则渲染失败。

媒体类型识别:三级回退机制

AssetVideo的媒体类型判定在 asset_video_ext.rs 的from_file_path/from_file_contents中实现,实际存在三级回退:

  1. 从文件扩展名猜测from_file_path先调用MediaType::guess_from_path(filepath)
  2. 从文件内容(魔数)猜测from_file_contents内部再通过MediaType::or_guess_from_data(media_type, &contents)校验/修正;
  3. 渲染期兜底猜测:若前两步都无法确定,Viewer 渲染时会再次尝试从数据猜测,仍失败则报错。

对应的 MP4 媒体类型常量定义在 media_type_ext.rs:pub const MP4: &'static str = "video/mp4";

让视频"动"起来:VideoFrameReference 帧引用机制

AssetVideo本身是静态的二进制资产,真正驱动视频播放的是VideoFrameReference。该原语的定义位于 video_frame_reference.def.rs,参考文档见 video_frame_reference.md,其字段模型为:

字段级别组件类型说明
timestamp必需VideoTimestamp引用离该时间戳最近的视频帧
video_reference可选EntityPath指向某个含AssetVideo/VideoStream的实体;缺省时假设视频就在同一实体下
opacity可选Opacity视频不透明度,用于多层媒体叠加,默认 1.0(完全不透明)
draw_order可选DrawOrder2D 绘制顺序,值越大越靠上层,默认-15.0

视频时间戳的语义细节

timestamp字段的类型是VideoTimestamp,其编码说明见 video_timestamp.md:底层 Arrow 数据类型为Int64,单位为纳秒。类型定义中对其语义有三点重要约束:

  • 取"最近"帧而非"最新"帧:渲染端会引用离该时间戳最近的一帧,这样对精度不高的时间戳类型更宽容(能容忍取整误差);
  • 时间戳相对于视频起点:0 永远对应视频第一帧;
  • 与 PTS 的关系:多数情况下等价于显示时间戳(PTS),但当视频存在 B 帧(双向预测帧)时,首帧 PTS 可能带有偏移。

video_reference 的 latest-at 语义

video_reference是可选的实体路径引用,用于关联到存放AssetVideo(或流式VideoStream)的实体。文档特别提醒:

  • 若缺省,则假定视频就位于当前VideoFrameReference所在实体;
  • 该引用始终指向数据存储(data store),因此对引用视频的 blueprint 覆盖(override)会被忽略;
  • 对于一系列连续的帧引用,建议只在序列开头指定一次video_reference,后续帧靠 Rerun 的 latest-at 查询语义继续命中该视频实体。

VideoStream是与之并列的流式视频原语,仓库中同样提供了 video_stream_query_and_mux.py 与 video_stream_synthetic.py 两个示例可供参考,本文聚焦AssetVideo

完整可运行的代码示例

Python:自动确定帧(video_auto_frames)

完整源码见 docs/snippets/all/archetypes/video_auto_frames.py。它先以static=True记录视频资产,再调用read_frame_timestamps_nanos()自动读出全部帧的纳秒时间戳,最后用send_columns以列式(columnar)方式一次性写入所有帧引用:

"""Log a video asset using automatically determined frame references.""" import sys import rerun as rr if len(sys.argv) < 2: # TODO(#7354): Only mp4 is supported for now. print(f"Usage: {sys.argv[0]} <path_to_video.[mp4]>") sys.exit(1) rr.init("rerun_example_asset_video_auto_frames", spawn=True) # Log video asset which is referred to by frame references. video_asset = rr.AssetVideo(path=sys.argv[1]) rr.log("video", video_asset, static=True) # Send automatically determined video frame timestamps. frame_timestamps_ns = video_asset.read_frame_timestamps_nanos() rr.send_columns( "video", # Note timeline values don't have to be the same as the video timestamps. indexes=[rr.TimeColumn("video_time", duration=1e-9 * frame_timestamps_ns)], columns=rr.VideoFrameReference.columns_nanos(frame_timestamps_ns), )

运行方式:python video_auto_frames.py /path/to/video.mp4。其中rr.TimeColumn("video_time", ...)创建一条名为video_time的时间轴,其取值(纳秒→秒)不必与视频帧时间戳一致——视频帧时间戳决定"显示哪一帧",时间轴值决定"何时显示"。rr.VideoFrameReference.columns_nanos(...)则把一维纳秒数组直接包装为帧引用组件列,与send_columns的列式写入无缝配合,性能优于逐行log

Python:手动帧引用(video_manual_frames)

完整源码见 docs/snippets/all/archetypes/video_manual_frames.py。它只记录两个帧引用,让同一视频分别冻结在 1 秒与 2 秒处,并发送一个并排双视图 blueprint 展示效果:

"""Manual use of individual video frame references.""" import sys import rerun as rr import rerun.blueprint as rrb if len(sys.argv) < 2: # TODO(#7354): Only mp4 is supported for now. print(f"Usage: {sys.argv[0]} <path_to_video.[mp4]>") sys.exit(1) rr.init("rerun_example_asset_video_manual_frames", spawn=True) # Log video asset which is referred to by frame references. rr.log("video_asset", rr.AssetVideo(path=sys.argv[1]), static=True) # Create two entities, showing the same video frozen at different times. rr.log( "frame_1s", rr.VideoFrameReference(seconds=1.0, video_reference="video_asset"), ) rr.log( "frame_2s", rr.VideoFrameReference(seconds=2.0, video_reference="video_asset"), ) # Send blueprint that shows two 2D views next to each other. rr.send_blueprint( rrb.Horizontal( rrb.Spatial2DView(origin="frame_1s"), rrb.Spatial2DView(origin="frame_2s"), ) )

这里可以看到video_reference="video_asset"的典型用法:视频资产记录在video_asset实体,而两个帧引用位于不同的子实体,通过显式路径跨实体关联。rr.VideoFrameReference(seconds=1.0, ...)直接以秒为单位构造时间戳,SDK 内部换算为纳秒。

Rust:自动确定帧

完整源码见 docs/snippets/all/archetypes/video_auto_frames.rs(仓库中_args为文档构建系统注入的命令行参数占位符,实际运行时应替换为std::env::args().collect::<Vec<_>>()):

//! Log a video asset using automatically determined frame references. use rerun::external::anyhow; fn main() -> anyhow::Result<()> { let args = _args; let Some(path) = args.get(1) else { // TODO(#7354): Only mp4 is supported for now. anyhow::bail!("Usage: {} <path_to_video.[mp4]>", args[0]); }; let rec = rerun::RecordingStreamBuilder::new( "rerun_example_asset_video_auto_frames", ) .spawn()?; // Log video asset which is referred to by frame references. let video_asset = rerun::AssetVideo::from_file_path(path)?; rec.log_static("video", &video_asset)?; // Send automatically determined video frame timestamps. let frame_timestamps_nanos = video_asset.read_frame_timestamps_nanos()?; let video_timestamps_nanos = frame_timestamps_nanos .iter() .copied() .map(rerun::components::VideoTimestamp::from_nanos) .collect::<Vec<_>>(); let time_column = rerun::TimeColumn::new_duration_nanos( "video_time", // Note timeline values don't have to be the same as the video timestamps. frame_timestamps_nanos, ); rec.send_columns( "video", [time_column], rerun::VideoFrameReference::update_fields() .with_many_timestamp(video_timestamps_nanos) .columns_of_unit_batches()?, )?; Ok(()) }

Rust 侧的关键 API:AssetVideo::from_file_path(path)读取文件并自动猜测媒体类型;video_asset.read_frame_timestamps_nanos()返回单调递增的纳秒时间戳向量;VideoFrameReference::update_fields().with_many_timestamp(...)批量填充帧时间戳;columns_of_unit_batches()把组件数据切分为单位长度的子批次,供send_columns使用。

C++:自动确定帧

完整源码见 docs/snippets/all/archetypes/video_auto_frames.cpp,接口与 Rust 高度对应:

// Log a video asset using automatically determined frame references. #include <rerun.hpp> #include <iostream> using namespace std::chrono_literals; int main(int argc, char* argv[]) { if (argc < 2) { // TODO(#7354): Only mp4 is supported for now. std::cerr << "Usage: " << argv[0] << " <path_to_video.[mp4]>" << std::endl; return 1; } const auto path = argv[1]; const auto rec = rerun::RecordingStream("rerun_example_asset_video_auto_frames"); rec.spawn().exit_on_failure(); // Log video asset which is referred to by frame references. auto video_asset = rerun::AssetVideo::from_file(path).value_or_throw(); rec.log_static("video", video_asset); // Send automatically determined video frame timestamps. std::vector<std::chrono::nanoseconds> frame_timestamps_ns = video_asset.read_frame_timestamps_nanos().value_or_throw(); // Note timeline values don't have to be the same as the video timestamps. auto time_column = rerun::TimeColumn::from_durations( "video_time", rerun::borrow(frame_timestamps_ns) ); std::vector<rerun::components::VideoTimestamp> video_timestamps( frame_timestamps_ns.size() ); for (size_t i = 0; i < frame_timestamps_ns.size(); i++) { video_timestamps[i] = rerun::components::VideoTimestamp(frame_timestamps_ns[i]); } rec.send_columns( "video", time_column, rerun::VideoFrameReference() .with_many_timestamp(rerun::borrow(video_timestamps)) .columns() ); }

C++ 侧使用std::chrono::nanoseconds承载帧时间戳,TimeColumn::from_durations直接以chrono时长构造时间轴,value_or_throw()统一处理错误传播。

底层原理:从类型定义到最终渲染

单一事实来源与代码生成

AssetVideo的所有语义都先在 asset_video.def.rs 中声明(该文件并非可执行代码,而是被re_types_builder解析的 Rerun 类型定义 DSL)。文件头标注了#[docs(category = "Video")]#[rerun(state = "stable")]#[rerun(visualizer_none)](无专属可视化器,因为渲染逻辑在视频帧可视化器中)等元信息,随后生成 Rust 实现、Python 绑定(rr.AssetVideo)与 C++ 绑定(rerun::AssetVideo)。这也是为什么文档文件头部注明"DO NOT EDIT! This file was auto-generated"——所有语言侧的文档与代码都源自同一份类型定义,保证多语言行为一致。

read_frame_timestamps_nanos 的实现路径

自动确定帧功能的核心在 asset_video_ext.rs 的read_frame_timestamps_nanos(仅在有videofeature 时编译)。其内部流程为:

  1. blob组件取回原始字节(Blob::serialized_blob_as_slice);
  2. 依次从media_type组件或数据魔数确定媒体类型;
  3. 调用re_video::VideoDataDescription::load_from_bytes(blob_bytes, media_type, "AssetVideo")解析视频元数据;
  4. 通过frame_timestamps_nanos()迭代器收集全部帧的 PTS,返回单调递增的纳秒数组;若视频无时间刻度(timescale)则返回VideoLoadError::NoTimescale

可见"自动确定帧"本质上是 SDK 侧对 MP4 容器做了一次轻量解析,把帧时间戳批量提取出来,而不是逐帧解码。

渲染端的 latest-at 视频查询

在 Viewer 端,视频帧由 crates/views/re_view_spatial/src/visualizers/video/video_frame_reference.rs 中的VideoFrameReferenceVisualizer负责绘制。该文件内部定义了latest_at_query_video_from_datastore(第 306 行起)与latest_at_query_video_stream_from_datastore(第 342 行起)两个查询函数,均通过ctx.recording_engine().cache().latest_at(...)从数据存储中按时间轴做 latest-at 查询——这正对应文档中"帧引用序列只需在开头指定一次video_reference,后续依赖 latest-at 语义保持引用激活"的设计。当VideoFrameReferencevideo_reference指向VideoStream实体时,渲染端还会结合 Viewer 当前激活的时间轴进行流式取帧。

可在哪些视图中查看

按官方文档,AssetVideo(连同VideoFrameReference)支持在以下视图中显示:

  • Spatial2DView:视频帧以平面纹理形式呈现;
  • Spatial3DView:仅当视频记录在某个投影(projection)之下时才可显示(例如作为相机图像面片);
  • DataframeView:以表格形式查看/查询视频资产及帧引用数据。

使用限制与注意事项

  • 容器格式:当前仅支持 MP4 容器(video/mp4),代码中TODO(#7354)明确标注这是阶段性限制;更细的编解码器(codec)支持矩阵以官方视频参考文档为准,本文档不展开。
  • 必须有帧引用才能显示:只记录AssetVideo而不同时记录VideoFrameReference,Viewer 无法将视频呈现为动态画面。
  • 时间戳语义:帧时间戳以纳秒为单位、相对于视频起点(0 = 第一帧),且渲染端取"最近帧"而非"最新帧"。
  • media_type 建议显式给出:虽然可省略并交由猜测机制兜底,但显式提供video/mp4可以避免渲染期猜测失败。
  • 静态记录:示例中视频资产均使用log_static/static=True记录,表示该资产不随时间变化,属于推荐做法。

小结

AssetVideo是 Rerun 视频工作流的"内容层",VideoFrameReference是"时间层",二者缺一不可:前者以blob+media_type两个组件承载 MP4 二进制与媒体类型,后者以纳秒级VideoTimestamp逐帧引用内容层并决定呈现时机。本文给出的三种语言示例(Python 自动帧、Python 手动帧、Rust、C++)覆盖了"自动提取帧时间戳批量写入"与"手动指定帧引用"两种典型模式,可直接作为机器人多模态数据、传感器回放等场景中视频可视化的起点。进一步深入可阅读 VideoFrameReference 参考文档 与 re_video 解码实现。

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 17:12:57

Django视频点播网站搭建:从ORM建模到HLS播放与Nginx部署

简介&#xff1a;一套基于Django框架开发的视频点播网站完整源码&#xff0c;面向计算机、数学、电子信息等专业学生&#xff0c;适合作为课程设计、期末大作业或毕业设计参考项目。项目已实现视频播放、收藏、后台管理等功能模块&#xff0c;代码结构清晰&#xff0c;可直接下…

作者头像 李华
网站建设 2026/9/16 17:11:00

微信快递小程序源码全解析:ThinkPHP后端与部署实战

简介&#xff1a;2024最新版快递小程序源码是一套完整可运营的微信快递服务项目&#xff0c;后端基于ThinkPHP&#xff08;PHP&#xff09;框架构建&#xff0c;前端为微信小程序&#xff0c;覆盖查件、寄件下单、物流跟踪等功能&#xff0c;并兼顾数据加密与隐私保护&#xff…

作者头像 李华
网站建设 2026/9/16 17:08:56

Gumroad 本地开发环境用户与认证(Users Authentication)完全指南

Gumroad 本地开发环境用户与认证&#xff08;Users & Authentication&#xff09;完全指南 【免费下载链接】gumroad See what sticks 项目地址: https://gitcode.com/GitHub_Trending/gumr/gumroad 本文围绕 Gumroad 开源仓库的 docs/users.md 展开&#xff0c;系统…

作者头像 李华
网站建设 2026/9/16 17:07:03

shadPS4如何更新PS4游戏版本?以Bloodborne为例的完整避坑指南

shadPS4如何更新PS4游戏版本&#xff1f;以Bloodborne为例的完整避坑指南 【免费下载链接】shadPS4 PlayStation 4 emulator for Windows, Linux, macOS and FreeBSD written in C 项目地址: https://gitcode.com/GitHub_Trending/sh/shadPS4 如果你从PS4上取出的游戏文…

作者头像 李华