fix: normalize time tags in fetched lrc (why [00:17:06]?)
This commit is contained in:
@@ -5,34 +5,15 @@ Priority:
|
||||
2. Embedded lyrics in audio metadata (FLAC, MP3 USLT/SYLT tags)
|
||||
"""
|
||||
|
||||
import re
|
||||
import os
|
||||
from typing import Optional
|
||||
from loguru import logger
|
||||
from lrcfetch.models import TrackMeta, LyricResult, CacheStatus
|
||||
from lrcfetch.fetchers.base import BaseFetcher
|
||||
from lrcfetch.lrc import detect_sync_status
|
||||
from mutagen._file import File
|
||||
from mutagen.flac import FLAC
|
||||
|
||||
# Matches LRC time tags like [00:12.34] or [01:23.456]
|
||||
_LRC_TIME_TAG_RE = re.compile(r"\[\d{2}:\d{2}\.\d{2,3}\]")
|
||||
# Matches time tags that are all zeros
|
||||
_ZERO_TIME_TAG_RE = re.compile(r"^\[00:00\.0{2,3}\]$")
|
||||
|
||||
|
||||
def _detect_sync_status(text: str) -> CacheStatus:
|
||||
"""Determine whether lyrics text contains meaningful LRC time tags.
|
||||
|
||||
Returns UNSYNCED if no tags exist or all tags are [00:00.00].
|
||||
"""
|
||||
tags = _LRC_TIME_TAG_RE.findall(text)
|
||||
if not tags:
|
||||
return CacheStatus.SUCCESS_UNSYNCED
|
||||
for tag in tags:
|
||||
if not _ZERO_TIME_TAG_RE.match(tag):
|
||||
return CacheStatus.SUCCESS_SYNCED
|
||||
return CacheStatus.SUCCESS_UNSYNCED
|
||||
|
||||
|
||||
class LocalFetcher(BaseFetcher):
|
||||
@property
|
||||
@@ -58,7 +39,7 @@ class LocalFetcher(BaseFetcher):
|
||||
with open(lrc_path, "r", encoding="utf-8") as f:
|
||||
content = f.read().strip()
|
||||
if content:
|
||||
status = _detect_sync_status(content)
|
||||
status = detect_sync_status(content)
|
||||
logger.info(f"Local: found .lrc sidecar ({status.value})")
|
||||
return LyricResult(
|
||||
status=status, lyrics=content, source=self.source_name
|
||||
@@ -83,7 +64,7 @@ class LocalFetcher(BaseFetcher):
|
||||
break
|
||||
|
||||
if lyrics:
|
||||
status = _detect_sync_status(lyrics)
|
||||
status = detect_sync_status(lyrics)
|
||||
logger.info(f"Local: found embedded lyrics ({status.value})")
|
||||
return LyricResult(
|
||||
status=status,
|
||||
|
||||
@@ -7,12 +7,12 @@ Search results are filtered by duration when the track has a known length
|
||||
to avoid returning lyrics for the wrong version of a song.
|
||||
"""
|
||||
|
||||
import re
|
||||
import httpx
|
||||
from typing import Optional
|
||||
from loguru import logger
|
||||
from lrcfetch.models import TrackMeta, LyricResult, CacheStatus
|
||||
from lrcfetch.fetchers.base import BaseFetcher
|
||||
from lrcfetch.lrc import is_synced
|
||||
from lrcfetch.config import (
|
||||
HTTP_TIMEOUT,
|
||||
TTL_NOT_FOUND,
|
||||
@@ -23,34 +23,12 @@ from lrcfetch.config import (
|
||||
UA_BROWSER,
|
||||
)
|
||||
|
||||
# Matches LRC time tags like [00:12.34] or [01:23.456]
|
||||
_LRC_TIME_TAG_RE = re.compile(r"\[\d{2}:\d{2}\.\d{2,3}\]")
|
||||
# Matches time tags that are all zeros: [00:00.00] or [00:00.000]
|
||||
_ZERO_TIME_TAG_RE = re.compile(r"^\[00:00\.0{2,3}\]")
|
||||
|
||||
_HEADERS = {
|
||||
"User-Agent": UA_BROWSER,
|
||||
"Referer": "https://music.163.com/",
|
||||
}
|
||||
|
||||
|
||||
def _is_synced_lrc(text: str) -> bool:
|
||||
"""Check whether *text* contains actual LRC time tags with non-zero times.
|
||||
|
||||
Returns False if:
|
||||
- No time tags at all
|
||||
- All time tags are [00:00.00] (unsynced disguised as synced)
|
||||
"""
|
||||
lines_with_tags = _LRC_TIME_TAG_RE.findall(text)
|
||||
if not lines_with_tags:
|
||||
return False
|
||||
# Check if ALL tags are zero — if so, it's unsynced
|
||||
for tag in lines_with_tags:
|
||||
if not _ZERO_TIME_TAG_RE.match(tag):
|
||||
return True # Found at least one non-zero tag
|
||||
return False
|
||||
|
||||
|
||||
class NeteaseFetcher(BaseFetcher):
|
||||
@property
|
||||
def source_name(self) -> str:
|
||||
@@ -186,7 +164,7 @@ class NeteaseFetcher(BaseFetcher):
|
||||
return LyricResult(status=CacheStatus.NOT_FOUND, ttl=TTL_NOT_FOUND)
|
||||
|
||||
# Determine sync status
|
||||
synced = _is_synced_lrc(lrc)
|
||||
synced = is_synced(lrc)
|
||||
status = CacheStatus.SUCCESS_SYNCED if synced else CacheStatus.SUCCESS_UNSYNCED
|
||||
logger.info(
|
||||
f"Netease: got {status.value} lyrics for song_id={song_id} "
|
||||
|
||||
Reference in New Issue
Block a user