Replace /queues + /bookmarks + /captures with one /crabidy fs provider whose track tomls link into a content-addressed store that de-duplicates audio by provider id and by content hash (architecture/crabidy-store.md). Green-field: no data migration. - crabidy_store.rs: CrabidyStore owns the state tree (state_dir/crabidy) and the data store (data_dir/crabidy); StoreIndex derived from the .cbd-store.toml sidecars. save() enumerates a source into a temp folder and swaps it in atomically (conflict refuses); capture_track dedups (already-stored -> provider-id -> hash -> new). Queue persistence lives here now (persist_current/load_current/save_snapshot/spawn_persister). - capture.rs: reduced to enumerate + Downloader::download_to + Progress; removed the Sink/capture_into/download-to-toml machinery. - orchestrator: one crabidy_client + crabidy_store, single crabidy_owns routing; get_lib_node annotates captured tracks via the store index. - rpc: capture_error_status helper; save_queue link-saves the live queue into /crabidy. playback persists/restores via CrabidyStore. - tidal/youtube set Track.provider_item_id (track id / video id). - cbd-tui: /crabidy/current, captured | row marker, delete confirmation removed (deletes never touch the store), cache-invalidation + help text. - delete bookmark_store/capture_store/queue_store; supersede their docs. See plan/summary.md for deviations (SaveQueue RPC kept; fs id left empty; shallow folder marking). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||
| README.md | ||
README.md
ytdy — the YouTube provider
Mounts YouTube at /youtube in the crabidy library.
How it works
Metadata comes from the pure-Rust rustypipe Innertube client:
/youtube/searchworks without any login. Press%to create a search term; the term becomes a persistent child node listing the top video results as tracks. Terms are renamable (e, re-runs the search) and deletable (d). Terms live in memory — a server restart forgets them, but navigating to an old term path recreates it./youtube/playlistsappears when a cookie login is configured and accepted: it lists the account's saved playlists.
Stream URLs are resolved through a minimal yt-dlp sidecar when
the binary is available (one bounded subprocess call per played or
captured track — no other functionality uses it). This is a deliberate
concession: YouTube currently caps tokenless stream URLs at their
leading ~1 MiB, and yt-dlp is the only maintained solver for the
cipher challenges that lift the cap; its URLs stream whole files at a
throttled ~32 KB/s (still ~2× audio bitrate). Without the binary the
provider still works, but playback of a track stops after roughly a
minute. Streams prefer audio/mp4 (AAC), the format the built-in
player decodes; captures therefore store .m4a files. See
architecture/youtube-rustypipe.md for the full analysis.
Search results and playlists are downloadable: W captures them with
audio into /captures/<name> (slow under the throttle, but captures
are resumable — re-capture the same name to continue).
Configuration — ~/.config/crabidy/ytdy.toml
All options with their defaults:
# Netscape cookies.txt export for the logged-in features (saved
# playlists). Export with a browser extension like "Get cookies.txt
# LOCALLY", ideally from an Incognito session you close afterwards.
# The provider caches the rotated session cookie under
# ~/.config/crabidy/rustypipe/, so the export only needs to be valid
# once. Default: unset (logged out; search still works).
# cookies = "/home/me/youtube-cookies.txt"
# Results per search term. Default: 20.
# search_results = 20
# Per-request timeout in seconds (Innertube calls; the yt-dlp sidecar
# gets at least 60 s). Default: 30.
# call_timeout_secs = 30
# The yt-dlp binary used ONLY for stream URLs. A bare name resolves
# via PATH. Default: "yt-dlp". Keep it fresh — a stale yt-dlp is the
# first suspect when YouTube playback breaks.
# binary = "yt-dlp"
# Optional rustypipe-botguard binary for PO-token attestation (also
# auto-detected on PATH). Currently ineffective upstream, but once
# rustypipe's web-client deciphering is fixed this makes streams work
# without yt-dlp. Default: unset.
# botguard_bin = "/home/me/.cargo/bin/rustypipe-botguard"
Secrets: the cookies file and the rustypipe cache grant access to your YouTube session — keep both private. The provider never logs their contents (paths only), and stream URLs are redacted from logs.
Failure behavior
- No network / broken client at startup: only
/youtubeis disabled, the server runs on. - Rejected or missing cookies: degrades to logged-out with a warning.
- Missing
yt-dlp: warning at startup; streams stop after ~1 MiB. 403 Forbiddenon streams in the log: YouTube's per-IP/per-video enforcement fluctuates; usually transient. If it persists, updateyt-dlp.