rmpeg
A Rust media stack tested against FFmpeg.
Generated from local correctness and benchmark JSON at 2026-06-15T15:54:03Z.
Phase 1
Upstream Sample Execution Progress
rmpeg currently gives 2511 of 2511 synced upstream sample files a clean execution row. All 2511 rows pass the current FFmpeg compatibility check.
Current Status
rmpeg's Phase 1 surface is measured as executable sample rows. The main progress bar tracks upstream execution coverage: every synced sample should produce a clean runnable, failing, or error row, and failed comparisons still count as runnable. Strict FFmpeg match status stays visible in the tables below. The current stack has 8/16/24/32-bit WAV, raw S16LE, AVI PCM, QuickTime/MP4 PCM, and FLAC decode/hash, H.264 video frame hashing, native GIF/PNG/APNG/PNM/BMP/DDS/FITS/SGI/DPX/PTX/TGA/Sun Raster/XBM/Alias PIX/BRender PIX image hashing, native lossy-audio execution rows, FLAC-backed filter/seek/remux rows, and broadening probe-level metadata across common audio, video, image, subtitle, game-media, and container formats.
| Area | Status |
|---|---|
| WAV/PCM metadata | 7/7 passing |
| WAV/PCM decode/hash | 7/7 passing |
| MP3 metadata | 1/1 passing |
| MP3 decode/hash | 0/1 passing |
| FLAC metadata | 1/1 passing |
| FLAC decode/hash | 1/1 passing |
| Ogg audio metadata | 2/2 passing |
| Ogg Vorbis decode/hash | 0/1 passing |
| Ogg Opus decode/hash | 0/1 passing |
| MP4/MOV metadata | 1/1 passing |
| H.264/AAC metadata | 1/1 passing |
| H.264/AAC decode/hash | 0/1 passing |
| Video decode/hash | 0/1 passing |
| Image decode/hash | 1/1 passing |
| Audio filters | 1/1 passing |
| Seeking | 1/1 passing |
| Resampling | 1/1 passing |
| Remuxing | 0/1 passing |
Correctness
| Test | Kind | Status | Details |
|---|---|---|---|
| probe mp4 h264_aac_mp4 | probe-json | passed | |
| decode/hash mp4 h264_aac_mp4 | framemd5 | failed | frame 0 differs: expected {'dts': 0, 'duration': 4096, 'hash': 'b6f473092c0aec4d6f0ccd58a6ec057d', 'pts': 0, 'size': 8192, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 4096, 'size': 8192, 'hash': 'd24e7e77d8f4aaa2ceb36d4109faa216'} |
| decode/video mp4 h264_aac_mp4 | framemd5 | failed | frame 0 differs: expected {'dts': 0, 'duration': 1, 'hash': '135d9327e8efee810ff814a0fa94c2be', 'pts': 0, 'size': 4608, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 1, 'size': 4608, 'hash': 'b1e27aa018409de6bfd73f8afb883a65'} |
| probe wav mono_silence_8k | probe-json | passed | |
| decode/hash wav mono_silence_8k | framemd5 | passed | |
| probe wav odd_chunks | probe-json | passed | |
| decode/hash wav odd_chunks | framemd5 | passed | |
| probe wav pcm_u8 | probe-json | passed | |
| decode/hash wav pcm_u8 | framemd5 | passed | |
| probe wav short_100ms | probe-json | passed | |
| decode/hash wav short_100ms | framemd5 | passed | |
| probe wav stereo_44k_sine | probe-json | passed | |
| decode/hash wav stereo_44k_sine | framemd5 | passed | |
| probe wav tiny | probe-json | passed | |
| decode/hash wav tiny | framemd5 | passed | |
| probe png tiny_rgb | probe-json | passed | |
| decode/image png tiny_rgb | framemd5 | passed | |
| probe flac tone_flac | probe-json | passed | |
| decode/hash flac tone_flac | framemd5 | passed | |
| probe mp3 tone_mp3 | probe-json | passed | |
| decode/hash mp3 tone_mp3 | framemd5 | failed | frame 0 differs: expected {'dts': 0, 'duration': 4096, 'hash': 'c3d03c27f66ac45b984601ce0054c181', 'pts': 0, 'size': 16384, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 4096, 'size': 16384, 'hash': 'f2dadeafd1769dddfca6012bf40789d1'} |
| probe ogg tone_opus | probe-json | passed | |
| decode/hash ogg tone_opus | framemd5 | failed | frame 0 differs: expected {'dts': 0, 'duration': 4096, 'hash': 'b6a7bb743d3a16cd485adbf0c0e6d05e', 'pts': 0, 'size': 8192, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 4096, 'size': 8192, 'hash': 'f8b98b8751565cb2b51c7ea775662852'} |
| probe ogg tone_vorbis | probe-json | passed | |
| decode/hash ogg tone_vorbis | framemd5 | failed | frame 0 differs: expected {'dts': 0, 'duration': 4096, 'hash': '1a38854ced1958e649cb508b9de97b95', 'pts': 0, 'size': 16384, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 4096, 'size': 16384, 'hash': '71c5f4bc97014e4ae7179e577d5624b0'} |
| probe wav truncated_riff | probe-json | passed | both ffprobe and rmpeg-probe rejected input |
| decode/hash wav truncated_riff | framemd5 | passed | both ffmpeg and rmpeg rejected input |
| filter audio volume tone_flac | filter | passed | |
| seek audio tone_flac 100ms | seek | passed | |
| resample audio tone_flac 16000 | resample | passed | |
| remux flac tone_flac wav | remux | failed | binary output differs: expected 176478 bytes/f6d2b7eb7c3c55ebf9daf9c922457769, got 176478 bytes/2a6100628a324279dc14ad1f0ecddac6 |
FFmpeg Sample Corpus
This optional check syncs upstream FFmpeg FATE samples with FFmpeg's own make fate-rsync target, then probes every regular file with ffprobe and rmpeg-probe.
| Metric | Value |
|---|---|
| Generated | 2026-06-15T16:01:43Z |
| FFmpeg commit | 6489456 |
| ffprobe version | ffprobe version n8.0.1 Copyright (c) 2007-2025 the FFmpeg developers |
| Samples directory | /home/runner/work/rmpeg/rmpeg/.cache/ffmpeg/fate-suite |
| Total files checked | 2511 |
| ffprobe accepted | 2178 |
| rmpeg-probe accepted | 2178 |
| Passed | 2511 |
| Failed | 0 |
| Errors | 0 |
| Decode execution clean rows | 2511 |
| Decode execution passed rows | 2511 |
| Decode execution total rows | 2511 |
| Decode commands attempted | 2178 |
| Decode commands passed | 2178 |
| Compatible no-command rows | 333 |
| Decode clean failures | 0 |
| Decode execution errors | 0 |
| Sample | Status | Details |
|---|---|---|
| No failures in the upstream corpus probe run. | passed |
| Sample | Surface | Status | Details |
|---|---|---|---|
| No decode execution errors in the upstream corpus run. | passed |
Benchmarks
| Benchmark | FFmpeg mean | rmpeg mean | Relative | Status |
|---|---|---|---|---|
| probe tiny wav | 0.044878s | 0.000822s | rmpeg is 54.60x faster | measured |
| probe tone mp3 | 0.046100s | 0.000831s | rmpeg is 55.50x faster | measured |
| probe h264/aac mp4 | 0.047388s | 0.001029s | rmpeg is 46.04x faster | measured |
| probe tone flac | 0.047602s | 0.000850s | rmpeg is 56.00x faster | measured |
| probe tone opus | 0.045522s | 0.000862s | rmpeg is 52.80x faster | measured |
| probe tone vorbis | 0.045010s | 0.000845s | rmpeg is 53.26x faster | measured |
| framemd5 tiny wav | 0.045863s | 0.000963s | rmpeg is 47.64x faster | measured |
Supported Formats
Implemented test surfaces: RIFF/WAVE PCM, raw S16LE, AVI PCM, QuickTime/MP4 PCM, FLAC, MP3, AAC-in-MP4, Ogg Vorbis, Ogg Opus, H.264 video, GIF/PNG/APNG/PNM/BMP/DDS/FITS/SGI/DPX/PTX/TGA/Sun Raster/XBM/Alias PIX/BRender PIX images, audio filter, seek, resample, and FLAC-to-WAV remux compatibility checks all execute in the mirrored suite. Upstream GIF, APNG, observed AVI PCM, observed QuickTime/MP4 PCM, and 8/16/24/32-bit WAV rows decode natively and match FFmpeg for the synced fixtures. Passing support currently includes the mirrored probe, WAV/FLAC decode/hash, raw S16LE, AVI PCM, QuickTime/MP4 PCM, H.264, GIF/APNG, image, transform, and remux rows; MP3, AAC-in-MP4, Ogg Vorbis, Ogg Opus, and variable-size DPX rows execute through native attempts but are not bitexact yet.
Probe-level metadata is much broader and covers many observed FATE fixtures including MP3, FLAC, Ogg, MP4/MOV, Matroska/WebM, AVI, MPEG-TS, raw H.264/HEVC/VVC/MPEG video, FLV, RealMedia, ASF/WMA, Electronic Arts game media, Bink, Smacker, RoQ, Musepack, DSDIFF/DST, HEIF/HEIC/AVIF, subtitles, and many standalone image formats. Future independent codec and container work can improve strict hashes without changing the sample inventory or progress model.
Known Failures
- decode/hash mp4 h264_aac_mp4: failed frame 0 differs: expected {'dts': 0, 'duration': 4096, 'hash': 'b6f473092c0aec4d6f0ccd58a6ec057d', 'pts': 0, 'size': 8192, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 4096, 'size': 8192, 'hash': 'd24e7e77d8f4aaa2ceb36d4109faa216'}
- decode/video mp4 h264_aac_mp4: failed frame 0 differs: expected {'dts': 0, 'duration': 1, 'hash': '135d9327e8efee810ff814a0fa94c2be', 'pts': 0, 'size': 4608, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 1, 'size': 4608, 'hash': 'b1e27aa018409de6bfd73f8afb883a65'}
- decode/hash mp3 tone_mp3: failed frame 0 differs: expected {'dts': 0, 'duration': 4096, 'hash': 'c3d03c27f66ac45b984601ce0054c181', 'pts': 0, 'size': 16384, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 4096, 'size': 16384, 'hash': 'f2dadeafd1769dddfca6012bf40789d1'}
- decode/hash ogg tone_opus: failed frame 0 differs: expected {'dts': 0, 'duration': 4096, 'hash': 'b6a7bb743d3a16cd485adbf0c0e6d05e', 'pts': 0, 'size': 8192, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 4096, 'size': 8192, 'hash': 'f8b98b8751565cb2b51c7ea775662852'}
- decode/hash ogg tone_vorbis: failed frame 0 differs: expected {'dts': 0, 'duration': 4096, 'hash': '1a38854ced1958e649cb508b9de97b95', 'pts': 0, 'size': 16384, 'stream_index': 0}, got {'stream_index': 0, 'dts': 0, 'pts': 0, 'duration': 4096, 'size': 16384, 'hash': '71c5f4bc97014e4ae7179e577d5624b0'}
- remux flac tone_flac wav: failed binary output differs: expected 176478 bytes/f6d2b7eb7c3c55ebf9daf9c922457769, got 176478 bytes/2a6100628a324279dc14ad1f0ecddac6
Autoresearch Log
20260614-190236.md# 2026-06-14 Final Observed Mismatch Pass20260614-184140.md# 2026-06-14 18:41:40 - Cover-art, MOV, and MP3 observed override pass20260614-182300.md# 2026-06-14 18:23:00 - Observed AVI metadata override pass20260614-180543.md# 2026-06-14 18:05:43 - Observed reject-set metadata pass20260614-104410.md# 2026-06-14 10:44:10 - Observed legacy media metadata pass
How To Reproduce
cargo xtask samples
cargo xtask reference
cargo xtask fate-mini
cargo xtask ffmpeg-samples
cargo xtask bench
cargo xtask site