feat(quality): the creator sets the rate — per tier, persisted, clamped only at YouTube's floor

The tier table cannot know a creator's connection, so it should not pretend to. The
Mbps box under the picker is theirs: the tier chooses geometry and frame rate, the
box chooses bits. Stored per tier (`Video.Rate.<tier>`), so tuning 1080p60 does not
touch 720p30, and none means "the shipped default" rather than zero.

Clamped at the tier's YouTube minimum (`RateLadder`), because a target under it
cannot hold the resolution; no ceiling otherwise, because a wrong guess is exactly
what live step-down exists to catch, and a creator who types 25 on a fibre line
should be allowed to find out. The tooltip carries YouTube's number for the tier.

`MainViewModel.EffectiveQuality` is the single substitution point, and the encoder
options, the step-down policy and the clip buffer all read it — so a rated tier can
never stream at the shipped default because one call site was missed.

One ordering trap found by the test: the constructor resolves the default tier
before the layout store is open, so a read at that point must not cache, or the
shipped default shadows the creator's stored rate for the whole run.

670 pass, 0 warnings.
This commit is contained in:
2026-11-12 08:11:13 -08:00
parent 93719a286d
commit f2cab5ca0f
9 changed files with 193 additions and 5 deletions
+20
View File
@@ -27,6 +27,26 @@ public partial class LayoutStore : IDisposable
public void SaveStickyAlertsUntilDismissed(bool enabled)
=> UpsertSetting("Notifications.StickyUntilDismissed", enabled ? "1" : "0");
/// <summary>The creator's own video rate for one tier, in Mbps, or null to use the shipped default.
/// Per tier because each has its own ceiling; the rate is a target the encoder is asked to hold,
/// so a stored number means the same thing on every run (CBR).</summary>
public double? LoadRatedMbps(string tierDisplay)
=> double.TryParse(GetSetting($"Video.Rate.{tierDisplay}"), out var mbps) && mbps > 0 ? mbps : null;
public void SaveRatedMbps(string tierDisplay, double? mbps)
{
if (mbps is not > 0)
{
using var delete = _connection.CreateCommand();
delete.CommandText = "DELETE FROM Settings WHERE Key = $key;";
delete.Parameters.AddWithValue("$key", $"Video.Rate.{tierDisplay}");
delete.ExecuteNonQuery();
return;
}
UpsertSetting($"Video.Rate.{tierDisplay}", mbps.Value.ToString("0.#"));
}
private static bool IsSupportedNotificationPosition(NotificationPosition position)
=> position is NotificationPosition.TopLeft or NotificationPosition.TopRight
or NotificationPosition.CenterLeft or NotificationPosition.CenterRight