From 05c41cb5c191cd410050f7115d60d27a035bff70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20Bene=C5=A1?= Date: Sun, 9 Aug 2026 01:33:07 +0200 Subject: [PATCH] Document the 5.5 interface: tabs, cookies, keys A new "Using it" page covering what a user needs and could not previously find written down anywhere: the tab order (Feed first, Watch last, and why), the Feed's two modes and the brakes on its refresh-on-open, where the account button is and what signing in with cookies buys, and the full keyboard and mouse table for the player -- including that F11 and Escape work from anywhere in the window, which matters because fullscreen hides the tab bar. Building gains the parts that only bite when working on the code: the render API embedding and its two hard rules (the render context must not outlive its GL context; nothing may reparent, screenshot or apply a graphics effect to the video widget), that pip install is a copy rather than a link, and how to test playback without depending on YouTube's throttling. Co-Authored-By: Claude Opus 5 (1M context) --- Building.md | 53 ++++++++++++++++++++++++-- Home.md | 1 + Using-it.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 Using-it.md diff --git a/Building.md b/Building.md index 13421af..3654a77 100644 --- a/Building.md +++ b/Building.md @@ -14,7 +14,10 @@ - ffmpeg (for download merging; the app can auto-install it) Without libmpv the app still runs — the Watch tab shows an install hint and -search/browse/download work normally. +feed/search/browse/download work normally. + +QtSvg is used for the interface icons. It ships with PySide6-Essentials, so +there is nothing extra to install. ## Run from source @@ -31,13 +34,55 @@ the Deno runtime (yt-dlp's JS challenge solver) into the SageTube data dir: - macOS: `~/Library/Application Support/SageTube/bin/` - Windows: `%LOCALAPPDATA%\SageTube\bin\` +The settings referenced in [Using it](Using-it) live in `sagetube_config.json` +beside those binaries, in `data/` rather than `bin/`. The subscriptions, feed +cache, watch history and play queue are in `sagetube_library.db` in the same +place. + +**Installing from source is a copy, not a link.** `pip install .` snapshots the +package into site-packages, so editing the checkout changes nothing until you +reinstall. Use `pip install -e .` while developing, or reinstall each time. + ## Notes on YouTube playback reliability Playback resolves streams through mpv's `ytdl_hook` using the managed yt-dlp. YouTube's CDN intermittently serves stalled streams to non-browser clients; -the player retries automatically (twice, after 25 s of no playback). Keeping -yt-dlp updated (built-in updater, stable or nightly channel) is the long-term -fix channel for extractor breakage. +the player retries automatically (twice, after 25 s of no playback) and shows a +buffering indicator meanwhile. Keeping yt-dlp updated (built-in updater, stable +or nightly channel) is the long-term fix channel for extractor breakage. + +## Notes on the embedded player + +The player renders libmpv into a `QOpenGLWidget` through mpv's **render API**. +The `wid=winId()` embedding path is not used: it does not work on native +Wayland. + +Two consequences worth knowing before changing anything in +`gui/ytsage_gui_player.py`: + +- **The mpv handle outlives the OpenGL context, and the render context must + not.** Qt destroys and recreates a widget's `QOpenGLContext` whenever the + widget moves to another top-level window, and libmpv allows one render + context per handle. `initializeGL()` therefore tears down before it creates, + teardown clears the update callback and frees with the GL context current, + and it is wired to `QOpenGLContext.aboutToBeDestroyed`. Getting this wrong + segfaults rather than failing visibly. +- **Nothing may reparent the video widget, screenshot it, or put a + `QGraphicsEffect` on an ancestor of it.** Fullscreen fullscreens the *main + window* for this reason; the tab cross-fade and the dialog blur both skip + their `grab()` when an OpenGL surface is present. + +Testing playback against YouTube is unreliable — it throttles non-browser +clients unpredictably. Generate a clip instead: + +```bash +ffmpeg -f lavfi -i testsrc=size=640x360:rate=25 -f lavfi -i sine=frequency=440 \ + -t 30 -c:v libx264 -pix_fmt yuv420p -c:a aac -shortest testclip.mp4 +``` + +`QT_QPA_PLATFORM=offscreen` works for GUI tests generally, but offscreen has no +real GL, so the render context never succeeds there — use a real display for +anything touching the player. ## Release workflows diff --git a/Home.md b/Home.md index bbd273f..de3dfb1 100644 --- a/Home.md +++ b/Home.md @@ -10,6 +10,7 @@ what it is and how to install it is in the | Page | What it is | |---|---| +| [Using it](Using-it) | The tabs, the Feed's two modes, signing in with cookies, and the player's keys and mouse. | | [Building](Building) | Requirements, building and running from source — including the mpv piece, without which the app is a downloader rather than a player. | | [Tracking-upstream](Tracking-upstream) | How the fork relates to YTSage, and how a merge from upstream is done. | | [Upstream-README](Upstream-README) | YTSage's own README, kept verbatim for reference. | diff --git a/Using-it.md b/Using-it.md new file mode 100644 index 0000000..fdbd7b4 --- /dev/null +++ b/Using-it.md @@ -0,0 +1,104 @@ +# Using SageTube + +## The tabs + +Five, in the order you move through them: + +| Tab | What it is | +|---|---| +| **Feed** | Your subscriptions and their recent uploads. Opens here. | +| **Search** | YouTube search, as a grid of cards. | +| **Browse** | A channel or playlist by URL — Videos / Shorts / Live for a channel. | +| **Downloads** | The full yt-dlp downloader inherited from YTSage. | +| **Watch** | The player and the play queue. | + +Watch is **last** on purpose: it is where the other tabs send you, not +somewhere you start. Every card has *Play*, *Queue* and a *Download* button +that opens the Downloads tab with the video ready to analyse. + +## The Feed + +Two modes, chosen with the selector at the top left: + +- **Local subscriptions** — subscribe to channels from Browse, and SageTube + aggregates their recent uploads itself. No account, no cookies. +- **YouTube account** — your real signed-in subscription feed. Needs cookies, + and is disabled until you have them. + +**Opening the tab refreshes it**, but conservatively: a refresh is one yt-dlp +run *per subscribed channel*, so only channels not seen for +`feed.auto_refresh_on_open_minutes` (default 30) are fetched, at most eight per +visit, and at most once per interval per session. The cached feed is on screen +immediately either way. The **Refresh** button always does the lot. + +Set `feed.auto_refresh_on_open_minutes` to `0` to switch automatic refreshing +off entirely. + +## Signing in with cookies + +The **account button in the top-right corner of the tab bar** shows whether +SageTube is using an account, and opens the cookie settings. The Feed offers +the same thing beside its mode selector when you have not signed in. + +Cookies are read from a browser profile (`--cookies-from-browser`) or from a +`cookies.txt` file. They enable the account feed, age-restricted and +members-only videos, and premium formats. **Changes take effect immediately** — +anything playing reloads at its current position. + +## Player keys and mouse + +The player takes focus when you click the video. Bindings work whenever the +player or one of its controls has focus, so they never interfere with typing in +the Search box or the Downloads URL field. + +| Key | Action | Key | Action | +|---|---|---|---| +| `Space`, `K` | Play / pause | `↑` / `↓` | Volume ±5 | +| `←` / `→` | Seek ∓5 s | `M` | Mute | +| `J` / `L` | Seek ∓10 s | `C` | Subtitles on / off | +| `Shift`+`←` / `→` | Seek ∓1 s | `[` / `]` | Speed ∓0.25× | +| `,` / `.` | Frame back / forward | `Backspace` | Normal speed | +| `0`–`9` | Jump to 0–90 % | `N` / `P` | Next / previous in queue | +| `Home` / `End` | Start / end | `Ctrl`+`→` / `←` | Next / previous | +| `F` | Fullscreen | `S` | Screenshot | + +**`F11` toggles fullscreen and `Escape` leaves it from anywhere in the +window**, not just the player — useful because fullscreen hides the tab bar. + +| Mouse | Action | +|---|---| +| Click | Play / pause | +| Double-click | Fullscreen | +| Wheel | Volume | +| `Ctrl` + wheel | Seek ±5 s | +| Right-click | Menu — speed, quality, subtitles, copy link, open in browser | + +In fullscreen the controls and the pointer hide after a few idle seconds and +come back on any movement. In a window they never hide, so nothing shifts under +the cursor. + +## Settings worth knowing + +Everything below lives in the config file — see +[Building](Building) for where that is on each platform. + +| Key | Default | What it does | +|---|---|---| +| `player.hwdec` | `auto` | `auto` picks a per-platform decoder list ending in software. Set `no` to force software decoding when diagnosing playback. | +| `player.default_quality` | `1080` | Maximum height the player requests. Also the quality selector in the control bar. | +| `player.resume` | `auto` | Resume where you left off. `off` always starts at the beginning. | +| `feed.per_channel_items` | `15` | Videos fetched per channel on a refresh. | +| `feed.auto_refresh_on_open_minutes` | `30` | Staleness before opening the Feed refreshes a channel. `0` disables. | +| `check_app_updates` | `false` | Check this repository's releases on startup. | +| `check_beta_updates` | `false` | Include pre-releases in that check. | + +**Updates are checked against this repository**, not upstream YTSage — see +[Tracking-upstream](Tracking-upstream) for why that distinction matters. The +yt-dlp, Deno and ffmpeg updaters are separate and track their own projects. + +## Language + +The interface is translated into fourteen languages, but the strings SageTube +added — the tab names, feed, cards, player and account text — exist only in +English so far. A non-English interface shows English for those and its own +language for everything inherited from YTSage.