FiftyOne 多模态 IR(中间表示):跨 worker、缓存与 UI 的共享数据语言 📅 发布时间:2026/9/15 11:00:44 👁 浏览次数: FiftyOne 多模态 IR中间表示跨 worker、缓存与 UI 的共享数据语言【免费下载链接】fiftyoneRefine high-quality datasets and visual AI models项目地址: https://gitcode.com/GitHub_Trending/fi/fiftyone导读在 FiftyOne 的多模态multimodal架构中app/packages/multimodal/src/ir/下的IRIntermediate Representations中间表示定义了整个系统的“共享语言”它用一组**被动passive、可克隆cloneable**的纯数据类型统一描述多模态数据在加载、解码、同步与可视化过程中跨边界传递的核心概念——字节源、流、帧、时间、清单manifest与可视化输出。读完本文你将理解 IR 的设计边界它只表达“数据意味着什么”不负责“如何加载、解码、渲染”掌握其从时间轴到流清单、从解码输出到播放同步的完整类型体系并能依据其“依赖叶子”的准入准则判断新概念是否应该放进 IR。IR 是什么作为共享语言的中间表示仓库中的 IR 说明文档 给出了最精炼的定义IR (Intermediate Representations) is the shared language.它定义的是一组**跨边界cross boundaries**传输的被动、可克隆的值包括sources字节源数据从哪里来如何按需获取streams流一条可发现、可寻址、语义独立的记录序列frames帧某条流在某个时刻解码得到的结构化输出time时间统一的时间轴与时间窗口描述manifests清单一个 episode 打开时的只读资产清单visualization outputs可视化输出解码器产出的、渲染器可消费的中性可视化数据。IR 的核心哲学是只表达数据的含义what the data means而不关心如何加载、解码或渲染它not how to load it, decode it, or render it。加载策略属于字节资源层解码逻辑属于各格式适配器adapter渲染属于视图层IR 只负责让这些层之间交换的“值”语义一致、格式无关。从源码结构看这一边界被严格执行IR 下的每个文件如bytes.ts、frames.ts、manifest.ts、time.ts几乎全部由interface、type别名和少量纯函数如compareBigInt、rawNodeToJson组成且所有字段均为readonly——这正是“可安全克隆、可在 worker 间传输、不携带行为”的直接体现。入口文件 index.ts 将全部子模块统一导出为公共类型面。IR 在 fiftyone/multimodal 架构中的位置IR 是整个fiftyone/multimodal包的数据契约层。根据 fiftyone/multimodal 包说明运行时流程为组合层composition识别数据源并懒加载对应适配器共享字节资源层获取源资产并填充有界缓存适配器返回中立的 manifest与基于拉取模型的EpisodeSession运行时策略请求时间窗口适配器将记录映射为DecodedFrame值与可克隆的可视化输出Episode 上下文把这些值交给 modal、grid、timeline、tile 等消费者。在这条链路中IR 恰好是 25 步之间交换的全部数据类型字节资源层消费ByteSourceDescriptor适配器产出EpisodeManifest与DecodedFrame播放策略消费TimeWindow与StreamSyncPolicy渲染层消费DecodedVisualization。因此 IR 是这些层之间唯一的“合同”各层不需要互相了解对方的具体格式。核心概念一跨边界传输的被动值sources / streams / frames / time / manifests / visualizationsIR 将跨边界的数据归纳为六个维度分别由独立模块承载维度模块核心类型sources字节源bytes.tsByteSourceDescriptor、ByteRangestreams流manifest.tsStreamId、StreamDescriptor、StreamKindframes帧frames.tsDecodedFrame、DecodedOutputtime时间time.tsNsRange、TimeWindow、TimeDomainmanifests清单manifest.tsEpisodeManifest、EpisodeRecordingFactsvisualization outputsframes.tsDecodedVisualization及其各子类型以 sources 为例bytes.ts 定义了ByteSourceDescriptor它携带sourceId、url、可选的etag、sizeBytes、localFile本地文件句柄以及readProfile读取画像。BYTE_SOURCE_READ_PROFILE只有两个取值local与remote——这是源本地性提示用于指导字节资源层选择缓存行为。ByteRange则以bigint表达半开区间[offset, offsetlength)是传输资源请求分片的统一描述。这类类型不包含任何网络或文件系统实现纯粹描述“一个字节资源是什么、从哪里取”。时间模型统一的时间轴多模态数据的最大难点之一是多条流的时间对齐因此 IR 对时间做了严格的统一建模。time.ts 中NANOSECONDS_PER_SECOND 1_000_000_000n全仓库统一的纳秒换算常量所有时间戳一律使用bigint 纳秒避免浮点精度损失NsRange包含端点的纳秒区间{startNs, endNs}TimeWindow NsRange播放会话请求的“包含端点的时间窗口”TimeDomain描述 episode 活动时间轴的物理语义kind为三选一duration相对时长轴sequence序列号轴如无时间戳的帧序timestamp绝对时间戳轴ByteTimelinePointepisode 时间上累计压缩字节曲线的采样点用于带宽感知调度compareBigInt对 bigint 值稳定的排序比较器供各层复用。这一设计让播放器、数值序列提取、字节调度等所有消费方共享同一时间语言且因为时间值都是bigint与只读元组天然满足“可克隆、可跨 worker 传输”的要求。流与清单episode 的只读资产视图manifest.ts 是 IR 中最核心的模块之一回答了“一个 episode 里有哪些数据”。流族StreamKindSTREAM_KIND常量定义了渲染器层级的 14 种流族audio、camera-calibration、grid、image、image-annotations、location、log、point-cloud、pose、scalar、scene-update、transform、video与unknown。流族是渲染能力分发的依据。流目录分类StreamCategorySTREAM_CATEGORY提供共享目录分类适配器可为流打上actions、annotations-planning、custom、diagnostics、instructions、observations、sensors、telemetry、transforms-poses等标签方便 UI 按语义组织流列表。StreamDescriptor描述单条流包含idStreamId、kind、sourceName、payloadPayloadDescriptor含encoding/schema/schemaEncoding供前端选择解码器、approxRateHz、count、coordinateFrameId、timeRange与自由形式的metadata。EpisodeManifestepisode 打开时返回的完整清单包含episodeId、streams、timeDomain、timeRange、可选的transformTopology静态坐标系关系图见下文、calibrations与recordingFacts。EpisodeRecordingFactsepisode 级的只读统计含format、channelCount、topicCount、messageCount、durationNs、startTimeNs/endTimeNs、sizeBytes、schemaCount与schemaCoverage针对不同容器还有专有子结构McapRecordingFactschunk 数、压缩率、message index 状态等与LeRobotRecordingFactsfps、机器人类型、任务标签、视频编解码器等。这些事实被设计为“跨 worker 克隆安全”的不可变快照。support facts 计算recordingSupportFactsFromStreams()是 IR 中少有的纯函数它遍历流清单依据SCENE_SOURCE_METADATA.TYPE与STREAM_METADATA.INSPECTABLE将每条流分类为可渲染renderable、可检视inspectable或不可用unavailable产出EpisodeRecordingSupportFacts——这是 UI 汇总“这个录制里有哪些能看、能查”的直接依据。相关元数据键由SCENE_SOURCE_METADATAscene.calibration_stream_id、scene.source_name、scene.source_type与STREAM_METADATAstream.category、stream.encoding、stream.decode_status、stream.inspectable、stream.schema_name、stream.count_noun统一定义。帧与解码输出DecodedFrame / DecodedOutputframes.ts 定义了适配器解码后交给下游的结构DecodedFrame一条流在某个纳秒时刻的一帧含streamId、timestampNs、可选sequence、sourceTimestamps、recordId格式原生身份用于驻留期去重与outputDecodedOutput帧的完整载荷可同时携带attributes标量/对象元数据DecodedAttributeValue支持 string/number/boolean/bigint/null、数组与嵌套对象供检视、过滤与轻量渲染器标签使用大型二进制载荷应放入visualizationvisualizationDecodedVisualization解码器产出的主可视化产物scalars数值观测ScalarSample含字段名、单位、时间戳transforms坐标系变换样本TransformSample含父子 frame 与四元数/平移静态变换可省略时间戳timing时间范围与源时间戳diagnostics解码诊断DecodedDiagnosticinfo/warning严重度与能力码resourceHintssizeBytes与可转移对象transferables供通用缓存与 worker 传输使用。DecodedAttributeValue的注释明确指出“大型二进制载荷属于visualization”这体现了 IR 对“轻元数据”与“重可视化数据”的刻意分层。可视化输出从解码到渲染的中性描述IR 为可视化输出定义了稳定的判别标识。visualization-kinds.ts 中的VISUALIZATION_KIND枚举了 12 种产物encoded-image、raw-image、encoded-video、raw-audio、encoded-audio、point-cloud、grid、camera-calibration、location、pose、scene-update、image-annotations。DecodedVisualization正是这些子类型的闭合联合。编码 vs 原始Encoded vs Raw是 IR 可视化建模的一条重要原则图像EncodedImageVisualization携带浏览器可直接渲染的压缩字节bytesmimeTypeRawImageVisualization则携带解码器归一化后的显示就绪rgba深度帧rgba为空数组交给 WebGPU 路径直接上传depth.values的全精度Uint16Array/Float32Array样本。视频EncodedVideoVisualization采用“字节 format”契约并按编解码器细分——H.264 需要 SPS/PPS 旁路数据h264.sps/h264.ppsAV1 直接来自 ISO BMFF 样本此外支持h265/vp9codec判别字段使源流可被归类为图像族或视频族。音频RawAudioVisualization的samples采用与源 PCM 布局一致的 typed arrayUint8Array | Int16Array | Int32Array | Float32Array刻意不做强制归一化为Float32Array与图像层 Encoded/Raw 的区分逻辑一致EncodedAudioVisualization保持opus/mp3/aac等源编码字节PCM 解码交由下游 Web Audio / WebCodecs。面向渲染的数据结构是另一大块PointCloudVisualization含fields、positions、可选colors与renderPayload、PointCloudRenderPayload采样点、sourceIndices回溯映射、有界包围盒、标量通道编码origin stored * scale、GridVisualization占位网格以行主序 RGBA 纹理呈现、CameraCalibrationVisualizationOpenCV/Foxglove 约定Z 前、X 右、Y 下K必选、R/P/畸变可选、LocationVisualizationWGS84 经纬度与 ENU 协方差、PoseVisualization位置 四元数 可选运动学、SceneUpdateVisualization实体/原语/删除操作实体计数被显式保留以便检视器评估源压力、ImageAnnotationsVisualization像素坐标下的圆/点/折线/文本覆盖层。这些类型的共同点是全部readonly、全部为“数据描述”而非渲染指令渲染器据此自行决定绘制方式从而保持“格式无关”。播放与同步策略playback.ts播放同步是 IR 的另一个关键领域。playback.ts 定义了运行时拥有的帧选择模式STREAM_SYNC_MODE三选一——latest取最近可用帧、nearest取最近邻帧、strict严格匹配StreamSyncPolicy单流本地呈现策略支持mode、limit、toleranceBeforeNs/toleranceAfterNs前后容差窗口bigint 纳秒StreamSyncPolicies以StreamId为键映射到各流策略ResolvedStreamSyncPolicy运行时默认值应用后的具体选择边界startNs/endNs/limit/modeSynchronizedFrameWindow围绕一个播放时刻为所有请求流选出的帧集合含frames、framesByStream、diagnosticsByStream如frame-decode-failed与逐流已解析策略EpisodeTimeline可播放的时间线元数据startNs/endNs/timeDomainId与可选的字节时间线供带宽感知调度使用TransportLaneinteractive/foreground/inspection/idle/bulk五种调度通道配合NetworkTransportSnapshot与LaneTransportSnapshot提供网络传输遥测。从源码结构看这一层刻意与“生成式 schema”解耦同步模式是运行时拥有的能力而非数据格式的一部分。预览与轻量读取preview.tspreview.ts 定义了“从 episode 网格到模态框”的轻量海报数据EpisodePosterFrameimageCameraVisualization或point-cloud二选一的渲染就绪海报帧EpisodePreviewNativeVideo限定在半个开区间内的浏览器原生视频源含codecString供canPlayType()做原生播放能力检查EpisodePreviewReadResult一次预览读取的结果可携带首次打开时学习到的bootstrapManifest、bootstrapTimeline、bootstrapTimeRange选中的streamId/streamSourceName可预览的源名列表以及videoDecodeRunway编码视频海报附带的一组解码序访问单元和statusempty/ready/unavailable。这使“网格缩略预览”与“完整播放”共享同一套 IR 类型只是数据规模与读取路径不同。原始记录浏览raw-record.ts当用户需要查看某条流的“原始消息”时IR 提供了有界、结构化克隆安全的表示。raw-record.ts 中RawRecordPruneBudgets裁剪预算maxDepth、maxArrayLength、maxStringLength、maxTotalNodes防止把超大消息原样送入 UIRawValueNode五类节点——scalar值以字符串保存并带valueType、bytes仅保留byteLength与 16 字节预览、object可记录droppedEntries、array保留totalLength与截断条目、truncated记录depth/nodes两种原因rawNodeToJson()IR 中另一个纯函数把节点树还原为 JSON 风格数据超出预算的数组/对象/字符串会生成… N more items、… N more fields、…等可读占位RawRecordStream与RawRecordCursor支持按精确索引浏览的流与不透明游标RawRecordIndexWindow与RawRecordIndexWindowRequest围绕游标或时间戳锚点的有界索引窗口RawRecordResult单条记录结果状态为ok/empty/unsupported/decode-error可携带fullJson、payloadBytes、decodeUnavailableReason等降级信息。日志、数值序列与坐标变换拓扑IR 还覆盖三类“辅助但必要”的数据日志log.tsLOG_LEVEL定义debug/info/warn/error/fatal/unknown六档严重度DecodedLogRow为任意格式适配器产出的归一化日志行可含message、level、name、file/line/functionName、hardwareId、topics、status、details键值对与kinddiagnostic/log并以LOG_ATTRIBUTE_ROWS logRows作为解码帧属性的规范键名。数值序列numeric.tsNumericStreamFields描述一条流可绘制的数值字段清单及其可用性ready/no-numeric-fields/schema-unavailable/unsupported-encodingNumericSeriesResult为打包的录制相对数值序列结果NumericSeriesField使用Float64Array保存时间秒与值并可携带bucketIndexes与bucketGapMask支持有界读取摘要的对齐与间断标记。坐标变换拓扑transform-topology.tsEpisodeTransformTopologyEdgeObservation记录一次有界扫描中观察到的坐标系关系static/temporal两类并给出首次/末次观测时间与出现次数供消费方按 parent/child 聚合EpisodeTransformTopologyFrameUse则记录“哪个可渲染流处于哪个坐标系”。配合 manifest 中的静态TransformTopologyEdge共同构成坐标系图谱的静态与动态两个视角。设计准则什么该放进 IR原文档用最后一段明确了 IR 的准入边界This namespace is a dependency leaf. New concepts belong here only when their semantics make sense across formats and can survive transport between workers, caches, runtime policy, and UI without carrying behavior with them.翻译成可操作的判断标准即依赖叶子dependency leafIR 不依赖任何解码器、渲染器或运行时实现其他模块可以依赖 IRIR 不得反向依赖他人——从各文件仅引用 IR 内部类型如StreamId、TimeWindow即可印证跨格式语义成立make sense across formats新概念必须对 MCAP、LeRobot、ROS/Foxglove 等不同源格式都有统一含义格式专属细节应留在适配器层可跨边界传输survive transport值必须在 worker、缓存、运行时策略与 UI 之间传递而不失真因此全部字段readonly、时间用 bigint、二进制用 TypedArray、对象树受预算约束不携带行为without carrying behaviorIR 只承载数据加载/解码/渲染逻辑一概不进入此命名空间。这四条准则解释了为什么 IR 中几乎只有接口、类型与纯函数也提醒开发者当某个新概念只是某种格式的独有细节或需要伴随方法逻辑才能成立时它就不属于 IR。继续探索如果你想在源码中追踪 IR 的实际消费方式可以按以下路径深入公共导出面app/packages/multimodal/src/ir/index.ts生产入口与运行时流程app/packages/multimodal/README.md消费 IR 的适配器端口app/packages/multimodal/src/ports/adapter.ts、session.ts、playback-policy.ts解码器注册与资源提示app/packages/multimodal/src/decoders/registry.ts、resource-hints.ts、types.ts运行时对 IR 的落地使用app/packages/multimodal/src/runtime/episode-byte-source.ts、episode-stream-cache.ts、episode-time-range-registry.ts、numeric-series-window.ts等底层多模态协议 schemaschemas/multimodal/v1/common.proto、inventory.proto、playback.proto与 schemas/multimodal/README.md可对照 protobuf 定义理解 IR 与传输层的对应关系。一句话总结IR 是 FiftyOne 多模态管线各层之间唯一的“共同语言”——它用不可变、可克隆的纯数据把字节源、流、帧、时间、清单与可视化输出统一起来让 worker、缓存、运行时策略与 UI 可以在互不感知对方实现的情况下协作而这正是“格式无关多模态播放”能够成立的数据基础。【免费下载链接】fiftyoneRefine high-quality datasets and visual AI models项目地址: https://gitcode.com/GitHub_Trending/fi/fiftyone创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考