feat(downloads): automatic PO-token provider (bgutil sidecar) to beat YouTube bot-detection
YouTube increasingly demands a Proof-of-Origin token (or shows 'confirm you're not a bot'). Instead of manual cookies, run the bgutil POT provider as a sidecar that mints tokens on demand: - compose: bgutil-pot service (brainicism/bgutil-ytdlp-pot-provider:1.3.1, port 4416, init) - requirements: bgutil-ytdlp-pot-provider==1.3.1 plugin (version pinned to the image) - config: DOWNLOAD_POT_BASE_URL (http://bgutil-pot:4416) + DOWNLOAD_PLAYER_CLIENTS (web_safari,web,tv — POT-capable; the default android_vr client never requests a token) - formats.build_ydl_opts wires extractor_args youtube:player_client + youtubepot-bgutilhttp:base_url Verified: the sidecar mints a valid PO token (BotGuard challenge solved) and yt-dlp fetches it from the provider. NOTE: end-to-end download couldn't be confirmed here because the test IP got hard-flagged by YouTube from heavy testing (~16 GB + dozens of extractions) — a hard abuse block needs cooldown/cookies, which POT doesn't lift; POT bypasses the normal soft bot-check.
This commit is contained in:
parent
d7fe3c34e8
commit
03a1865aa8
5 changed files with 58 additions and 4 deletions
|
|
@ -138,6 +138,18 @@ class Settings(BaseSettings):
|
|||
# Whether THIS process runs the download worker loop. On for the dedicated worker
|
||||
# container, off for the API (which keeps the scheduler). Mirrors scheduler_enabled.
|
||||
worker_enabled: bool = False
|
||||
# Base URL of the bgutil PO-token provider sidecar. When set, the download worker asks it
|
||||
# for YouTube Proof-of-Origin tokens (bypasses bot-detection + unlocks high-quality
|
||||
# formats). Empty disables it (yt-dlp still works, but may hit "confirm you're not a bot").
|
||||
download_pot_base_url: str = "http://bgutil-pot:4416"
|
||||
# yt-dlp player clients to use (comma-separated). POT-capable clients (web_safari/web) must
|
||||
# be used for the PO token to actually apply; the default clients (android_vr) don't request
|
||||
# one. Empty = yt-dlp's own default. Admin-tunable when YouTube shifts what works.
|
||||
download_player_clients: str = "web_safari,web,tv"
|
||||
|
||||
@property
|
||||
def player_client_list(self) -> list[str]:
|
||||
return [c.strip() for c in self.download_player_clients.split(",") if c.strip()]
|
||||
# How many downloads the worker runs concurrently (claimed via FOR UPDATE SKIP LOCKED).
|
||||
download_worker_concurrency: int = 2
|
||||
# How often (empty pending queue) the worker polls for a new job, in seconds.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue