@uimaxbai/am-lyrics 1.0.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/AmLyrics.d.ts.map +1 -1
- package/dist/src/am-lyrics.js +96 -27
- package/dist/src/am-lyrics.js.map +1 -1
- package/dist/src/react.js +96 -27
- package/dist/src/react.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/AmLyrics.ts +100 -20
- package/src/GoogleService.ts +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmLyrics.d.ts","sourceRoot":"","sources":["../../src/AmLyrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAE,MAAM,KAAK,CAAC;AA2F5C,qBAAa,QAAS,SAAQ,UAAU;IACtC,MAAM,CAAC,MAAM,0BA+mCX;IAGF,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,OAAO,CAAC,cAAc,CAAmC;IAGzD,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,cAAc,SAAa;IAG3B,oBAAoB,SAA+B;IAGnD,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,UAAU,UAAQ;IAGlB,WAAW,UAAQ;IAGnB,OAAO,CAAC,gBAAgB,CAAS;IAGjC,OAAO,CAAC,eAAe,CAAS;YAElB,kBAAkB;YAKlB,iBAAiB;YAsBjB,iBAAiB;YAKjB,gBAAgB;IAyC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,YAAY,CAAK;IAEzB,IACI,WAAW,CAAC,KAAK,EAAE,MAAM,EAM5B;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAGD,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,MAAM,CAAC,CAAe;IAE9B,OAAO,CAAC,iBAAiB,CAAgB;IAEzC,OAAO,CAAC,qBAAqB,CAAkC;IAE/D,OAAO,CAAC,2BAA2B,CAAkC;IAErE,OAAO,CAAC,gBAAgB,CAAkC;IAE1D,OAAO,CAAC,sBAAsB,CAAkC;IAGhE,OAAO,CAAC,YAAY,CAAuB;IAE3C,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAElC,OAAO,CAAC,kBAAkB,CAGZ;IAEd,OAAO,CAAC,wBAAwB,CAGlB;IAGd,OAAO,CAAC,eAAe,CAAC,CAAc;IAEtC,OAAO,CAAC,qBAAqB,CAAuB;IAEpD,OAAO,CAAC,mBAAmB,CAAC,CAAS;IAGrC,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,oBAAoB,CAAS;IAErC,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,gBAAgB,CAAC,CAAgC;IAGzD,OAAO,CAAC,iBAAiB,CAAqB;IAG9C,OAAO,CAAC,aAAa,CAA0B;IAE/C,OAAO,CAAC,wBAAwB,CAA4B;IAE5D,OAAO,CAAC,qBAAqB,CAA4B;IAGzD,OAAO,CAAC,oBAAoB,CAGZ;IAEhB,OAAO,CAAC,mBAAmB,CAAK;IAEhC,OAAO,CAAC,cAAc,CAAqB;IAE3C,OAAO,CAAC,mBAAmB,CAAC,CAAgC;IAE5D,OAAO,CAAC,sBAAsB,CAAC,CAAgC;IAG/D,OAAO,CAAC,eAAe,CAAK;IAE5B,OAAO,CAAC,cAAc,CAA0B;IAEhD,iBAAiB;IAKjB,oBAAoB;YAUN,WAAW;
|
|
1
|
+
{"version":3,"file":"AmLyrics.d.ts","sourceRoot":"","sources":["../../src/AmLyrics.ts"],"names":[],"mappings":"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"}
|
package/dist/src/am-lyrics.js
CHANGED
|
@@ -228,19 +228,18 @@ class GoogleService {
|
|
|
228
228
|
line.romanizedText // Skip if already romanized
|
|
229
229
|
)
|
|
230
230
|
return line;
|
|
231
|
-
//
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
const
|
|
231
|
+
// Get the entire line text to romanize together for context-aware pronunciation
|
|
232
|
+
const fullText = line.text.map((s) => s.text).join('');
|
|
233
|
+
// romanizeTexts expects an array of strings, so we pass an array of one
|
|
234
|
+
const [romanizedFullLine] = await this.romanizeTexts([fullText]);
|
|
235
|
+
const newSyllabus = line.text.map((s) => ({
|
|
235
236
|
...s,
|
|
236
|
-
romanizedText:
|
|
237
|
-
? `${romanizedTexts[index]}`
|
|
238
|
-
: s.text,
|
|
237
|
+
romanizedText: s.romanizedText, // Keep any existing syllabus romanization if provided by API natively
|
|
239
238
|
}));
|
|
240
239
|
return {
|
|
241
240
|
...line,
|
|
242
241
|
text: newSyllabus,
|
|
243
|
-
romanizedText:
|
|
242
|
+
romanizedText: romanizedFullLine || '',
|
|
244
243
|
};
|
|
245
244
|
}));
|
|
246
245
|
}
|
|
@@ -310,14 +309,14 @@ class GoogleService {
|
|
|
310
309
|
}
|
|
311
310
|
}
|
|
312
311
|
|
|
313
|
-
const VERSION = '1.0
|
|
312
|
+
const VERSION = '1.1.0';
|
|
314
313
|
const INSTRUMENTAL_THRESHOLD_MS = 7000; // Show dots for gaps >= 7s
|
|
315
314
|
const KPOE_SERVERS = [
|
|
316
315
|
'https://lyricsplus.binimum.org',
|
|
316
|
+
'https://lyricsplus.atomix.one',
|
|
317
|
+
'https://lyricsplus-seven.vercel.app',
|
|
317
318
|
'https://lyricsplus.prjktla.workers.dev',
|
|
318
319
|
'https://lyrics-plus-backend.vercel.app',
|
|
319
|
-
'https://lyricsplus.onrender.com',
|
|
320
|
-
'https://lyricsplus.prjktla.online',
|
|
321
320
|
];
|
|
322
321
|
const DEFAULT_KPOE_SOURCE_ORDER = 'apple,lyricsplus,musixmatch,spotify,musixmatch-word';
|
|
323
322
|
const TIDAL_SERVERS = [
|
|
@@ -471,7 +470,9 @@ class AmLyrics extends i {
|
|
|
471
470
|
!this.songArtist &&
|
|
472
471
|
!this.query;
|
|
473
472
|
if (resolvedMetadata?.metadata && !isMusicIdOnlyRequest) {
|
|
474
|
-
const
|
|
473
|
+
const title = resolvedMetadata.metadata.title?.trim() || '';
|
|
474
|
+
const artist = resolvedMetadata.metadata.artist?.trim() || '';
|
|
475
|
+
const youLyResult = await AmLyrics.fetchLyricsFromYouLyPlus(title, artist, resolvedMetadata.metadata);
|
|
475
476
|
if (youLyResult && youLyResult.lines.length > 0) {
|
|
476
477
|
this.lyrics = youLyResult.lines;
|
|
477
478
|
this.lyricsSource = youLyResult.source ?? 'LyricsPlus (KPoe)';
|
|
@@ -672,12 +673,9 @@ class AmLyrics extends i {
|
|
|
672
673
|
}
|
|
673
674
|
return null;
|
|
674
675
|
}
|
|
675
|
-
static async fetchLyricsFromYouLyPlus(metadata) {
|
|
676
|
-
|
|
677
|
-
const artist = metadata.artist?.trim();
|
|
678
|
-
if (!title || !artist) {
|
|
676
|
+
static async fetchLyricsFromYouLyPlus(title, artist, metadata = {}) {
|
|
677
|
+
if (!title || !artist)
|
|
679
678
|
return null;
|
|
680
|
-
}
|
|
681
679
|
const params = new URLSearchParams({ title, artist });
|
|
682
680
|
if (metadata.album) {
|
|
683
681
|
params.append('album', metadata.album);
|
|
@@ -686,8 +684,32 @@ class AmLyrics extends i {
|
|
|
686
684
|
params.append('duration', Math.round(metadata.durationMs / 1000).toString());
|
|
687
685
|
}
|
|
688
686
|
params.append('source', DEFAULT_KPOE_SOURCE_ORDER);
|
|
689
|
-
|
|
690
|
-
|
|
687
|
+
const getRank = (sourceLabel, parsedLines) => {
|
|
688
|
+
const lower = sourceLabel.toLowerCase();
|
|
689
|
+
const hasWordSync = parsedLines.some((line) => line.text && Array.isArray(line.text) && line.text.length > 1);
|
|
690
|
+
const isQQ = lower.includes('qq') || lower.includes('lyricsplus');
|
|
691
|
+
if (lower.includes('apple') && hasWordSync)
|
|
692
|
+
return 1;
|
|
693
|
+
if (isQQ && hasWordSync)
|
|
694
|
+
return 2;
|
|
695
|
+
if (lower.includes('musixmatch') && hasWordSync)
|
|
696
|
+
return 3;
|
|
697
|
+
if (lower.includes('apple') && !hasWordSync)
|
|
698
|
+
return 4;
|
|
699
|
+
if (isQQ && !hasWordSync)
|
|
700
|
+
return 5;
|
|
701
|
+
if (lower.includes('musixmatch') && !hasWordSync)
|
|
702
|
+
return 6;
|
|
703
|
+
return 10;
|
|
704
|
+
};
|
|
705
|
+
let bestFallbackResult = null;
|
|
706
|
+
let bestFallbackRank = 100;
|
|
707
|
+
// Shuffle servers so we pick a random one first, with all others as fallback
|
|
708
|
+
// Limit to 2 servers to prevent unnecessary API spam when Apple lyrics are missing
|
|
709
|
+
const shuffledServers = [...KPOE_SERVERS]
|
|
710
|
+
.sort(() => Math.random() - 0.5)
|
|
711
|
+
.slice(0, 2);
|
|
712
|
+
for (const base of shuffledServers) {
|
|
691
713
|
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;
|
|
692
714
|
const url = `${normalizedBase}/v2/lyrics/get?${params.toString()}`;
|
|
693
715
|
let payload = null;
|
|
@@ -708,19 +730,50 @@ class AmLyrics extends i {
|
|
|
708
730
|
const sourceLabel = payload?.metadata?.source ||
|
|
709
731
|
payload?.metadata?.provider ||
|
|
710
732
|
'LyricsPlus (KPoe)';
|
|
733
|
+
const rank = getRank(sourceLabel, lines);
|
|
711
734
|
const result = { lines, source: sourceLabel };
|
|
712
735
|
// If source is Apple, return immediately (best quality)
|
|
713
|
-
if (
|
|
736
|
+
if (rank === 1) {
|
|
714
737
|
return result;
|
|
715
738
|
}
|
|
716
739
|
// Otherwise, store as fallback if we don't have one yet
|
|
717
|
-
if (
|
|
718
|
-
|
|
740
|
+
if (rank < bestFallbackRank) {
|
|
741
|
+
bestFallbackResult = result;
|
|
742
|
+
bestFallbackRank = rank;
|
|
743
|
+
}
|
|
744
|
+
// Proxies are identical mirrors; if we got a valid response (even a fallback),
|
|
745
|
+
// there's no reason to query the next proxy because it will return the exact same fallback.
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
// If we finished the 2-server check and STILL don't have Apple (1) or QQ (2),
|
|
751
|
+
// force an explicit query against lyricsplus.binimum.org looking for QQ
|
|
752
|
+
if (bestFallbackRank > 2) {
|
|
753
|
+
try {
|
|
754
|
+
const qqParams = new URLSearchParams(params);
|
|
755
|
+
qqParams.set('source', 'qq');
|
|
756
|
+
const url = `https://lyricsplus.binimum.org/v2/lyrics/get?${qqParams.toString()}`;
|
|
757
|
+
const response = await fetch(url);
|
|
758
|
+
if (response.ok) {
|
|
759
|
+
const payload = await response.json();
|
|
760
|
+
if (payload) {
|
|
761
|
+
const lines = AmLyrics.convertKPoeLyrics(payload);
|
|
762
|
+
const sourceLabel = payload?.metadata?.source ||
|
|
763
|
+
payload?.metadata?.provider ||
|
|
764
|
+
'LyricsPlus (KPoe)';
|
|
765
|
+
const rank = getRank(sourceLabel, lines || []);
|
|
766
|
+
if (lines && lines.length > 0 && rank < bestFallbackRank) {
|
|
767
|
+
return { lines, source: sourceLabel };
|
|
768
|
+
}
|
|
719
769
|
}
|
|
720
770
|
}
|
|
721
771
|
}
|
|
772
|
+
catch (error) {
|
|
773
|
+
// Explicit QQ fallback failed, ignore and proceed to return whatever we had
|
|
774
|
+
}
|
|
722
775
|
}
|
|
723
|
-
return
|
|
776
|
+
return bestFallbackResult;
|
|
724
777
|
}
|
|
725
778
|
/**
|
|
726
779
|
* Parse LRC subtitle format into LyricsLine[].
|
|
@@ -947,16 +1000,17 @@ class AmLyrics extends i {
|
|
|
947
1000
|
personIndexMap.set(agentKey, personIndex);
|
|
948
1001
|
});
|
|
949
1002
|
agentEntries.forEach(([agentKey, agentData]) => {
|
|
1003
|
+
const mappedKey = agentData.alias || agentKey;
|
|
950
1004
|
if (agentData.type === 'group') {
|
|
951
|
-
singerAlignmentMap[
|
|
1005
|
+
singerAlignmentMap[mappedKey] = 'start';
|
|
952
1006
|
}
|
|
953
1007
|
else if (agentData.type === 'other') {
|
|
954
|
-
singerAlignmentMap[
|
|
1008
|
+
singerAlignmentMap[mappedKey] = 'end';
|
|
955
1009
|
}
|
|
956
1010
|
else if (agentData.type === 'person') {
|
|
957
1011
|
const personIndex = personIndexMap.get(agentKey);
|
|
958
1012
|
if (personIndex !== undefined) {
|
|
959
|
-
singerAlignmentMap[
|
|
1013
|
+
singerAlignmentMap[mappedKey] =
|
|
960
1014
|
personIndex % 2 === 0 ? 'start' : 'end';
|
|
961
1015
|
}
|
|
962
1016
|
}
|
|
@@ -1406,7 +1460,22 @@ class AmLyrics extends i {
|
|
|
1406
1460
|
return [];
|
|
1407
1461
|
const activeLines = [];
|
|
1408
1462
|
for (let i = 0; i < this.lyrics.length; i += 1) {
|
|
1409
|
-
|
|
1463
|
+
const line = this.lyrics[i];
|
|
1464
|
+
let effectiveEndTime = line.endtime;
|
|
1465
|
+
// Extend the "active" highlight window to abut the next line,
|
|
1466
|
+
// leaving a 500ms gap for breathing/scrolling
|
|
1467
|
+
if (i < this.lyrics.length - 1) {
|
|
1468
|
+
const nextLineStart = this.lyrics[i + 1].timestamp;
|
|
1469
|
+
const gapDuration = nextLineStart - line.endtime;
|
|
1470
|
+
// If the gap is large enough to trigger the breathing dots,
|
|
1471
|
+
// DO NOT extend the highlight. The text should dim when the dots appear.
|
|
1472
|
+
if (gapDuration < INSTRUMENTAL_THRESHOLD_MS) {
|
|
1473
|
+
if (effectiveEndTime < nextLineStart) {
|
|
1474
|
+
effectiveEndTime = Math.max(effectiveEndTime, nextLineStart - 500);
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
if (time >= line.timestamp && time <= effectiveEndTime) {
|
|
1410
1479
|
activeLines.push(i);
|
|
1411
1480
|
}
|
|
1412
1481
|
}
|