docs(player): allocate UR-074/DR-162 for the streaming bitrate cap
🏗️ Build and Test JellyTau / Run Tests (push) Failing after 5m10s
🏗️ Build and Test JellyTau / Android Compile Check (push) Skipped
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m27s
Traceability Validation / Check Requirement Traces (push) Successful in 16s

The feature shipped tagged against DR-160, which a parallel session had
claimed for picture-in-picture in the meantime. Renumbered to DR-162
across the Rust and frontend TRACES comments (the PiP tags in
VideoPlayer.svelte, pictureInPicture.ts and nativeVideo.ts keep DR-160)
and regenerated bindings.ts.

Adds the requirement rows the tags point at: UR-074 for the user need, and
DR-162 covering why the cap has to reach the PlaybackInfo negotiation and
not only the transcode URL, why the ceiling is process-wide, and why the
Settings default persists while the in-player override does not. Notes
that this gives UR-070 its resume-at-the-same-point mechanism while the
server-offered rendition list that requirement also asks for stays
proposed. UT-156/157 record what the tests pin.

docs/specs/streaming-bitrate-cap.md carries the layer assignment — the
step definitions, the video/audio split, the resolution pairing and the
reload decision are all Rust; the frontend holds a serde token and the
labels it was handed.

TRACES: UR-074 | DR-162 | UT-156, UT-157
This commit is contained in:
2026-08-15 16:39:53 +02:00
parent 9c352fdb77
commit d49d027020
13 changed files with 197 additions and 38 deletions
+5 -5
View File
@@ -205,7 +205,7 @@ async playerGetVideoSettings() : Promise<VideoSettings> {
* frontend reads them here rather than encoding them — the same arrangement as
* [`player_get_eq_presets`].
*
* TRACES: UR-074 | DR-160
* TRACES: UR-074 | DR-162
*/
async playerGetStreamingQualities() : Promise<([StreamingQuality, string, string])[]> {
return await TAURI_INVOKE("player_get_streaming_qualities");
@@ -226,7 +226,7 @@ async playerGetStreamingQualities() : Promise<([StreamingQuality, string, string
* durable default belongs to Settings. `player_set_video_settings` is the one
* that writes to the database.
*
* TRACES: UR-074 | DR-160
* TRACES: UR-074 | DR-162
*/
async playerSetStreamQuality(repositoryHandle: string, quality: StreamingQuality, useHtml5: boolean, currentPosition: number | null, mediaSourceId: string | null, audioStreamIndex: number | null) : Promise<StreamQualityResponse> {
return await TAURI_INVOKE("player_set_stream_quality", { repositoryHandle, quality, useHtml5, currentPosition, mediaSourceId, audioStreamIndex });
@@ -2897,7 +2897,7 @@ export type StreamKind = "audio" | "video" | "subtitle" |
* Mirrors [`AudioTrackSwitchResponse`]: the backend decides whether the caller
* has to reload anything, so no strategy branch lives in the UI.
*
* TRACES: UR-074 | DR-160
* TRACES: UR-074 | DR-162
*/
export type StreamQualityResponse =
/**
@@ -2922,7 +2922,7 @@ export type StreamQualityResponse =
* bitrate so the encoder does not spend a small budget on pixels it cannot
* afford. See docs/specs/streaming-bitrate-cap.md.
*
* TRACES: UR-074 | DR-160
* TRACES: UR-074 | DR-162
*/
export type StreamingQuality =
/**
@@ -3057,7 +3057,7 @@ autoPlayMaxEpisodes?: number;
* `#[serde(default)]` so settings JSON persisted before this field existed
* loads as the previous behaviour (uncapped).
*
* TRACES: UR-074 | DR-160
* TRACES: UR-074 | DR-162
*/
streamingQuality?: StreamingQuality }
/**