refactor(player): delete the webview video path; mpv selects its own tracks
DR-235 phase 3. Every video renderer is native now: mpv on Linux and Windows, ExoPlayer on Android, all drawing behind the transparent webview. The HTML5 <video> path is gone, not bypassed: - Frontend: hls.js, Html5PlayerAdapter and its compatibility shim, the createAdapter factory, streamTransport, hlsRecovery, timeTracking, videoFit, the <video>/<track> markup and every element handler in VideoPlayer (3277 -> 2144 lines), the experimentalNativeVideo store and its Settings toggle, webviewVideoFallback/supportsNativeVideo, and the setHtml5VideoState PiP bridge call. NativePlayerAdapter is the one video adapter; webview audio gets its own adapter kind. - Rust: use_html5 dropped from player_seek_video, player_switch_audio_track and player_set_stream_quality with the Html5* strategies and ReloadStream responses; use_html5_element and VideoBackend dropped from PlayerStatus; player_play_item always loads the backend (set_current_item removed); Capabilities::webview removed; the WebKitGTK GStreamer/VAAPI setup (and its gst-inspect spawn) removed. - Android: the HTML5 video state in PictureInPictureManager and ScreenWakeManager, and the bridge method feeding it. - CSP: connect-src loses http:/https: and worker-src loses blob: - both existed for hls.js; with it gone they were only an exfiltration channel and a blob worker for injected script. A test now keeps them out. mpv takes over what the <video> element did (mpv_tracks, UT-275): subtitles are the WebVTT list the play request carries, queued on sub-files and selected by position in that list, starting off; audio tracks are selected by position in the file; sid/aid are reset before each load. Without this, Linux video had no subtitle selection and a direct-play audio switch failed since mpv became its renderer. Verified: Rust 948 passing, and the same 948 cross-compiled for Windows under wine against the shipped DLL (track tests included); frontend 1111 passing; aarch64 debug APK builds. Lint warnings 158 -> 146, CI ratchet tightened to match. Not yet seen on Windows hardware.
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
|
||||
A cross-platform Jellyfin client. Business logic lives in a Rust backend
|
||||
(`src-tauri/`); a SvelteKit + TypeScript frontend (`src/`) handles presentation
|
||||
and talks to it over Tauri v2 IPC. Targets **Linux** (libmpv for audio and video) and
|
||||
**Android** (ExoPlayer); Windows still renders video in the webview `<video>`.
|
||||
and talks to it over Tauri v2 IPC. Targets **Linux** and **Windows** (libmpv for audio and video) and **Android**
|
||||
(ExoPlayer). There is no webview `<video>`: every video renderer is native,
|
||||
drawing behind the transparent webview.
|
||||
|
||||
Package manager is **bun**.
|
||||
|
||||
@@ -151,10 +152,11 @@ output as a reviewed draft, not a final changelog.
|
||||
- **Svelte frontend** (`src/`) — presentation only. Stores in
|
||||
`src/lib/stores/`, API wrappers in `src/lib/api/`, components in
|
||||
`src/lib/components/`.
|
||||
- **Playback layers** — Linux uses libmpv for audio and video (mpv draws video
|
||||
beneath the transparent webview); Windows still uses the webview HTML5
|
||||
`<video>` element for video; Android uses ExoPlayer with a foreground media
|
||||
service + `MediaSessionCompat`. Every mpv command goes through
|
||||
- **Playback layers** — Linux and Windows use libmpv for audio and video (mpv
|
||||
draws video beneath the transparent webview: the render API into a GTK surface
|
||||
on Linux, `wid` into the app window on Windows); Android uses ExoPlayer with a
|
||||
foreground media service + `MediaSessionCompat`. The webview `<video>`/hls.js
|
||||
path was deleted (DR-235). Every mpv command goes through
|
||||
`player/mpv_command.rs` (argv, never a command string) and every handle is
|
||||
hardened (`tls-verify=yes`, `ytdl=no`) — see DR-298/DR-299.
|
||||
- **tauri-specta** generates TypeScript bindings and typed events from the Rust
|
||||
@@ -170,7 +172,7 @@ canonical, maintained source; this file only summarizes. See
|
||||
| [02-svelte-frontend.md](docs/architecture/02-svelte-frontend.md) | Stores, repository architecture, MiniPlayer, autoplay, nav guard |
|
||||
| [03-data-flow.md](docs/architecture/03-data-flow.md) | Cache-first query flow, playback initiation, mode transfer |
|
||||
| [04-type-sync-and-threading.md](docs/architecture/04-type-sync-and-threading.md) | **Rust↔TS type sync, the IPC camelCase convention + param table, locking** |
|
||||
| [05-platform-backends.md](docs/architecture/05-platform-backends.md) | MpvBackend (Linux), ExoPlayerBackend (Android), MediaSession, HTML5 adapter |
|
||||
| [05-platform-backends.md](docs/architecture/05-platform-backends.md) | MpvBackend (Linux/Windows) incl. desktop native video, ExoPlayerBackend (Android), MediaSession |
|
||||
| [06-downloads-and-offline.md](docs/architecture/06-downloads-and-offline.md) | Download manager/worker, smart cache, offline commands |
|
||||
| [07-connectivity.md](docs/architecture/07-connectivity.md) | HTTP retry, ConnectivityMonitor, reachability model |
|
||||
| [08-database-design.md](docs/architecture/08-database-design.md) | Tables, relationships, key queries |
|
||||
@@ -188,10 +190,9 @@ and [docs/build/build-release.md](docs/build/build-release.md).
|
||||
player reports and never determine it.
|
||||
- **Unified player boundary.** UI controls playback *only* through the frontend
|
||||
facade `src/lib/player/index.ts` (`playerController`) — never by calling
|
||||
`commands.player*` directly. Webview HTML5 `<video>` reports its state back
|
||||
into Rust via `src/lib/player/html5Adapter.ts` and the `player_report_*`
|
||||
commands, so the controller stays the single source of truth in both native
|
||||
and HTML5 modes.
|
||||
`commands.player*` directly. Video has one adapter, `NativePlayerAdapter`,
|
||||
which only forwards intents; the backend performs every seek, track switch
|
||||
and quality change itself.
|
||||
- **Reachability from real traffic.** Server online/offline is derived from the
|
||||
outcome of actual repository requests (reported to `ConnectivityMonitor`), not
|
||||
a side-channel poller. The `/System/Info/Public` probe runs *only while
|
||||
@@ -316,8 +317,9 @@ tagged responses keep the Rust field names as-is (e.g. `new_url`, not `newUrl`).
|
||||
player or hold a lock — it deadlocks. On Android, bind a locked
|
||||
`AutoplayDecision` to a `let` *before* matching; a tokio `MutexGuard` held in
|
||||
the `match` scrutinee deadlocks the `AdvanceToNext` arm.
|
||||
- **VideoPlayer native mode**: no lifecycle calls after an `await` in `onMount`
|
||||
(it flips to HTML5 mode and breaks Android seek).
|
||||
- **VideoPlayer `onMount`**: no lifecycle calls after an `await` — they throw
|
||||
`lifecycle_outside_component` (this once silently switched seeks to a renderer
|
||||
that was not playing).
|
||||
- **Transcoded resume/seek**: `get_video_stream_url` must return the HLS
|
||||
`master.m3u8`, not `stream.mp4`, or transcoded playback never starts.
|
||||
- **Downloads** cap at 3 concurrent; the backend pump auto-starts pending rows.
|
||||
|
||||
Reference in New Issue
Block a user