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
🏗️ 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:
@@ -23,7 +23,7 @@ use crate::utils::lock::RwLockSafe;
|
||||
/// Set from `player_set_video_settings` / `player_set_stream_quality`, and
|
||||
/// restored from the database at startup.
|
||||
///
|
||||
/// TRACES: UR-074 | DR-160
|
||||
/// TRACES: UR-074 | DR-162
|
||||
static STREAMING_QUALITY: RwLock<StreamingQuality> = RwLock::new(StreamingQuality::Original);
|
||||
|
||||
/// Apply a bandwidth ceiling to every subsequently-opened video stream.
|
||||
@@ -32,14 +32,14 @@ static STREAMING_QUALITY: RwLock<StreamingQuality> = RwLock::new(StreamingQualit
|
||||
/// property of the URL the server is transcoding for, so changing it mid-stream
|
||||
/// requires re-opening at the new quality (`player_set_stream_quality`).
|
||||
///
|
||||
/// TRACES: UR-074 | DR-160
|
||||
/// TRACES: UR-074 | DR-162
|
||||
pub fn set_streaming_quality(quality: StreamingQuality) {
|
||||
*STREAMING_QUALITY.write_safe() = quality;
|
||||
}
|
||||
|
||||
/// The ceiling currently applied to new video streams.
|
||||
///
|
||||
/// TRACES: UR-074 | DR-160
|
||||
/// TRACES: UR-074 | DR-162
|
||||
pub fn streaming_quality() -> StreamingQuality {
|
||||
*STREAMING_QUALITY.read_safe()
|
||||
}
|
||||
@@ -421,7 +421,7 @@ impl OnlineRepository {
|
||||
/// that suits the budget. `Original` keeps the historical 20/18 Mbps
|
||||
/// allowance, which is a transcode ceiling rather than a user-facing limit.
|
||||
///
|
||||
/// TRACES: UR-004, UR-074 | DR-140, DR-160 | UT-130, UT-156
|
||||
/// TRACES: UR-004, UR-074 | DR-140, DR-162 | UT-130, UT-156
|
||||
pub async fn get_video_stream_url(
|
||||
&self,
|
||||
item_id: &str,
|
||||
@@ -537,7 +537,7 @@ impl OnlineRepository {
|
||||
// Audio-only is already far under any video cap, but a user on the
|
||||
// bottom rungs of the ladder asked for *less traffic*, so take the
|
||||
// lower of the two rather than always 384 kbps.
|
||||
// TRACES: UR-074 | DR-160
|
||||
// TRACES: UR-074 | DR-162
|
||||
(
|
||||
"MaxStreamingBitrate",
|
||||
streaming_quality().audio_bitrate().min(384_000).to_string(),
|
||||
@@ -1473,7 +1473,7 @@ impl MediaRepository for OnlineRepository {
|
||||
// downstream is moot. `Original` keeps the historical "no ceiling"
|
||||
// sentinel so the default path negotiates exactly as before.
|
||||
//
|
||||
// TRACES: UR-074 | DR-160
|
||||
// TRACES: UR-074 | DR-162
|
||||
let quality = streaming_quality();
|
||||
let negotiated_bitrate = quality.max_bitrate().unwrap_or(999_999_999) as i64;
|
||||
if let Some(cap) = quality.max_bitrate() {
|
||||
@@ -1714,7 +1714,7 @@ impl MediaRepository for OnlineRepository {
|
||||
is_playback: true,
|
||||
// Live TV is video like any other, so the user's cap applies here
|
||||
// too — a channel opened at the source bitrate would walk straight
|
||||
// past a limit set for the connection. TRACES: UR-074 | DR-160
|
||||
// past a limit set for the connection. TRACES: UR-074 | DR-162
|
||||
max_streaming_bitrate: streaming_quality().max_bitrate().unwrap_or(20_000_000),
|
||||
};
|
||||
|
||||
@@ -2466,7 +2466,7 @@ mod tests {
|
||||
/// streaming ceiling, and restores the uncapped default afterwards — without
|
||||
/// it, a capped test running concurrently changes what an uncapped one sees.
|
||||
///
|
||||
/// TRACES: UR-074 | DR-160
|
||||
/// TRACES: UR-074 | DR-162
|
||||
static QUALITY_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
|
||||
|
||||
struct QualityFixture(#[allow(dead_code)] std::sync::MutexGuard<'static, ()>);
|
||||
@@ -2490,7 +2490,7 @@ mod tests {
|
||||
/// can carry. Capping only `MaxStreamingBitrate` would leave the server
|
||||
/// encoding 1080p into 2 Mbps.
|
||||
///
|
||||
/// TRACES: UR-074 | DR-160 | UT-156
|
||||
/// TRACES: UR-074 | DR-162 | UT-156
|
||||
#[tokio::test]
|
||||
async fn test_video_stream_url_applies_bitrate_cap() {
|
||||
let _fixture = QualityFixture::set(StreamingQuality::Mbps2);
|
||||
@@ -2512,7 +2512,7 @@ mod tests {
|
||||
/// The uncapped default must keep the exact transcode allowance this
|
||||
/// endpoint has always used, and must not start constraining resolution.
|
||||
///
|
||||
/// TRACES: UR-074 | DR-160 | UT-156
|
||||
/// TRACES: UR-074 | DR-162 | UT-156
|
||||
#[tokio::test]
|
||||
async fn test_video_stream_url_uncapped_keeps_legacy_allowance() {
|
||||
let _fixture = QualityFixture::set(StreamingQuality::Original);
|
||||
@@ -2535,7 +2535,7 @@ mod tests {
|
||||
/// The background-audio handoff is already cheap, but someone who capped the
|
||||
/// connection at 720 kbps asked for less traffic than its fixed 384 kbps.
|
||||
///
|
||||
/// TRACES: UR-040, UR-074 | DR-160 | UT-156
|
||||
/// TRACES: UR-040, UR-074 | DR-162 | UT-156
|
||||
#[tokio::test]
|
||||
async fn test_audio_only_stream_url_takes_the_lower_of_cap_and_default() {
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user