Fetch lyrics from LRCLIB (synced when available) and serve an admin media library of uploaded video and audio with cover art and embedded lyrics
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
"""auto_lyrics.py — transcribe saved songs locally and inject them as shared lyrics.
|
||||
|
||||
Free and offline: faster-whisper (CTranslate2, int8, CPU) runs on this machine —
|
||||
no API key, no credits. Audio comes from the server's own cache
|
||||
Lyrics come from LRCLIB first (free, key-less, often SYNCED) and otherwise from
|
||||
faster-whisper (CTranslate2, int8, CPU) running on this machine — no API key, no
|
||||
credits either way. Audio comes from the server's own cache
|
||||
(/api/media/<id>?a=1), results go to /api/notes/<id>/lyrics with baseRev, so a
|
||||
song someone already has lyrics for is never overwritten unless --overwrite.
|
||||
|
||||
@@ -124,6 +125,7 @@ def main():
|
||||
ap.add_argument('--watch', type=int, default=0, metavar='SECONDS',
|
||||
help='keep running: re-check for songs without lyrics every SECONDS (worker mode)')
|
||||
ap.add_argument('--state', default='', help='JSON file remembering instrumentals/failures (worker mode)')
|
||||
ap.add_argument('--no-web', action='store_true', help='skip the LRCLIB lookup and always transcribe')
|
||||
args = ap.parse_args()
|
||||
if args.watch:
|
||||
return watch(args)
|
||||
@@ -216,11 +218,18 @@ def run_once(args, api):
|
||||
|
||||
|
||||
def transcribe_one(args, api, model, vid):
|
||||
"""Transcribe one saved song and upload it. Returns a one-line result."""
|
||||
"""Give one saved song lyrics. Published (often synced) lyrics from LRCLIB
|
||||
beat a machine transcript, so that is tried first; transcription is the
|
||||
fallback. Returns a one-line result."""
|
||||
st, cur = api.call('GET', f'/api/notes/{vid}')
|
||||
live = (cur or {}).get('lyrics') if st == 200 else None
|
||||
if live and live['data']['lines'] and not args.overwrite:
|
||||
return 'skip: has lyrics'
|
||||
if not getattr(args, 'no_web', False):
|
||||
st, r = api.call('POST', f'/api/notes/{vid}/lyrics/web', {'overwrite': bool(args.overwrite)})
|
||||
if st == 200:
|
||||
m = r.get('match') or {}
|
||||
return f"saved rev {r.get('rev')} — LRCLIB {'synced' if r.get('synced') else 'plain'}: {m.get('artist', '')} – {m.get('track', '')}"
|
||||
st, audio = api.call('GET', f'/api/media/{vid}?a=1', raw=True)
|
||||
if st != 200:
|
||||
return f'no cached audio ({st})'
|
||||
|
||||
Reference in New Issue
Block a user