Live: https://encoding-helper.brain-bbqs.org
A didactic, in-browser video encoding lab. Load an MP4 and it inspects the container, teaches you how MP4 storage and H.264 encoding actually work (tied to the numbers in your file), runs empirical seeking tests, and re-encodes video directly in the browser — while always producing a copy-paste ffmpeg command for local/headless/batch use.
Companion to Video Info Tool and Frame-Accurate Video Player.
- Inspect - rich metadata plus a visual MP4 atom map (
ftyp/moov/mdat/moof, byte offsets & sizes, moov-before-mdat "faststart" detection) and per-frame GOP/I-frame/B-frame structure - Identify the codec - infers the codec family from the container (H.264/AVC, H.265/HEVC, VP8/VP9, AV1, AAC, Opus, FLAC, MP3, AC-3/E-AC-3, PCM) and decodes its embedded profile/level/tier straight out of the RFC 6381 codec string, with a short explainer on what that codec actually is and why you'd (not) choose it
- Teach - interactive explanations tied to the loaded file: CRF vs. bitrate, x264 presets, GOP/keyframe interval, I/P/B frames,
yuv420pchroma subsampling, even-dimension requirements, and the moov-atom/faststart tradeoff - Measure - empirical seeking tests (nearest-keyframe distance per timestamp, decode wall-clock, keyframe-interval histogram) with a scatter plot of distance vs. decode time, plus before/after compression stats
- Re-encode - H.264/MP4 directly in the browser, saved back to disk via the File System Access API, with two engines:
- ffmpeg.wasm (exact) - runs the literal CRF/preset command, byte-for-byte equivalent to the CLI, lazy-loaded (~30 MB), GPL
- mediabunny / WebCodecs (fast) - hardware-accelerated, no CRF (bitrate/quality-preset only), surfaced honestly as an approximation
- Encode Test (A/B) - encodes just a short window (1-10s) of the video at the chosen CRF/preset, then decodes the original and the result side-by-side with synchronized pixel-level zoom & pan, one-click Fit/Actual Size (100%) buttons, a pixel grid that appears once zoomed in far enough to make individual pixels visible, and a scrub slider — so you can judge a quality setting before committing to a full re-encode
- Always emits a CLI command - a live, editable
ffmpegcommand mirroring sleap-io'sreencode, for anyone who wants to run it locally, headless, or in batch - Report / Export - compiles metadata, the codec explainer, the atom map, GOP/keyframe stats, the seeking test and Encode Test results (if run), and the CLI command into one report — copy as Markdown, download a
.mdfile, or print to PDF via the browser's native print dialog
- Load a video via drag-and-drop, the file picker, or Load Sample (bundled
mice.mp4) - Explore the Inspect tab for metadata, the codec explainer, the atom map, and GOP/frame structure
- Run the Seeking Test to measure nearest-keyframe distance and decode latency across the timeline (and see it plotted)
- Tune CRF, preset, keyframe interval, B-frames, faststart, and audio handling in the Re-encode tab
- Copy the generated
ffmpegcommand, or click Encode (exact) / Encode (fast) to transcode in-browser and save the result - Try different CRF/preset values on a short clip in the Encode Test tab and compare against the original side-by-side before running the full encode
- Head to the Report tab to copy/download a Markdown summary of everything above, or print it to PDF
A TypeScript + Vite app; the video-handling libraries are ordinary npm dependencies rather than CDN <script> tags:
- mediabunny - metadata, packet/GOP analysis, frame seeking, WebCodecs-based fast re-encode (lazy-loaded via a dynamic
import()the first time a file is loaded, and bundled into its own chunk) - mp4box.js - MP4 atom map and sample table (keyframes/GOP/B-frames); ships no TypeScript types, so a small local
.d.ts(src/lib/mp4box.d.ts) declares the slice this app actually uses - @ffmpeg/ffmpeg + @ffmpeg/util - exact in-browser re-encode. As a proper ESM package, Vite bundles and loads its worker itself; the
ffmpeg-core.js/.wasmbinaries (~30 MB) are still fetched from the jsdelivr CDN at runtime via@ffmpeg/util'stoBlobURL(), the officially documented pattern, and only once an "exact" encode actually runs
- GitHub Pages serves no custom headers, so only the single-thread ffmpeg.wasm core is used (no COOP/COEP, no
coi-serviceworker) - this keeps the tool a single self-contained page at the cost of some encode speed - WebCodecs exposes no CRF control, only target bitrate/quality presets - the "fast" engine cannot byte-match the CLI command, and the UI says so
- Firefox's H.264 WebCodecs encoder support is weak; the fast engine feature-detects and falls back to ffmpeg.wasm/CLI-only
- ffmpeg.wasm is GPL-licensed; credited in the footer
npm install # install dependencies
npm run dev # start the Vite dev server
npm run build # typecheck + production build to dist/
npm test # run the unit test suite (vitest)
npm run lint # eslint (type-aware, strict)
npm run test:integration # Playwright integration tests (tests/integration/)
npm run storybook # component sandbox at http://localhost:6006 (stories/)Source lives under src/: src/lib/ holds pure logic (formatting, the MP4/codec parsers, the CLI-command builder, the ffmpeg.wasm/mediabunny encode engines), src/ui/ holds one renderer module per tab, and src/main.ts wires it all up to the static skeleton markup in index.html. Unit tests for the pure lib/ modules live under tests/unit/; Playwright integration tests live under tests/integration/. Component snapshots are driven by Storybook and Chromatic (both a Storybook build and a dedicated Playwright suite under tests/chromatic/), which visually regression-test the UI on every push.
New vibe: encoding-helper — didactic in-browser video encoding lab (inspect, teach, seek-test, reencode). See GitHub issue #66 for the full spec, motivated by the BBQS Day 3 working session on video → behavioral annotation pipelines (Acquisition and QC tracks), with sleap-io's
reencodeas the shared transcoding baseline this tool makes legible.