1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-22 11:15:41 +02:00

feat: YouTube Music audio capture (ytm: shorthand, Spotify detection, stalled job recovery) (#19)

* feat: add YouTube Music and Spotify source detection

- Add Source variants: YouTubeMusicTrack, YouTubeMusicPlaylist,
  SpotifyTrack, SpotifyAlbum, SpotifyPlaylist
- ytm:ID shorthand → music.youtube.com/watch?v=ID (audio-only, forced
  in core regardless of caller quality hint)
- ytm:playlist/ID and music.youtube.com/playlist URLs detected but
  fail with 'not yet implemented' via fail_run
- Spotify URLs/shorthands detected and fail fast with clear DRM error
  via fail_run (after run item created, so status is visible in /runs)
- source_metadata: youtube_music/music/audio and spotify/music/audio
  (entity_kind='music' for UI pill, representation_kind='audio' stored)
- locator_to_ytdlp_url includes YouTubeMusicTrack for probe endpoint
- generate_entry_title: 'Title — Artist' for YTM tracks
- Frontend: isVideoSource handles ytm: and music.youtube.com/watch;
  Spotify returns false (no probe, clear server error on submit)
- Placeholder updated to include ytm:ID
- SOURCE_ICONS: youtube_music (red disc) and spotify (green waves)
- 14 new tests covering all new sources (163 total, all pass)

* fix: prevent yt-dlp playlist expansion and stalled run recovery

- Add --no-playlist to ytdlp::download and fetch_metadata: URLs with a
  list= parameter (e.g. music.youtube.com/watch?v=ID&list=RDAMVM…) no
  longer cause yt-dlp to expand the full playlist and hang; both the
  metadata probe and the download are now single-item only

- Fix fail_stalled_capture_jobs to also recover archive_runs and
  archive_run_items: capture_jobs.run_uid is NULL at crash time so a
  join is unreliable; instead fail all archive_runs/items still
  in_progress directly, then recount failed_count via subquery.
  Startup recovery now makes the Runs UI reflect the correct failed
  state after a hard shutdown

- Expand fail_stalled_jobs_on_restart test to assert archive_run and
  archive_run_item rows are also marked failed, not just capture_jobs

* fix: use play triangle for youtube_music icon
This commit is contained in:
TheGeneralist 2026-07-06 15:34:14 +02:00 committed by GitHub
parent 339076e6a2
commit 21b11c211f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 362 additions and 7 deletions

View file

@ -109,7 +109,12 @@ pub fn download(
let out_template = temp_dir.join(format!("{timestamp}.%(ext)s"));
let mut cmd = Command::new(&ytdlp);
cmd.arg(&path).arg("-f").arg(quality_format(quality));
cmd.arg(&path)
.arg("-f").arg(quality_format(quality))
// This function is only called for single-item sources; --no-playlist
// prevents yt-dlp from expanding a list= query parameter into a full
// playlist download (e.g. music.youtube.com/watch?v=ID&list=RDAMVM…).
.arg("--no-playlist");
if is_audio {
// -x guarantees audio-only even when /best falls back to a combined
// A/V format. No --audio-format → native remux only, no re-encode.
@ -166,6 +171,10 @@ pub fn fetch_metadata(path: &str) -> Option<String> {
let out = std::process::Command::new(&ytdlp)
.arg("--dump-json")
// Same rationale as download(): only called for single-item sources;
// prevents --dump-json from emitting one JSON object per playlist item
// when the URL contains a list= parameter.
.arg("--no-playlist")
.arg(path)
.output()
.ok()?;