Open-sourcevideo tools
For streaming video, decryption and subtitle timing. Each one is documented, MIT licensed and tested on real streams.
Pick a tool
Download a stream, check its subtitles, fetch more. Three tools, all open source.
m314dl
★ 32CLIv0.3.6
MIT · Linux, macOS, Windows
Downloads HLS and DASH and decrypts CENC and cbcs with the keys you supply, in the same pass. There is no mp4decrypt step.
Homebrew
brew install m314dev/tap/m314dlScoop
scoop bucket add m314dev https://github.com/m314dev/scoop-bucket
scoop install m314dlGo
go install github.com/m314dev/m314dl@latestDocker
docker run --rm -v "$PWD:/data" ghcr.io/m314dev/m314dl -o out.mp4 <url>- cenc, cbcs, cens and cbc1 decrypted in memory, one fragment at a time
- HLS, DASH, Smooth Streaming, plain files and M3U playlists
- Records live streams and serves them again as HLS, MPEG-TS or DASH
- Resumes byte for byte after a hard kill
$ m314dl -sv 'res=1680:for=best' -sa best -o tos.mp4 https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.mpd
selected: video_eng=2200000.1.4 video 1680x750 2200kbps avc1.640028 [en] (video_eng=2200000)
selected: audio_eng=128002.0.1 audio 128kbps mp4a.40.2 [en] (audio_eng=128002)
100.0% | 370/370 segs | 194.6MiB | 2.3MiB/s
done: tos.mp4Every number on this page comes from a real run: the seconds below, the film, and the two subtitle files.



Faster in every case
Seconds for each tool to download, decrypt and mux the same 5-minute 1080p stream, best of three. Shorter is better. The harness is in bench/, so you can run it on your own machine.
m314dl vsd 0.5.0 N_m3u8DL-RE 0.6.0
HLS TS
HLS fMP4
DASH clear
DASH CENC
DASH cbcs
m314ss
★ 8CLI · library
MIT · needs FFmpeg
Listens to a video’s audio to decide whether a subtitle belongs to it. If it does, it fixes the timing. If not, it writes nothing.
Command line
go install github.com/m314dev/m314ss/cmd/m314ss@latestLibrary
go get github.com/m314dev/m314ss- Lines up cue starts with speech found in the audio, never with filenames
- Rejects a subtitle unless sigma and lift both clear 5
- Fixes offsets up to ±120 s and 23.976, 24 and 25 fps drift
- Finds candidates on SubDL and OpenSubtitles through subapi

$ m314ss -srt tos_en.srt -video tos.mp4 -o tos_en.synced.srt tos_en.synced.srt (sigma 5.1, +0.35s) $ m314ss -srt sintel_en.srt -video tos.mp4 -o /dev/null subtitle does not fit this video (sigma 4.5, need 5.0)
How m314ss decides
tos_en.srt · 76 cues
1 00:00:23,000 --> 00:00:24,500 You're a jerk, Thom. 2 00:00:25,000 --> 00:00:27,000 Look Celia, we have to follow our passions;
From Wikimedia Commons. Nobody has checked it against this cut of the film.
First the subtitle arrives, timing unchecked.
tos.mp4 · 12:14 of audio

speech starts cue starts
157
places where someone starts talking, found in the audio. The subtitle has 76 cue starts to line up against them.
Then it finds where speech starts.
offset search · −120 s to +120 s
Best: +0.35 s, one sharp spike. The dashed line is chance, 14.7%.
Best: −79.00 s, one of several bumps. The dashed line is chance, 16.2%.
Then it tries every offset.
verdict · its own subtitle
Match
- sigma 5.12 (needs 5)
- lift 23.4 points (needs 5)
- shift +0.35s

verdict · Sintel's subtitle
No match
- sigma 4.47 (needs 5)
- lift 33.8 points (needs 5)
Lift alone would have let this one through. The spread of the whole search is what rejects it, and nothing gets written.
Last, one offset stands out, or none does.
subapi
★ 1Go library
MIT · standard library only
One Source interface for SubDL and OpenSubtitles. Find returns candidates, and nothing downloads until you call Fetch.
Go
go get github.com/m314dev/subapi- Search by TMDB id, IMDb id, or title and year
- Season packs opened to the episode you asked for, never a neighbour
- OpenSubtitles results sorted by download count
- Your own *http.Client for timeouts and proxies
// one query, two sites; nothing downloads until Fetch sources := []subapi.Source{ &subapi.SubDL{APIKey: subdlKey}, &subapi.OpenSubtitles{APIKey: osKey, UserAgent: "myapp v1.0"}, } q := subapi.Query{TMDBID: 1396, Season: 1, Episode: 1, Lang: "ar"} for _, src := range sources { cands, err := src.Find(ctx, q) if err != nil { continue } for _, c := range cands { srt, err := c.Fetch(ctx) // one SRT, even from a season pack if err == nil { fmt.Println(c.Source, c.Release, len(srt)) } } }
Open source, all of it
Every tool here is MIT licensed, with its tests and its benchmark harness in the repo. Use it, fork it, send a fix.
Star a repo
New releases land on GitHub first. Star a tool to hear about them, or open an issue when a stream or a subtitle trips it up.
m314 on GitHubLet’s talk
Hiring for video, or running m314dl or m314ss in production and need a hand? I answer every email.
About me