<p align="center">
<img src="https://raw.githubusercontent.com/vbasky/sheathe/main/docs/banner.png" alt="sheathe — pure-Rust HLS / DASH / CMAF packager" width="100%">
</p>
# sheathe
[](https://github.com/vbasky/sheathe/actions/workflows/ci.yml)
[](https://crates.io/crates/sheathe)
[](https://docs.rs/sheathe)
[](#license)
[](https://medium.com/@vbasky/packaging-the-worlds-video-in-pure-rust-ff1f6b884fec)
**Pure-Rust HLS / DASH / CMAF media packager.** A memory-safe, dependency-light
alternative to [Shaka Packager](https://github.com/shaka-project/shaka-packager),
built and validated against it as the reference oracle.
📖 **Read the story:** [Packaging the World's Video in Pure Rust](https://medium.com/@vbasky/packaging-the-worlds-video-in-pure-rust-ff1f6b884fec)
> Status: **working VOD pipeline + encryption + a broad input matrix.** `probe`
> and `package` demux MP4, MPEG-TS, raw elementary streams, and WebM/Matroska,
> then write playable CMAF segments + DASH/HLS manifests with correct codec
> strings. Video: H.264, H.265, AV1, VP8/VP9. Audio: AAC, AC-3, E-AC-3, MP3,
> FLAC, Opus. Text: WebVTT, plus CEA-608 caption extraction from H.264/H.265 SEI.
> Encryption covers all four CENC schemes (`cenc`/`cens`/`cbc1`/`cbcs`) with
> multi-DRM `pssh` and key rotation. The path to full Shaka Packager parity (the
> last codec/format gaps, real-corpus oracle diffs, live) is tracked in
> [`ROADMAP.md`](./ROADMAP.md).
## Why
Mature DASH/HLS manifest *parsers* exist in Rust, but a mature *packager /
origin* does not. `sheathe` fills the Delivery lane: probe → ladder → CMAF
segment → DASH/HLS manifests, with no C/C++ dependencies.
## Workspace layout
| [`sheathe-core`](crates/sheathe-core) | Media model: streams, samples, timing, errors | `media/base` |
| [`sheathe-mp4`](crates/sheathe-mp4) | ISO-BMFF / fMP4 / CMAF box writing + fragmentation | `media/formats/mp4` + chunking |
| [`sheathe-ts`](crates/sheathe-ts) | MPEG-2 TS demux (PAT/PMT/PES) + audio codec parsers (AAC/AC-3/E-AC-3/MP3/FLAC) | `media/formats/mpeg` |
| [`sheathe-es`](crates/sheathe-es) | Raw elementary stream demux (Annex B, ADTS, AC-3/E-AC-3, MP3, FLAC) | `media/formats` |
| [`sheathe-mkv`](crates/sheathe-mkv) | WebM/Matroska (EBML) demux — VP8/VP9/AV1 + Opus | `media/formats/webm` |
| [`sheathe-text`](crates/sheathe-text) | Timed text: WebVTT input + CEA-608 caption extraction → `wvtt` | `media/formats/webvtt` |
| [`sheathe-dash`](crates/sheathe-dash) | MPEG-DASH `.mpd` generation | `mpd` |
| [`sheathe-hls`](crates/sheathe-hls) | HLS master + media playlist generation | `hls` |
| [`sheathe-crypto`](crates/sheathe-crypto) | Common Encryption (cenc / cbcs) | `media/crypto` |
| [`sheathe`](crates/sheathe) / [`sheathe-cli`](crates/sheathe-cli) | The `sheathe` binary / its CLI library | `app` (`packager`) |
## Install / build
```sh
cargo install sheathe # installs the `sheathe` binary
# or, from a checkout:
cargo run -p sheathe -- --help
```
## Usage (target CLI)
```sh
# Package an MP4 into 6s CMAF segments with both DASH and HLS manifests.
sheathe package input.mp4 --out site/ --segment-duration 6 --dash --hls
# Inspect what sheathe detects (MP4, MPEG-TS, WebM, raw ES, WebVTT).
sheathe probe input.mp4
sheathe probe input.ts
sheathe probe input.webm
sheathe package input.h264 input.ac3 --out site/ --dash --hls # CEA-608 auto-extracted
sheathe package input.webm subtitles.vtt --out site/ --dash
# Differential-test against Shaka Packager (when `packager` is on PATH).
just oracle input.mp4
```
## Method
Per the workspace's `revelo method`: implement in pure Rust, then
differential-test output (segments, MPD, playlists) against Shaka Packager on a
sample corpus. Numbers and bitstreams that can't be validated against the oracle
don't ship.
## MSRV
Rust **1.85** (declared in `Cargo.toml`'s `workspace.package.rust-version`). CI
reads that exact value and builds against it, so the MSRV can't drift.
## License
`MIT OR Apache-2.0`.