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:
@@ -791,36 +791,15 @@ by exactly the inset.
|
||||
Unlike `addJavascriptInterface`, the inset push only writes CSS properties, so it
|
||||
can safely be re-sent on resume.
|
||||
|
||||
## Stream Transport
|
||||
## Stream Selection in the Player
|
||||
|
||||
**Location**: `src/lib/player/streamTransport.ts`
|
||||
**TRACES**: UR-079 | DR-225 | UT-214
|
||||
|
||||
`videoLoaderFor(selection, capabilities)` picks the loader for the webview
|
||||
`<video>` element — `hlsjs`, `nativeHls`, or `direct` — from the backend's tagged
|
||||
`selection.transport`. `elementSrcFor` is its template companion: the element's
|
||||
`src` is emptied only when hls.js is driving it.
|
||||
|
||||
The split is the point. **The transport is the stream's property and comes from
|
||||
Rust; whether a given loader exists is the browser's, and is the only thing
|
||||
decided here.**
|
||||
|
||||
> This replaced `currentStreamUrl.includes(".m3u8")`, which appeared twice in
|
||||
> `VideoPlayer.svelte` — once in the HLS `$effect` and once inline in the
|
||||
> template's `src`. Rust builds that URL and knows what it is; re-deriving it
|
||||
> here by substring match was a domain fact reconstructed in the presentation
|
||||
> layer, and it fails silently in both directions. The two tests that pin it are
|
||||
> the ones that failed against the old implementation: a `progressive` stream
|
||||
> whose URL contains `.m3u8` must **not** get an HLS loader, and an `hls` stream
|
||||
> whose URL contains no `.m3u8` must.
|
||||
>
|
||||
> Logic lives in a plain `.ts` module rather than in the component for the usual
|
||||
> reason — it is testable there. Same pattern as `episodeStrip.ts`.
|
||||
**TRACES**: UR-079 | DR-225, DR-227
|
||||
|
||||
`VideoPlayer` holds a `currentSelection`, not a URL string; `currentStreamUrl` is
|
||||
derived from it. A reload replaces the selection **wholesale** (the adapter's
|
||||
bridge takes a `StreamSelection`, not a URL), so transport and URL can never
|
||||
drift apart. The background-audio handoff states the transport it is moving to —
|
||||
derived from it. A reload replaces the selection **wholesale**, so transport and
|
||||
URL can never drift apart — the transport is the stream's property and comes from
|
||||
Rust, never from a substring match on the URL (which is what `.m3u8` sniffing in
|
||||
the component once did). The background-audio handoff states the transport it is moving to —
|
||||
progressive mp3 out, HLS back — via `selectionAt()`, rather than leaving it to be
|
||||
inferred.
|
||||
|
||||
@@ -833,21 +812,16 @@ ceiling above the source bitrate *is* the source.
|
||||
## Native Video Store
|
||||
|
||||
**Location**: `src/lib/stores/nativeVideo.ts`
|
||||
**TRACES**: UR-003, UR-004 | DR-188
|
||||
**TRACES**: UR-003, UR-004 | DR-188, DR-235
|
||||
|
||||
Two separate concerns live here, deliberately:
|
||||
`nativeVideoActive` — whether a native surface is on screen *right now*.
|
||||
Setting it toggles `data-native-video` on `<html>`, which is what the CSS in
|
||||
`app.css` keys off to clear the app's opaque backgrounds so the picture behind
|
||||
the webview shows. The backgrounds must come back the moment the player unmounts.
|
||||
|
||||
- `experimentalNativeVideo` — the user-facing opt-in flag, **defaulting to on**.
|
||||
Rust already decides *which backend this platform has* (`useHtml5Element` from
|
||||
`player_play_item`); this flag only *suppresses* that decision. It never turns
|
||||
native on where Rust says HTML5. An explicit stored choice wins in both
|
||||
directions, so someone who opted out is not re-enabled by a default flip —
|
||||
hence the `null` check rather than a bare `=== "true"`.
|
||||
- `nativeVideoActive` — whether a native surface is on screen *right now*.
|
||||
Setting it toggles `data-native-video` on `<html>`, which is what the CSS in
|
||||
`app.css` keys off to clear the app's opaque backgrounds. It is deliberately
|
||||
**not** derived from the flag: the backgrounds must come back the moment the
|
||||
player unmounts.
|
||||
It used to hold `experimentalNativeVideo`, a stored switch that could force video
|
||||
back to the webview `<video>` element. That element is gone (DR-235), and the
|
||||
switch with it.
|
||||
|
||||
See [05-platform-backends.md](05-platform-backends.md#native-video-compositing-android)
|
||||
for what is behind the WebView.
|
||||
|
||||
Reference in New Issue
Block a user