FB Video Viewer
Play .fb FlatBuffer log files containing JPEG frame sequences as video, directly inside VS Code.
This is not a generic FlatBuffer browser. It targets a specific log layout: a stream of RawMessage records, each carrying a topic, msg_type, nanosecond timestamp, and an opaque data byte vector. When data is a ROS2 sensor_msgs/CompressedImage CDR payload, the embedded JPEG is extracted and rendered.
Features
- Open any
*.fb file in a custom editor — no schema files, no flatc, no Python.
- Scrub and play through the JPEG frames like a video.
- Per-frame metadata sidebar: timestamp, topic, message type, payload size, JPEG dimensions, decoded JPEG byte count.
- FPS auto-derived from the timestamp range; falls back to 30 fps if timestamps are missing or non-monotonic.
- Keyboard controls:
← / → to step, Space to toggle play.
- Theme-aware (VS Code dark/light), CSP-locked webview.
How it works
The extension performs three things in pure TypeScript:
- FlatBuffer parsing. The
.fbs schema is unknown, so the parser is data-driven. It tries three buffer framings (plain root, 4-byte size prefix, concatenated size-prefixed records) and probes every vtable slot of the root and message tables, classifying fields by content (int64 timestamp range, length-prefixed printable strings, length-prefixed binary blobs).
- CDR decoding. For
sensor_msgs/msg/CompressedImage payloads, it walks the CDR-encoded Header.stamp / frame_id / format / data layout with proper 4-byte alignment, then returns the JPEG byte slice. If CDR parsing fails, it falls back to scanning for JPEG SOI/EOI markers.
- JPEG dimension reading. Walks JPEG marker segments to find any SOFn marker and reads the width/height from its payload.
The full file buffer stays in the extension host. The webview receives only frame index metadata ({index, timestampNs, topic, msgType, dataLength}); JPEG frames are delivered on demand as base64 data URLs and cached in an LRU of 30 in the webview.
Schema assumed
table RawMessage {
timestamp_ns: long;
topic: string;
msg_type: string;
data: [ubyte];
}
table Log { messages: [RawMessage]; }
root_type Log;
Field IDs need not be exactly 0..3 — the parser probes every slot. Additional fields on either table are tolerated.
Usage
- Open the folder containing your
.fb files in VS Code.
- Click a
.fb file (or use Open With… → FB Video Viewer).
- Use the play button, the timeline scrubber, or the arrow keys.
Limitations
- Only JPEG payloads are rendered. PNG, raw YUV, and other compression formats inside
CompressedImage are not decoded.
- Streaming chunks larger than ~1 GB will hit the V8 string size limit when base64-encoding individual JPEGs (each frame is bounded, so this is unlikely in practice).
- The webview shows one frame at a time; there is no thumbnail strip.
Development
npm install
npm run watch # background type-check + dual esbuild bundle
Press F5 to launch the Extension Development Host.