fix: tighten lyric placeholder detection

This commit is contained in:
2026-07-22 00:13:39 +08:00
parent b0d1b1766d
commit 2ba121b0c1
4 changed files with 17 additions and 11 deletions
@@ -127,6 +127,7 @@ public class LyricsService {
String normalized = lyrics.replace("\uFEFF", "").replace("\r", "");
int lines = 0;
int chars = 0;
int timedLines = 0;
for (String raw : normalized.split("\\n")) {
String line = raw.trim();
if (line.isEmpty() || line.matches("^\\[(?:ti|ar|al|by|re|ve|offset):.*$")) continue;
@@ -134,8 +135,10 @@ public class LyricsService {
String body = timed.matches() ? timed.group(1).trim() : line;
if (body.isEmpty() || META_LINE.matcher(body).matches()) continue;
lines++;
if (timed.matches()) timedLines++;
chars += body.replaceAll("\\s+", "").length();
}
if (timedLines > 0) return lines >= 3 && chars >= 12;
return lines >= 2 && chars >= 8;
}
private static byte[] readLimited(InputStream in) throws Exception { try (InputStream x = in; ByteArrayOutputStream b = new ByteArrayOutputStream()) { byte[] buf = new byte[8192]; int n, total = 0; while ((n = x.read(buf)) >= 0) { total += n; if (total > MAX_BYTES) throw new IllegalArgumentException("歌词响应过大"); b.write(buf, 0, n); } return b.toByteArray(); } }
@@ -30,7 +30,7 @@ class LibraryHealthServiceTest {
Path album = root.resolve("Artist").resolve("Album");
Files.createDirectories(album);
Files.write(album.resolve("01 - Song.mp3"), new byte[]{1, 2, 3});
Files.write(album.resolve("01 - Song.lrc"), "[00:01]first line\n[00:02]second line".getBytes(StandardCharsets.UTF_8));
Files.write(album.resolve("01 - Song.lrc"), "[00:01]first line\n[00:02]second line\n[00:03]third line".getBytes(StandardCharsets.UTF_8));
Files.write(album.resolve("orphan.lrc"), "[00:01]orphan".getBytes(StandardCharsets.UTF_8));
Files.write(album.resolve("cover.jpg"), new byte[]{(byte) 0xFF, (byte) 0xD8, (byte) 0xFF});
return album;
@@ -244,7 +244,7 @@ class LibraryHealthServiceTest {
Files.createDirectories(album);
// 大写 .LRC 侧车:既不应算缺歌词,也不应算孤立(与 orphan 判定保持一致)
Files.write(album.resolve("01 - Song.mp3"), new byte[]{1, 2, 3});
Files.write(album.resolve("01 - Song.LRC"), "[00:01]first line\n[00:02]second line".getBytes(StandardCharsets.UTF_8));
Files.write(album.resolve("01 - Song.LRC"), "[00:01]first line\n[00:02]second line\n[00:03]third line".getBytes(StandardCharsets.UTF_8));
LibraryHealthService svc = newService(root);
LibraryHealthReport report = svc.scan(false);
@@ -22,8 +22,8 @@ class LyricsServiceTest {
@Test
void selectsExactArtistInsteadOfFirstCoverCandidate() throws Exception {
String json = "["
+ "{\"title\":\"夜曲 (网易云音乐)\",\"artist\":\"Xai小爱\",\"lyrics\":\"[00:01]翻唱第一句\\n[00:02]翻唱第二句\",\"type\":\"lrc\",\"source\":\"netease\"},"
+ "{\"title\":\"夜曲 (酷狗音乐)\",\"artist\":\"周杰伦\",\"lyrics\":\"[00:01]一群嗜血的蚂蚁\\n[00:02]被腐肉所吸引\",\"type\":\"lrc\",\"source\":\"kugou\",\"isComplete\":true}]";
+ "{\"title\":\"夜曲 (网易云音乐)\",\"artist\":\"Xai小爱\",\"lyrics\":\"[00:01]翻唱第一句\\n[00:02]翻唱第二句\\n[00:03]翻唱第三句\",\"type\":\"lrc\",\"source\":\"netease\"},"
+ "{\"title\":\"夜曲 (酷狗音乐)\",\"artist\":\"周杰伦\",\"lyrics\":\"[00:01]一群嗜血的蚂蚁\\n[00:02]被腐肉所吸引\\n[00:03]我面无表情\",\"type\":\"lrc\",\"source\":\"kugou\",\"isComplete\":true}]";
start(json, 200);
LyricsService.Candidate result = new LyricsService().lookup("夜曲", "周杰伦");
assertNotNull(result);
@@ -45,7 +45,7 @@ class LyricsServiceTest {
@Test
void acceptsTimestampedLyrics() {
assertTrue(LyricsService.hasMeaningfulLyrics("[00:01.00]第一句歌词\n[00:03.00]第二句歌词\n"));
assertTrue(LyricsService.hasMeaningfulLyrics("[00:01.00]第一句歌词\n[00:03.00]第二句歌词\n[00:05.00]第三句歌词\n"));
}
private void start(String body, int status) throws Exception {