fix lyrics
This commit is contained in:
100
cmdnat/pipe.py
100
cmdnat/pipe.py
@@ -5,6 +5,7 @@ import sys
|
||||
import json
|
||||
import socket
|
||||
import re
|
||||
import threading
|
||||
from datetime import datetime, timedelta
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
from pathlib import Path
|
||||
@@ -20,6 +21,8 @@ from SYS.config import get_hydrus_access_key, get_hydrus_url
|
||||
|
||||
_ALLDEBRID_UNLOCK_CACHE: Dict[str,
|
||||
str] = {}
|
||||
_NOTES_PREFETCH_INFLIGHT: set[str] = set()
|
||||
_NOTES_PREFETCH_LOCK = threading.Lock()
|
||||
|
||||
|
||||
def _repo_root() -> Path:
|
||||
@@ -389,6 +392,99 @@ def _set_mpv_item_context(store: Optional[str], file_hash: Optional[str]) -> Non
|
||||
pass
|
||||
|
||||
|
||||
def _get_lyric_prefetch_limit(config: Optional[Dict[str, Any]]) -> int:
|
||||
try:
|
||||
raw = (config or {}).get("lyric_prefetch_limit")
|
||||
if raw is None:
|
||||
return 5
|
||||
value = int(raw)
|
||||
except Exception:
|
||||
return 5
|
||||
return max(0, min(20, value))
|
||||
|
||||
|
||||
def _prefetch_notes_async(
|
||||
store: Optional[str],
|
||||
file_hash: Optional[str],
|
||||
config: Optional[Dict[str, Any]],
|
||||
) -> None:
|
||||
if not store or not file_hash:
|
||||
return
|
||||
|
||||
key = f"{str(store).strip().lower()}:{str(file_hash).strip().lower()}"
|
||||
with _NOTES_PREFETCH_LOCK:
|
||||
if key in _NOTES_PREFETCH_INFLIGHT:
|
||||
return
|
||||
_NOTES_PREFETCH_INFLIGHT.add(key)
|
||||
|
||||
cfg = dict(config or {})
|
||||
|
||||
def _worker() -> None:
|
||||
try:
|
||||
from MPV.lyric import (
|
||||
load_cached_notes,
|
||||
set_notes_prefetch_pending,
|
||||
store_cached_notes,
|
||||
)
|
||||
from Store import Store
|
||||
|
||||
cached = load_cached_notes(store, file_hash, config=cfg)
|
||||
if cached is not None:
|
||||
return
|
||||
|
||||
set_notes_prefetch_pending(store, file_hash, True)
|
||||
|
||||
registry = Store(cfg, suppress_debug=True)
|
||||
backend = registry[str(store)]
|
||||
notes = backend.get_note(str(file_hash), config=cfg) or {}
|
||||
store_cached_notes(store, file_hash, notes)
|
||||
try:
|
||||
debug(
|
||||
f"Prefetched MPV notes cache for {key} keys={sorted(str(k) for k in notes)}"
|
||||
)
|
||||
except Exception:
|
||||
debug(f"Prefetched MPV notes cache for {key}")
|
||||
except Exception as exc:
|
||||
debug(f"MPV note prefetch failed for {key}: {exc}", file=sys.stderr)
|
||||
finally:
|
||||
try:
|
||||
from MPV.lyric import set_notes_prefetch_pending
|
||||
|
||||
set_notes_prefetch_pending(store, file_hash, False)
|
||||
except Exception:
|
||||
pass
|
||||
with _NOTES_PREFETCH_LOCK:
|
||||
_NOTES_PREFETCH_INFLIGHT.discard(key)
|
||||
|
||||
thread = threading.Thread(
|
||||
target=_worker,
|
||||
name=f"mpv-notes-prefetch-{file_hash[:8]}",
|
||||
daemon=True,
|
||||
)
|
||||
thread.start()
|
||||
|
||||
|
||||
def _schedule_notes_prefetch(items: Sequence[Any], config: Optional[Dict[str, Any]]) -> None:
|
||||
limit = _get_lyric_prefetch_limit(config)
|
||||
if limit <= 0:
|
||||
return
|
||||
|
||||
seen: set[str] = set()
|
||||
scheduled = 0
|
||||
for item in items or []:
|
||||
store, file_hash = _extract_store_and_hash(item)
|
||||
if not store or not file_hash:
|
||||
continue
|
||||
key = f"{store.lower()}:{file_hash}"
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
_prefetch_notes_async(store, file_hash, config)
|
||||
scheduled += 1
|
||||
if scheduled >= limit:
|
||||
break
|
||||
|
||||
|
||||
def _get_playlist(silent: bool = False) -> Optional[List[Dict[str, Any]]]:
|
||||
"""Get the current playlist from MPV. Returns None if MPV is not running."""
|
||||
cmd = {
|
||||
@@ -1143,6 +1239,8 @@ def _queue_items(
|
||||
except Exception as e:
|
||||
debug(f"Warning: Could not initialize Store registry: {e}", file=sys.stderr)
|
||||
|
||||
_schedule_notes_prefetch(items, config)
|
||||
|
||||
# Dedupe existing playlist before adding more (unless we're replacing it)
|
||||
existing_targets: set[str] = set()
|
||||
if not clear_first:
|
||||
@@ -2226,6 +2324,8 @@ def _start_mpv(
|
||||
hydrus_header = _build_hydrus_header(config or {})
|
||||
ytdl_opts = _build_ytdl_options(config, hydrus_header)
|
||||
|
||||
_schedule_notes_prefetch(items[:1], config)
|
||||
|
||||
cookies_path = None
|
||||
try:
|
||||
from tool.ytdlp import YtDlpTool
|
||||
|
||||
Reference in New Issue
Block a user