Skip to content

KJ: add lyrics to a quick version gen made without any (v0.150.0) - #314

Merged
beveradb merged 2 commits into
mainfrom
feat/sess-20261106-1858-manual-lyrics-search
Nov 8, 2026
Merged

beveradb merged 2 commits into
mainfrom
feat/sess-20261106-1858-manual-lyrics-search

Conversation

@beveradb

@beveradb beveradb commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Why

Live show 2026-11-06 01:24: Sombr "My Body Isn't Ready (Orchestral Version Live From Sound City)" played with audio but nothing on screen. gen's quick version found no lyrics (its LRCLIB lookup uses the exact decorated title), so the draft only said "(lyrics unavailable)" (gen_quick_versions.lyrics_tier = none, job f9764a9f). LRCLIB has synced lyrics for the plain title.

What

  • Rotation rows whose quick version has no lyrics show a red ⚠ NO LYRICS badge. Now Playing shows ⚠ No lyrics, add them while that file plays.
  • The modal auto-searches LRCLIB with the cleaned title ((…), […] and - Live … suffixes stripped). Each result shows whether it's synced and whether its length matches the video. Synced timing is on by default only within 4 s of the video length, otherwise the lyrics scroll at a steady pace. The KJ can also paste plain text or LRC (same idea as gen's review page reference lyrics).
  • POST /rotation/quick-lyrics re-renders only the video track with fastgen's crawl code (audio stream-copied, so no separation needed). It swaps the file in place (same path and media id) and records the new lyrics_tier. Since mpv keeps playing the old file it has open, the modal then offers Play it again from the start.
  • New: kj-controller/quick_lyrics.py, GET /rotation/quick-lyrics/search, POST /rotation/quick-lyrics. Docs: ARCHITECTURE + CHANGELOG.

Testing

  • 44 new tests (unit tests including a real ffmpeg render, plus route tests). All pass.
  • Full suite on the build host: 3 failures, all of which also fail on unmodified main (test_download_queues_item, test_download_failure_tracked, test_header_and_cards_share_one_column). test_ensure_hls_discards_stale_partial_and_relaunches failed once in the full run but passes on its own (flaky).
  • Manual check in a local dev server against real LRCLIB and a 3:45 test video: the badge shows, the search finds 15 results, 36 synced lines render in about 7 s, the badge clears, and the frame shows the lyrics on the reading row at the right time.
  • Local CodeRabbit review: 0 findings.

@coderabbitai ignore

🤖 Generated with Claude Code

https://claude.ai/code/session_012RYLVWXLyvTmHNnqQu3rzA

beveradb and others added 2 commits November 6, 2026 19:17
gen's quick version looks lyrics up on LRCLIB by the exact job title, so a
decorated title ("... (Orchestral Version Live From Sound City)") misses and
the draft only shows "(lyrics unavailable)" - audio but nothing on screen.

KJ UI: a NO LYRICS badge on the rotation row and a Now Playing button open a
modal that searches LRCLIB (cleaned title), flags whether synced timing matches
the video length, or takes pasted plain/LRC lyrics. The box re-renders only the
video track (fastgen crawl, audio stream-copied) in place in seconds, records
the new lyrics_tier, and offers to play the song again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RYLVWXLyvTmHNnqQu3rzA
…58-manual-lyrics-search

# Conflicts:
#	docs/CHANGELOG.md
#	kj-controller/pyproject.toml
@beveradb
beveradb merged commit e16348d into main Nov 8, 2026
1 check passed
beveradb added a commit to nomadkaraoke/karaoke-gen that referenced this pull request Nov 8, 2026
… overrides (v0.294.1) (#1257)

## Why
At a kjbox show on 2026-11-06, the make-it quick version for Sombr "My
Body Isn't Ready (Orchestral Version Live From Sound City)" (job
`f9764a9f`) rendered with only "(lyrics unavailable)" on screen. The
singer heard the backing track with no lyrics. LRCLIB only has this song
under the plain title.

## What
- `fetch_lrclib_lyrics`: if the exact `/get` and `/search` find nothing,
retry `/search` once with the title cleaned (`clean_title`: trailing
`(…)`/`[…]` groups and `- Live …`/`- Remaster` style suffixes removed).
- A synced hit from the retry keeps its timing only when its length is
within **4 s** of the audio, because a different length usually means a
different recording (studio vs live). Any other hit is used as plain
lyrics (constant crawl).
- Plain lyrics found under the exact title still win, and titles with
nothing to clean make no extra request.
- The quick render now searches with the job's
`lyrics_artist`/`lyrics_title` overrides, else the title without a tempo
label, the same names the review page uses. The displayed artist/title
are unchanged.
- Companion: kjbox v0.150.0 (nomadkaraoke/kjbox#314, deployed) lets the
KJ add lyrics on the box when a draft still comes back without any.

## Testing
- `backend/tests/test_quick_version.py`: 56 pass, including 17 new tests
(cleaned-title retry: matching sync, wrong-length sync downgraded to
plain, no duration, exact plain wins, failure paths, no retry for plain
titles; `clean_title` cases; lyrics-search names incl. tempo label and
overrides).
- Live LRCLIB check: `fetch_lrclib_lyrics('Sombr', "My Body Isn't Ready
(Orchestral Version Live From Sound City)", 224.5)` returns **synced, 37
lines**. Before this change it returned nothing.
- Local CodeRabbit review: 0 findings. Full suite left to CI.

@coderabbitai ignore

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_012RYLVWXLyvTmHNnqQu3rzA

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@beveradb
beveradb deleted the feat/sess-20261106-1858-manual-lyrics-search branch November 9, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant