{"id":50334872,"url":"https://github.com/vbasky/revelo","last_synced_at":"2026-06-06T03:04:28.765Z","repository":{"id":360875763,"uuid":"1252094360","full_name":"vbasky/revelo","owner":"vbasky","description":"A safe, fast Rust port of MediaInfoLib — reads technical and tag metadata from 177 audio, video, image, and container formats. Drop-in libmediainfo replacement (C ABI + CLI), differential-tested byte-for-byte against the mediainfo oracle.","archived":false,"fork":false,"pushed_at":"2026-05-29T05:15:12.000Z","size":1205,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-29T05:23:53.035Z","etag":null,"topics":["audio","c-api","cli","codec","container-formats","ffi","image","libmediainfo","media","mediainfo","mediainfo-alternative","metadata","metadata-extraction","multimedia","parser","rust","video"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vbasky.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-28T07:23:01.000Z","updated_at":"2026-05-29T05:15:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vbasky/revelo","commit_stats":null,"previous_names":["vbasky/revelio","vbasky/revelo"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/vbasky/revelo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbasky%2Frevelo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbasky%2Frevelo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbasky%2Frevelo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbasky%2Frevelo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vbasky","download_url":"https://codeload.github.com/vbasky/revelo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbasky%2Frevelo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33652986,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio","c-api","cli","codec","container-formats","ffi","image","libmediainfo","media","mediainfo","mediainfo-alternative","metadata","metadata-extraction","multimedia","parser","rust","video"],"created_at":"2026-05-29T13:00:14.769Z","updated_at":"2026-05-29T13:00:23.155Z","avatar_url":"https://github.com/vbasky.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Revelo\n\n![revelo — read technical metadata from any media file, in pure Rust](docs/banner.png)\n\nA library and CLI for containers, audio \u0026 video codecs, image formats, subtitle\nstreams, archives, and embedded tags. A port of MediaInfoLib, validated\nbyte-for-byte against the C++ `mediainfo` oracle through differential testing.\n\n**Name:** *Revelo* is Latin *to reveal/unveil* (and a backronym: **R**eveals **E**very **V**ideo \u0026 **E**ncoding **L**ayer **O**utput) — it reveals the technical metadata hidden inside media files.\n\n[![crates.io](https://img.shields.io/crates/v/revelo-core?logo=rust\u0026color=orange)](https://crates.io/crates/revelo-core)\n[![docs.rs](https://img.shields.io/docsrs/revelo-core?logo=docsdotrs)](https://docs.rs/revelo-core)\n[![CI](https://img.shields.io/github/actions/workflow/status/vbasky/revelo/ci.yml?branch=master\u0026logo=github\u0026label=CI)](https://github.com/vbasky/revelo/actions)\n[![License](https://img.shields.io/crates/l/revelo-core)](LICENSE)\n[![MSRV](https://img.shields.io/badge/MSRV-1.85-blue)](https://www.rust-lang.org)\n[![Parsers](https://img.shields.io/badge/parsers-194-blueviolet)](docs/formats.md)\n\n## How it reads a file\n\nFirst revelo detects the format (every parser races to claim the bytes), then it\nwalks the container's *native* on-disk structure, reading fields box-by-box. An\nMP4/MOV file is a tree of boxes (\"atoms\") — `moov` holds the metadata, `mdat` the\ncoded samples:\n\n```text\n  ftyp                          file brand: isom · qt · M4A …\n  moov                          movie-level metadata\n    mvhd                        timescale, duration → General: Duration\n    trak                        one per track\n      tkhd                      track geometry → Video: Width, Height\n      edts ▸ elst               edit list / start delay\n      mdia\n        mdhd                    media header → Language\n        hdlr                    vide·soun·subt·text → selects stream kind\n        minf ▸ stbl             sample table\n          stsd                  codec sample entry → Format (avc1/hvc1/mp4a…)\n            avcC ▸ hvcC ▸ esds  codec config → Profile, Level, BitDepth\n            colr ▸ pasp         colour, pixel aspect → primaries, DAR\n            dvcC ▸ dvvC         Dolby Vision → HDR_Format\n          stts                  time-to-sample → FrameRate\n          stsz                  sample sizes → StreamSize, BitRate\n          stco ▸ co64           chunk offsets\n    udta ▸ meta ▸ ilst          iTunes tags, cover art → General: Title\n  mdat                          coded samples — sized; scanned for x264/x265 tags\n```\n\n(`▸` marks a box that just wraps the next.) revelo walks every container's\n*native* structure the same way — here are the other big families.\n\n**Matroska / WebM** — EBML elements (`id ▸ size ▸ data`) under one Segment:\n\n```text\n  EBML                          header: DocType (matroska / webm), version\n  Segment                       the single top-level element\n    SeekHead                    index of the elements below\n    Info                        TimestampScale, Duration, Segment UUID\n    Tracks ▸ TrackEntry         CodecID → Format; Video/Audio sub-elements\n                                → Width, Height, Channels, SamplingRate\n    Tags                        Title, Encoder, cover art\n    Cluster ▸ SimpleBlock       coded frames (sized; timestamps only)\n```\n\n**MPEG-TS** — a flat stream of 188-byte packets, demuxed by PID:\n\n```text\n  packet · 188 B                sync 0x47 · PID · payload-unit-start\n  PAT  (PID 0)                  lists each program's PMT PID\n  PMT                           elementary streams: PID + stream_type\n  PES                           → Video/Audio: Format + codec params\n```\n\n**RIFF** — chunked; AVI and WAV share the layout:\n\n```text\n  RIFF 'AVI '                   LIST hdrl ▸ avih (frame rate, dimensions)\n    LIST strl ▸ strh/strf       per-stream header + format → codec params\n    LIST movi                   interleaved samples (00dc, 01wb, …)\n  RIFF 'WAVE'                   fmt (codec, rate, channels) · data\n    bext ▸ iXML ▸ axml          BWF metadata → Title, timecode, loudness\n```\n\nWhatever the container, the output is the same: one **General** stream for the\nfile plus one stream per track — **Video · Audio · Text · Image · Menu · Other**.\n\n## MediaInfoLib comparison\n\nRevelo is a from-scratch port of MediaInfoLib v26.05. Every line is new Rust —\nno C++ translation, no FFI wrappers, no generated bindings.\n\n| | MediaInfoLib | Revelo |\n| --- | --- | --- |\n| **Language** | C++ | Pure Rust |\n| **Memory safety** | Manual | Compile-time guaranteed |\n| **Build** | `./Configure` + `make` + 10 system deps | `cargo build` (no system libs) |\n| **Install** | `apt install mediainfo` / `brew install mediainfo` | `brew install revelo` or `cargo install revelo-cli` |\n| **Parser model** | Virtual `File__Analyze` hierarchy | `fn(\u0026mut FileAnalyze) -\u003e bool` flat table, parallel race via rayon |\n| **Output fidelity** | Reference oracle | Byte-equal XML (differential harness) |\n| **License** | BSD-2-Clause | BSD-2-Clause |\n| **Format support** | ~200 formats | 194 parsers, 185 fields |\n| **WASM** | No | Compiles on `wasm32-unknown-unknown` |\n\n## Project scale\n\n| Metric | Value |\n| --- | --- |\n| Parsers | 193 across 8 domains |\n| Output fields | 185 (all gaps closed) |\n| Output formatters | 10 — XML / Text / JSON + 7 domain |\n| Workspace crates | 15 |\n| Tests | 579 passing |\n| License | BSD-2-Clause |\n| MSRV | Rust 1.85+ (edition 2024) |\n\n## Format coverage\n\n| Category | Parsers | Coverage | Formats |\n| --- | --- | --- | --- |\n| Containers | 42 | 98% | MP4/MOV, MKV/WebM, AVI, MPEG-TS, MPEG-PS, WAV, AIFF, Ogg, FLV, MXF, +32 more |\n| Audio | 56 | 100% | AAC/ADTS, MP3, AC-3/4, DTS/DTS-UHD, FLAC, Opus, Vorbis, TrueHD/Atmos, Dolby E, PCM, ADM, MGA, CELT, MPEG-H 3D, **IAMF/Eclipsa Audio**, **AC-4 IMS/JOC**, SMPTE ST 302/331/337, +37 more |\n| Video | 28 | 100% | AVC, HEVC, VVC, AV1, VP8/VP9, MPEG-2, VC-1, VC-3/DNxHD, ProRes, FFV1, H.263, MPEG-4V, Theora, Y4M, Canopus HQ, CineForm, Dirac, HDR Vivid, **Dolby Vision RPU**, **HDR10+**, **SL-HDR1**, **HLG/PQ**, **CTA-861**, +8 more |\n| Image | 19 | 100% | JPEG, PNG, GIF, BMP, TIFF, WebP, ICO, PSD, DPX, EXR, DDS, BPG, PCX, TGA, ArriRaw, Amiga Icon, RLE, AVIF Gain Map, HEIF |\n| Text/Subtitles | 21 | 100% | SubRip, TTML, Timed Text, PGS, DVB Subtitle, Teletext, EIA-608/708, CDP, SCC, N19, PDF, SDP, PAC, DTvCC, SCTE-20, Kate, CMML, ARIB STD-B24/B37, WebVTT |\n| Archives | 11 | 100% | ZIP, 7z, RAR, TAR, gzip, bzip2, ACE, ISO 9660, ELF, Mach-O, MZ/PE |\n| Tags | 12 | 86% | ID3v1/v2, APE Tag, Vorbis Comment, Lyrics3, EXIF, XMP, ICC, IIM/IPTC, C2PA, PropertyList, SphericalVideo |\n| Reader | 4 | 100% | File, Directory, HTTP, MMS |\n\nComplete format catalog with spec references: **[docs/formats.md](docs/formats.md)**\n\nComplete field coverage with sources: **[docs/field_coverage.md](docs/field_coverage.md)**\n\n## Architecture\n\nThe crate stack, from consumers at the top down to the foundation:\n\n```text\n┌────────────────────────────────────────────────────────────┐\n│  CLI (revelo)        C ABI (revelo-cdylib)                 │  frontends\n├────────────────────────────────────────────────────────────┤\n│  revelo-export       revelo-reader                         │  output / input\n├────────────────────────────────────────────────────────────┤\n│  revelo-dispatcher — parser table + parallel detect()       │  dispatch\n├────────────────────────────────────────────────────────────┤\n│  container · audio · video · image · text · tag · archive    │  parsers (193)\n├────────────────────────────────────────────────────────────┤\n│  revelo-core (FileAnalyze engine)     revelo-util                │  foundation\n└────────────────────────────────────────────────────────────┘\n   revelo-diff — differential harness, diffs output vs the mediainfo oracle\n```\n\n## Crates\n\nFifteen workspace crates: a foundation layer, seven format-parser domains, the\noutput/API surface, and the differential test harness.\n\n### Foundation\n\n| Crate | Role | Status |\n| --- | --- | --- |\n| `revelo-util` | ZenLib port — `Ztring`, bit reader, integer/float types | Stable |\n| `revelo-core` | Analysis engine — `FileAnalyze` byte reader, stream model, demux/trace, config dispatch, computed fields | Stable |\n| `revelo-dispatcher` | Parser table (single source of truth) + parallel `detect()` | Stable |\n\n### Format parsers\n\n| Crate | Role | Status |\n| --- | --- | --- |\n| `revelo-parsers-container` | 42 containers — MP4, MKV, AVI, MPEG-TS/PS, WAV, Ogg, MXF, … | Stable |\n| `revelo-parsers-audio` | 56 audio codecs — AAC, MP3, AC-3/4, DTS, FLAC, Opus, TrueHD, … | Stable |\n| `revelo-parsers-video` | 28 video codecs — AVC, HEVC, VVC, AV1, VP9, ProRes, … | Stable |\n| `revelo-parsers-image` | 19 image formats — JPEG, PNG, TIFF, WebP, DPX, EXR, … | Stable |\n| `revelo-parsers-text` | 21 subtitle/caption formats — SubRip, PGS, Teletext, EIA-608/708, … | Stable |\n| `revelo-parsers-tag` | 12 tag formats — ID3v1/v2, EXIF, XMP, Vorbis Comment, … | Stable |\n| `revelo-parsers-archive` | 11 archive/binary formats — ZIP, 7z, RAR, TAR, ELF, Mach-O, … | Stable |\n\n### Output \u0026 API\n\n| Crate | Role | Status |\n| --- | --- | --- |\n| `revelo-export` | 10 output formatters — XML, Text, JSON + EBUCore/MPEG-7/PBCore/NISO/FIMS/Graph/reVTMD | Stable |\n| `revelo-reader` | Input layer — File, Directory, HTTP, MMS | Stable |\n| `revelo-cli` | The `revelo` command-line binary | Stable |\n| `revelo-cdylib` | C ABI (`MediaInfo_*`) — drop-in replacement for libmediainfo | Stable |\n\n### Tooling\n\n| Crate | Role | Status |\n| --- | --- | --- |\n| `revelo-diff` | Differential harness — diffs revelo's output against the `mediainfo` oracle | Stable |\n\n## Installation\n\n```sh\nbrew install revelo                              # Homebrew (macOS / Linux)\ncargo install revelo-cli                         # CLI only (binary)\ncargo add revelo-core                            # library (core + dispatcher)\ncargo add revelo-export                          # library (output formatters)\n```\n\nOr add individual parser crates as needed:\n\n```sh\ncargo add revelo-parsers-container\ncargo add revelo-parsers-audio\ncargo add revelo-parsers-video\ncargo add revelo-parsers-image\ncargo add revelo-parsers-text\ncargo add revelo-parsers-tag\ncargo add revelo-parsers-archive\n```\n\n## Library usage\n\nProbe a file from Rust — the full analysis engine is exposed through `revelo-core`:\n\n```rust\nuse revelo_core::{FileAnalyze, FileLevelInfo, fill_file_level_fields};\nuse revelo_dispatcher::detect;\n\nlet bytes = std::fs::read(\"video.mp4\")?;\n\n// 1. Detect the format (parallel parser race)\nlet parser = detect(\u0026bytes).expect(\"no parser matched\");\n\n// 2. Run the winner on a fresh state\nlet mut fa = FileAnalyze::new(\u0026bytes);\nparser(\u0026mut fa);\n\n// 3. Fill derived General-stream fields\nfill_file_level_fields(\u0026mut fa, \u0026FileLevelInfo {\n    file_size: bytes.len() as u64,\n    extension: Some(\"mp4\"),\n    modified_unix_secs: None,\n    local_offset_secs: 0,\n});\n\n// 4. Read back metadata\nfor stream in fa.streams() {\n    println!(\"{:?}:\", stream.kind());\n    for (key, value) in stream.iter() {\n        println!(\"  {key} = {value}\");\n    }\n}\n```\n\nFor XML output (byte-equal with mediainfo):\n\n```rust\nuse revelo_export::to_xml;\nlet xml = to_xml(fa.streams(), \"video.mp4\", \"26.05\");\n```\n\n## Design\n\n| Principle | Description |\n| --- | --- |\n| **Pure Rust** | No C++ FFI, no system DLLs, no `pkg-config` — a single `cargo build` |\n| **Harness-validated** | Every ported parser is diffed against the `mediainfo` oracle for byte-equal XML |\n| **Race + walk** | All parsers race in parallel to detect the format; the winner re-parses from a fresh state to extract every field |\n| **Container-native** | Each container is walked through its *own* on-disk structure (boxes, EBML, RIFF chunks, PES packets) — not a unified abstraction |\n| **No unsafe** | `#![deny(unsafe_code)]` enforced workspace-wide |\n| **BSD-2-Clause** | Permissive license, no GPL restrictions |\n\n## Output formats\n\n- **XML** — byte-equal with the MediaInfoLib oracle\n- **Text** — 42-column layout, duration as `X s Y ms`\n- **JSON** — MediaInfo-compatible `{media:{@ref, track:[...]}}` structure\n- **EBUCore, MPEG-7, PBCore, NISO, FIMS, Graph, reVTMD** — 7 domain formatters\n\n## Quick start\n\n```sh\n# build the workspace\ncargo build --release\n\n# inspect a file (text / json / xml)\ncargo run -p revelo-cli -- --text path/to/media.mp4\ncargo run -p revelo-cli -- --json path/to/media.mp4\ncargo run -p revelo-cli -- --xml  path/to/media.mp4\n\n# build the C ABI shared library (libmediainfo drop-in)\ncargo build -p revelo-cdylib --release\n\n# diff revelo's output against the mediainfo oracle\ncargo run -p revelo-diff -- path/to/file\n```\n\n## Status\n\nAll layers are implemented and validated:\n\n| Layer | Status | Detail |\n| --- | --- | --- |\n| Format parsers | ✓ | 194 parsers across 8 domains |\n| Output fields | ✓ | 185 fields, all gaps closed |\n| Output formatters | ✓ | XML/Text/JSON + 7 domain |\n| Reader layer | ✓ | File, Directory, HTTP, MMS |\n| Core infra | ✓ | demux/trace/config dispatch, channel math, IBI, MIME, computed |\n| Element trees | ✓ | RIFF, Ogg, MP4 box tree for trace/debug |\n| Multi-file | ✓ | BDMV M2TS concatenation, SRT/SST sidecars, duplicate resolution |\n\n**Verified:** all tests pass against the differential harness (byte-equal XML for\nthe format subset with oracle samples).\n\n**Blocked — unverifiable against the oracle:** `File_Apv` (APV), `File_Av2`\n(AV2), `File_Ancillary` (SMPTE 436 VANC), and `File_Umf` (Ikegami UMF) are\nintentionally **not** ported. Correctness here is defined as output-match\nagainst `mediainfo` v26.05, and none of these can produce a sample *and* oracle\noutput to diff against:\n\n- **APV** — ffmpeg 8.x ships only a raw APV muxer, no encoder; mediainfo v26.05\n  doesn't surface APV, so there's no oracle target.\n- **AV2** — no encoder exists anywhere yet; not in the v26.05 oracle.\n- **Ancillary** — only exists embedded in MXF (no standalone sample), and is a\n  ~1000-line VANC/CDP/AFD parser.\n- **Umf** — proprietary Ikegami format with no obtainable sample.\n\nPorting these would mean translating ~3.7k lines of C++ blind, with no way to run\nthe differential harness — contrary to the project's harness-validated workflow.\nThey become tractable only with real sample files (and, for APV/AV2, a newer\nmediainfo). DCP PKL, the one validatable holdout, is implemented (BYTE-EQUAL).\n\n## Future improvements\n\nPlanned features and high-impact areas for the next development phase:\n\n### Output \u0026 Reporting\n\n- **CSV / YAML export** — Machine-friendly formats for pipeline integration\n  (straightforward addition to `revelo-export`).\n- **HTML report** — Self-contained visual report with collapsible sections and\n  summary cards.\n- **Summary mode** — Aggregate statistics across a file collection: codec\n  distribution, resolution ranges, bitrate profiles, container breakdown.\n\n### Batch \u0026 Comparison\n\n- **Glob / batch processing** — `revelo --json \"**/*.mp4\"` to process an entire\n  directory tree and output as NDJSON or an array. Currently only single-file +\n  BDMV playlists are supported.\n- **Diff mode** — `revelo --diff a.mkv b.mkv` to show which fields differ\n  between two files (user-facing, distinct from the harness-oriented\n  `revelo-diff`).\n\n### Fidelity gaps\n\n- **Elementary-stream extraction** — Wire PES payload parsing for MPEG-TS\n  (AVC/AAC), VP9 frame headers in MKV/WebM, FLV per-tag AVC bitstream, and AV1\n  OBU sequence headers in MP4 to close the remaining ~10 divergence gaps.\n- **Blocked fields** — `FrameRate_Mode_Original` and `Format_Settings_SBR` need\n  real-world test samples to validate against the oracle.\n\n### Broader reach\n\n- **Python bindings** via PyO3 — natural fit for the media analysis audience,\n  with the existing C ABI (`revelo-cdylib`) as a proven bridge.\n- **NPM package** — WASM builds already compile on `wasm32-unknown-unknown`; a\n  documented JS API and NPM release would enable browser-side media inspection.\n\n### Extraction\n\n- **Cover art / attachment extraction** — `--extract-attachments` flag for MKV\n  Attachments, MP4 Cover boxes, and ID3 APIC frames.\n- **Subtitle extraction** — Dump subtitle streams to SRT/VTT from any container.\n- **Thumbnail / keyframe offset** — Report byte offset of the first keyframe\n  (no decoding — metadata-position only).\n\n### Quality of life\n\n- **Stream filtering** — `--video-only`, `--audio-only`, `--stream 0:1` to\n  select specific tracks by index.\n- **Container verification** — Structural integrity checks: MOOV atom\n  completeness, EBML well-formedness, RIFF size consistency.\n- **Format conversion** — `revelo --to-json --from-xml` to transform between\n  export formats without re-parsing.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbasky%2Frevelo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvbasky%2Frevelo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbasky%2Frevelo/lists"}