feat: keyboard seek, playback speed, and persist edited settings
Player - Arrow keys seek by 5s, Shift for a 30s jump on long recordings, J/L for +-30s, Space toggles playback, and up/down adjust volume. Dragging a scrubber across a multi-hour replay is unusable — one pixel is tens of seconds — so keys are the practical way to move around a long recording. - The shortcuts ignore key events from inputs, so typing a chapter time in the replay editor no longer scrubs the video. - Add a playback speed selector. It is a replay tool: speeding a live stream up would only push it further ahead of the encoder's buffer. Replay editor - Stop playback restarting on every edit. The player's source effect depended on the `lines` and `qualities` arrays, and callers such as the replay editor pass fresh literals on every render, so adding a chapter or typing a title was treated as a source change and reloaded the stream from the beginning. The effect now depends on the resolved source URL instead of the arrays it came from. Measured: adding three chapters leaves the media requests unchanged and the playhead advancing. Settings persistence - Settings edited in the UI were applied to the in-memory settings object and never written down, so the brand, transcode ladder and load-balancing strategy silently reverted to the config.py defaults on every restart. They are now saved to backend/settings.json (atomic temp-file replace) and re-applied at startup, with only known keys accepted so a hand-edited file cannot inject arbitrary attributes. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
1 parent
cdf591f933
commit
8e61dc111c
7 files changed
+232
-29
No files matched your search
@@ -2,6 +2,7 @@ from fastapi import APIRouter, HTTPException, Depends
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
from config import settings
|
||||
from services.settings_store import save_settings
|
||||
from routes.auth import require_auth
|
||||
from services.load_balancer import lb
|
||||
from services.multicast_detector import multicast_detector
|
||||
@@ -83,6 +84,9 @@ async def update_strategy(body: StrategyUpdate, _: bool = Depends(require_auth))
|
||||
settings.load_balance_strategy = body.strategy
|
||||
if body.multicast_enabled is not None:
|
||||
settings.multicast_enabled = body.multicast_enabled
|
||||
# Persisted for the same reason as the brand: in-memory only meant a restart
|
||||
# silently restored the defaults.
|
||||
save_settings()
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user