Iris
"Your library, untethered." A homemade Netflix, literally: tracker retrieval and aggregation, a custom web player that digests the exotic, full Android TV and mobile apps. In Rust.
- Role
- Design, development, Android apps, operations.
- Period
- 2026
- Stack
- Rust (Axum, SQLite), librqbit, ffmpeg, React 19, WebCodecs, Kotlin (Compose for TV, Media3)
- Links


The brief
I wanted the equivalent of Netflix for my household: a search, a library that fills itself and playback on every screen in the house. Iris is that private media library. Accounts open by invitation, the sources are the trackers and indexers I configure, and each downloaded file is shared back with the other peers.
Between the first commit, on 8 May 2026, and version 1.5.0, on 1 October, Iris went through 30 releases.
In use
A search queries all trackers in parallel and returns a single ranked list. Each release is checked against TMDB, because indexer identifiers are often wrong. Playback starts as soon as the first pieces arrive.
The library keeps each account’s playback position and offers the next episode. Every three hours, the discovery shelves cross TMDB trends with what is available. When the disk fills up, Iris deletes the releases played longest ago.
Iris also offers live TV: the free channels from the iptv-org lists and free-to-air TV from the house antenna, received by an old set-top box.


Architecture
The server is a Rust binary that embeds its own BitTorrent engine: a file can be played while it downloads. Each client declares the formats and decoders it supports; the server answers with a manifest, and the client chooses its playback mode.
The web player contains six playback engines behind a single interface, from the lightest to the most expensive: from direct MP4 playback to HLS produced by the server, by way of MKV remuxing, WebCodecs decoding and HEVC to H.264 transcoding in a WebAssembly worker. If an engine fails, the player moves to the next one. I reduced the transcoder’s time to first frame, after a seek in the video, from 17.9 s to 3.8 s.
Terrestrial TV is received by an AirTies AIR 7310T running mainline Linux. I wrote its DVB driver from the registers read in the original firmware; Iris remuxes the channels into HLS and shares the box’s two tuners between viewers.
The Android TV app also works on phones. It embeds Media3’s FFmpeg and AV1 decoders, which lets the TV play DTS and 10-bit AV1.


Decisions
The work on the client side. The browser remuxes by itself; the server copies the streams and re-encodes only for a device that decodes a heavy 10-bit source in software.
One API contract for three clients. The server publishes its OpenAPI specification, from which the types of the web client and the TV app are generated: a divergence breaks the build.
Compatible updates. The APK installs from my server and updates from its settings. The server stays compatible with older versions of the app; a version header frames the rare breaking changes.
Trace back to the cause. On macOS, Firefox 154 failed to resume playback of HEVC files. A test page isolated the cause in Gecko, which skips CRA pictures as entry points; Iris converts the initial CRA into an IDR keyframe. I reported the issue to Mozilla with a 112 KB reproduction case.
Today
Iris 1.5.0 serves the household on the web, on Android TV and on phones, live TV included. The code is public at github.com/uplg/iris, and the set-top box driver at github.com/uplg/BCM7231B2.