mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-04 00:47:00 +01:00
138 lines
7.5 KiB
Markdown
138 lines
7.5 KiB
Markdown
# proton-stream
|
|
|
|
A Netflix-style cross-platform client for **Proton Drive public links**.
|
|
|
|
Paste a share URL and its password; get a browsable, streamable library. No
|
|
Proton account, no server to host, no download step — episodes start playing in
|
|
seconds and the seek bar works.
|
|
|
|
Built on [`proton-sdk-rs`](https://github.com/narrrl/proton-sdk-rs), a pure-Rust
|
|
Proton Drive SDK.
|
|
|
|
## Why it works
|
|
|
|
A Proton Drive file's content blocks are each a self-contained PGP packet
|
|
decrypted under one shared session key. There is no sequential streaming session
|
|
to resume, so seeking costs exactly the blocks the seek lands on — a 2 GB episode
|
|
is playable without downloading 2 GB of it.
|
|
|
|
## Status
|
|
|
|
Early, but it is an app now: the picture lands **inside the window**, not in an
|
|
mpv window of its own. The SDK streaming surface, the catalog, the streaming
|
|
layer and the player are done and verified against a real share, and the app has
|
|
a library wall, a page per title with seasons and episodes,
|
|
resume-where-you-left-off, an overlay with a chapter-marked seek bar, a skip
|
|
button for openings and endings, next/previous episode with an "up next"
|
|
countdown, subtitle files beside the video, optional metadata, themes and share
|
|
management. What is left is mostly running the macOS packaging on a real Mac. See
|
|
`docs/DEVELOPMENT.md`.
|
|
|
|
A native Android 12+ client is under `android/`, sharing the Rust catalog and
|
|
streaming implementation through UniFFI. It features a modern Material 3 interface,
|
|
an immersive fullscreen player with auto-hiding controls, and offline downloads.
|
|
Its toolchain, emulator, signing, and release instructions are in [`docs/ANDROID.md`](docs/ANDROID.md).
|
|
|
|
An iOS 17+ client under `ios/` is a SwiftUI port of the Android one over the same
|
|
Rust engine, built as an unsigned `.ipa` for SideStore or AltStore; see
|
|
[`docs/IOS.md`](docs/IOS.md).
|
|
|
|
```bash
|
|
cargo run --release -p pstr-app # the app
|
|
proton-stream 'https://drive.proton.me/urls/TOKEN#fragment' # open the Add form with a link
|
|
```
|
|
|
|
One window at a time: a second launch brings the open window forward and
|
|
hands it any share link it was given, then exits.
|
|
|
|
The `pstr` CLI does the same work headlessly, and is what tells you which layer
|
|
is broken:
|
|
|
|
```bash
|
|
cargo run -p pstr-cli -- add --name anime 'https://drive.proton.me/urls/TOKEN#fragment'
|
|
cargo run -p pstr-cli -- crawl
|
|
cargo run -p pstr-cli -- list
|
|
cargo run -p pstr-cli -- metadata # opt-in; off unless configured
|
|
cargo run --release -p pstr-cli -- play --file Frieren --disk-cache
|
|
cargo run --release -p pstr-cli -- bench --file Frieren --verify
|
|
```
|
|
|
|
On a 761 MiB, 26-minute 1080p HEVC episode over a real password-protected link:
|
|
**2.3 s to first frame, ~1.5 s to resume after dragging to an arbitrary point,
|
|
61 MiB fetched for the first 38 seconds of playback.** Watch it again and the
|
|
disk cache serves it with **no network at all** — 0.3 s to first frame.
|
|
|
|
`bench` measures the same file without a player, reporting cold seek latency,
|
|
sustained throughput and peak memory, and `--verify` cross-checks a mid-file read
|
|
against the SDK's own range download.
|
|
|
|
## Design
|
|
|
|
| | |
|
|
|---|---|
|
|
| Topology | Fat client. No server; each viewer's app talks to Proton directly. |
|
|
| Auth | Public links only — but several, merged into one library. |
|
|
| Player | Embedded libmpv, drawing into the app's own GL surface: HEVC 10-bit, HDR and ASS subtitles with hardware decode. Volume, audio-track, subtitle and chapter pickers; skip-the-opening; next/previous episode and autoplay. The language picked is preferred for the next file too. |
|
|
| Transcoding | None. mpv demuxes and decodes natively. |
|
|
| UI | egui/eframe on glow; mpv renders into the same GL context. |
|
|
| Themes | The shipped near-black palette, Catppuccin Latte, Frappé, Macchiato and Mocha, and a Persona 5 one — black, white and one loud red, which is what the Red accent is there for — each with a choice of nine accents, drawn as a gradient unless you turn that off. Picked on the Settings page, applied without a restart. |
|
|
| Metadata | Filename parsing, with optional AniList/TMDB enrichment — **off by default**, because enabling it sends your library's titles to a third party. It brings posters, synopses, fanart and per-episode titles and synopses (for AniList, from ani.zip, which is sent the matched ids); a title the scorer refuses to guess about can be pinned by hand, and a pinned match is never overwritten. The library sorts by name, watch, add or air date, rating and popularity, folds a franchise into one tile, and shelves titles by director, studio and genre. See [docs/METADATA.md](docs/METADATA.md). |
|
|
| Platforms | Linux and Windows; macOS packaging is written but has not been run on a Mac. A native Android 12+ client is available featuring a Material 3 UI and immersive fullscreen playback, and an iOS 17+ port of it for sideloading. |
|
|
|
|
## Building
|
|
|
|
Rust 2024, MSRV 1.96.
|
|
|
|
```bash
|
|
cargo build --release
|
|
```
|
|
|
|
`pstr-player` needs libmpv development headers (`mpv` ≥ 2.0), and on Linux
|
|
`pstr-app` needs WebKitGTK 4.1's, for the window Proton's CAPTCHA is shown in.
|
|
On Windows the libmpv ones
|
|
come from the separate **mpv-dev** archive rather than mpv's player build, and
|
|
`libmpv-2.dll` ships next to the executable. The Proton SDK crates come from
|
|
crates.io; nothing here builds against a sibling checkout.
|
|
|
|
Installable artifacts — tarball, `.deb`, `.rpm`, Arch package, `.app`/`.dmg`,
|
|
and a portable `.zip` plus an `.msi` on Windows — are produced by
|
|
`scripts/build.sh` and `scripts\build.ps1`; `packaging/README.md` has the
|
|
per-platform detail.
|
|
|
|
Android builds use JDK 17, Android SDK 36/NDK 28, Gradle 8.13, `cargo-ndk`, and
|
|
UniFFI. Run `bash scripts/build-android.sh debug` after installing that toolchain;
|
|
see [`docs/ANDROID.md`](docs/ANDROID.md) for exact setup and release signing.
|
|
|
|
iOS builds need macOS with Xcode, XcodeGen and the `aarch64-apple-ios` Rust
|
|
target: `scripts/build-ios.sh all` writes `dist/proton-stream-<version>-ios.ipa`.
|
|
|
|
## Privacy
|
|
|
|
- The share URL fragment **is** the decryption password. It and any custom
|
|
password live in the OS credential store — Secret Service on Linux, Credential
|
|
Manager on Windows — never in a config file.
|
|
- Nothing leaves your machine except requests to Proton, unless you turn metadata
|
|
enrichment on. The player is fed through an in-process mpv stream callback, not
|
|
a local HTTP server: there is no port for another process on the machine to ask
|
|
for the plaintext, and mpv is handed an opaque token rather than a URL that
|
|
would put a share secret in its log and window title.
|
|
- The block cache holds decrypted content. It lives in your cache directory,
|
|
can be deleted at any time the app is not running, and can be sized or
|
|
emptied from Settings → Storage.
|
|
- A share link given as a command-line argument is visible to other users of
|
|
the machine in the process list while that launch runs, and may land in
|
|
shell history. Pasting it into the window (Ctrl+V) does neither.
|
|
- The desktop's media widget is handed the title, the episode and a `file://`
|
|
path to artwork already on disk — never a provider URL, so the shell never
|
|
contacts a metadata provider on its own.
|
|
|
|
## License
|
|
|
|
The shared Rust crates and desktop application are MIT licensed. The Android and
|
|
iOS applications and their combined native distributions are GPL-3.0-or-later; see
|
|
[`android/LICENSE.md`](android/LICENSE.md), [`ios/LICENSE.md`](ios/LICENSE.md) and
|
|
the bundled-component notices.
|
|
The desktop application embeds the Inter typeface, under the SIL Open Font
|
|
License 1.1 ([`crates/pstr-app/assets/fonts/Inter-OFL.txt`](crates/pstr-app/assets/fonts/Inter-OFL.txt)),
|
|
and the Phosphor icon font, under MIT.
|