Files
MyTool/scripts/backfill-lyrics.sh
T

65 lines
3.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
LIBRARY_DIR="${1:-/vol3/1000/音视频/MusicWork/Library}"
BASE_URL="${MANGTOOL_LYRICS_BASE_URL:-http://192.168.10.159:28883}"
AUTH="${MANGTOOL_LYRICS_AUTH:-}"
[[ -d "$LIBRARY_DIR" ]] || { echo "Library 不存在: $LIBRARY_DIR" >&2; exit 1; }
export BASE_URL AUTH
find "$LIBRARY_DIR" -type f \( -iname '*.mp3' -o -iname '*.flac' -o -iname '*.m4a' -o -iname '*.aac' -o -iname '*.ogg' -o -iname '*.opus' -o -iname '*.wma' \) -print0 |
while IFS= read -r -d '' audio; do
lrc="${audio%.*}.lrc"
if [[ -s "$lrc" ]] && python3 - "$lrc" <<'PY'
import re,sys
text=open(sys.argv[1],encoding='utf-8-sig',errors='replace').read().replace('\r','')
meta=re.compile(r'^\[(?:ti|ar|al|by|re|ve|offset):',re.I)
timed=re.compile(r'^\s*\[(?:\d{1,2}:)?\d{1,2}:\d{2}(?:\.\d+)?\]\s*(.*)$')
labels=re.compile(r'^(?:作词|作曲|词曲|编曲|制作人?|混音(?:师|助理)?|录音(?:师)?|工程师|弦乐|鼓和钢琴|电贝斯|额外编程|数字编辑|原唱|演唱|出品|发行|版权|produced|written|composer|arranged|lyrics?|music|artist|title)\s*[:\-].*$',re.I)
body=[]
for raw in text.split('\n'):
line=raw.strip()
if not line or meta.match(line): continue
match=timed.match(line); line=(match.group(1).strip() if match else line)
if line and not labels.match(line): body.append(line)
sys.exit(0 if len(body)>=2 and len(''.join(body).replace(' ',''))>=8 else 1)
PY
then
echo "SKIP $audio"
continue
fi
meta=$(ffprobe -v error -show_entries format_tags=title,artist -of json "$audio" 2>/dev/null || true)
result=$(AUDIO_META="$meta" python3 - <<'PY'
import json,os,sys,urllib.parse,urllib.request
m=json.loads(os.environ.get('AUDIO_META','{}')).get('format',{}).get('tags',{}); t=m.get('title','').strip(); a=m.get('artist','').strip()
if not t or not a: sys.exit(0)
req=urllib.request.Request(os.environ['BASE_URL'].rstrip('/')+'/lrc?'+urllib.parse.urlencode({'title':t,'artist':a}))
if os.environ.get('AUTH'): req.add_header('Authorization',os.environ['AUTH'])
try:
with urllib.request.urlopen(req,timeout=15) as r: rows=json.load(r)
except Exception: sys.exit(0)
def n(x): return ''.join(c.lower() for c in x if c.isalnum())
def meaningful(text):
import re
meta=re.compile(r'^\[(?:ti|ar|al|by|re|ve|offset):',re.I)
timed=re.compile(r'^\s*\[(?:\d{1,2}:)?\d{1,2}:\d{2}(?:\.\d+)?\]\s*(.*)$')
labels=re.compile(r'^(?:作词|作曲|词曲|编曲|制作人?|混音(?:师|助理)?|录音(?:师)?|工程师|弦乐|鼓和钢琴|电贝斯|额外编程|数字编辑|原唱|演唱|出品|发行|版权|produced|written|composer|arranged|lyrics?|music|artist|title)\s*[:\-].*$',re.I)
body=[]
for raw in text.replace('\r','').split('\n'):
line=raw.strip()
if not line or meta.match(line): continue
match=timed.match(line); line=(match.group(1).strip() if match else line)
if line and not labels.match(line): body.append(line)
return len(body)>=2 and len(''.join(body).replace(' ',''))>=8
best=None
for x in rows if isinstance(rows,list) else []:
l=x.get('lyrics','').strip(); ct=x.get('title',''); ca=x.get('artist','')
if not meaningful(l): continue
s=(45 if n(t)==n(ct) else 25 if n(t) in n(ct) or n(ct) in n(t) else 0)+(45 if n(a)==n(ca) else 20 if n(a) in n(ca) or n(ca) in n(a) else -40)
s+=10 if '[' in l and ':' in l else 0
if s>=60 and (best is None or s>best[0]): best=(s,l)
if best: sys.stdout.write(best[1])
PY
)
[[ -n "$result" ]] || { echo "MISS $audio"; continue; }
printf '%s\n' "$result" > "${lrc}.tmp" && mv -f "${lrc}.tmp" "$lrc"; echo "OK $lrc"
done