@uimaxbai/am-lyrics 1.5.0 → 1.5.2
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 +78 -25
- package/dist/src/am-lyrics.js.map +1 -1
- package/dist/src/react.js +78 -25
- package/dist/src/react.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -1
- package/src/AmLyrics.ts +116 -29
package/dist/src/react.js
CHANGED
|
@@ -322,7 +322,7 @@ class GoogleService {
|
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
-
const VERSION = '1.5.
|
|
325
|
+
const VERSION = '1.5.2';
|
|
326
326
|
const INSTRUMENTAL_THRESHOLD_MS = 7000; // Show dots for gaps >= 7s
|
|
327
327
|
const FETCH_TIMEOUT_MS = 8000; // Timeout for all lyrics fetch requests
|
|
328
328
|
const SEEK_THRESHOLD_MS = 500;
|
|
@@ -600,20 +600,23 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
600
600
|
if (biniResult && biniResult.lines.length > 0) {
|
|
601
601
|
collectedSources.push(biniResult);
|
|
602
602
|
}
|
|
603
|
-
|
|
603
|
+
const hasWordSync = (sources) => sources.some(s => s.lines.some(l => l.isWordSynced || (l.text && l.text.length > 1)));
|
|
604
|
+
if (collectedSources.length === 0 || !hasWordSync(collectedSources)) {
|
|
604
605
|
const unisonResult = await AmLyrics.fetchLyricsFromUnison(resolvedMetadata.metadata);
|
|
605
606
|
if (unisonResult && unisonResult.lines.length > 0) {
|
|
606
607
|
collectedSources.push(unisonResult);
|
|
607
608
|
}
|
|
608
609
|
}
|
|
609
|
-
if (collectedSources.length === 0) {
|
|
610
|
+
if (collectedSources.length === 0 || !hasWordSync(collectedSources)) {
|
|
610
611
|
const youLyResults = await AmLyrics.fetchLyricsFromYouLyPlus(title, artist, resolvedMetadata.catalogIsrc, resolvedMetadata.metadata, true);
|
|
611
612
|
if (youLyResults && youLyResults.length > 0) {
|
|
612
613
|
collectedSources.push(...youLyResults);
|
|
613
614
|
}
|
|
614
615
|
}
|
|
615
616
|
}
|
|
616
|
-
|
|
617
|
+
const hasLineSync = (sources) => sources.some(s => s.lines.some(l => l.timestamp > 0 || l.endtime > 0));
|
|
618
|
+
if ((collectedSources.length === 0 || !hasLineSync(collectedSources)) &&
|
|
619
|
+
resolvedMetadata?.metadata) {
|
|
617
620
|
// Fallback: LRCLIB
|
|
618
621
|
const lrclibResult = await AmLyrics.fetchLyricsFromLrclib(resolvedMetadata.metadata);
|
|
619
622
|
if (lrclibResult && lrclibResult.lines.length > 0) {
|
|
@@ -764,6 +767,23 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
764
767
|
const resolvedMetadata = await this.resolveSongMetadata();
|
|
765
768
|
if (resolvedMetadata?.metadata) {
|
|
766
769
|
const newSources = [];
|
|
770
|
+
// Try Unison if not fetched
|
|
771
|
+
if (!this.availableSources.some(s => s.source.toLowerCase().includes('unison'))) {
|
|
772
|
+
const unisonResult = await AmLyrics.fetchLyricsFromUnison(resolvedMetadata.metadata);
|
|
773
|
+
if (unisonResult && unisonResult.lines.length > 0) {
|
|
774
|
+
newSources.push(unisonResult);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
// Try YouLyPlus (KPoe) if we don't have Apple or QQ
|
|
778
|
+
if (!this.availableSources.some(s => s.source.toLowerCase().includes('apple') ||
|
|
779
|
+
s.source.toLowerCase().includes('qq'))) {
|
|
780
|
+
const title = resolvedMetadata.metadata.title?.trim() || '';
|
|
781
|
+
const artist = resolvedMetadata.metadata.artist?.trim() || '';
|
|
782
|
+
const youLyResults = await AmLyrics.fetchLyricsFromYouLyPlus(title, artist, resolvedMetadata.catalogIsrc, resolvedMetadata.metadata, true);
|
|
783
|
+
if (youLyResults && youLyResults.length > 0) {
|
|
784
|
+
newSources.push(...youLyResults);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
767
787
|
// Try LRCLIB if not fetched
|
|
768
788
|
if (!this.availableSources.some(s => s.source.toLowerCase().includes('lrclib'))) {
|
|
769
789
|
const lrclibResult = await AmLyrics.fetchLyricsFromLrclib(resolvedMetadata.metadata);
|
|
@@ -2039,6 +2059,15 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2039
2059
|
const currentGap = this.findInstrumentalGapAt(newTime);
|
|
2040
2060
|
if (currentGap) {
|
|
2041
2061
|
this.lastInstrumentalIndex = currentGap.insertBeforeIndex;
|
|
2062
|
+
// Un-highlight the previous line immediately when gap dots are playing
|
|
2063
|
+
if (currentGap.insertBeforeIndex > 0) {
|
|
2064
|
+
const prevLine = this._getLineElement(currentGap.insertBeforeIndex - 1);
|
|
2065
|
+
if (prevLine &&
|
|
2066
|
+
prevLine.classList.contains('persist-highlight') &&
|
|
2067
|
+
!prevLine.classList.contains('active')) {
|
|
2068
|
+
AmLyrics.unfinishSyllables(prevLine);
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2042
2071
|
}
|
|
2043
2072
|
else if (this.lastInstrumentalIndex !== null) {
|
|
2044
2073
|
this.lastInstrumentalIndex = null;
|
|
@@ -2185,7 +2214,18 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2185
2214
|
}
|
|
2186
2215
|
// 1. Compute scroll lookahead based on gap to next line (YouLyPlus style)
|
|
2187
2216
|
let scrollLookAheadMs = 350;
|
|
2188
|
-
|
|
2217
|
+
let currentAudioIndex = -1;
|
|
2218
|
+
for (let i = 0; i < this.lyrics.length; i += 1) {
|
|
2219
|
+
if (this.lyrics[i].timestamp > this.currentTime) {
|
|
2220
|
+
currentAudioIndex = i - 1;
|
|
2221
|
+
break;
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
if (currentAudioIndex === -1 && this.lyrics.length > 0) {
|
|
2225
|
+
if (this.currentTime >= this.lyrics[this.lyrics.length - 1].timestamp) {
|
|
2226
|
+
currentAudioIndex = this.lyrics.length - 1;
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2189
2229
|
if (currentAudioIndex !== -1 &&
|
|
2190
2230
|
currentAudioIndex + 1 < this.lyrics.length) {
|
|
2191
2231
|
const currentLine = this.lyrics[currentAudioIndex];
|
|
@@ -2196,29 +2236,32 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2196
2236
|
// 2. Find scroll target at predictive time
|
|
2197
2237
|
const predictiveTime = this.currentTime + scrollLookAheadMs;
|
|
2198
2238
|
const predictiveActiveIndices = this.findActiveLineIndices(predictiveTime);
|
|
2199
|
-
let
|
|
2239
|
+
let targetElement = null;
|
|
2200
2240
|
if (predictiveActiveIndices.length > 0) {
|
|
2201
|
-
|
|
2241
|
+
const targetLineIdx = this.getPrimaryScrollLineIndex(predictiveActiveIndices, predictiveTime);
|
|
2242
|
+
if (targetLineIdx !== null && targetLineIdx !== -1) {
|
|
2243
|
+
targetElement = this._getLineElement(targetLineIdx);
|
|
2244
|
+
}
|
|
2202
2245
|
}
|
|
2203
|
-
|
|
2246
|
+
if (!targetElement) {
|
|
2204
2247
|
// Fallback: closest line before predictiveTime
|
|
2205
|
-
|
|
2248
|
+
const targetLineIdx = this.getLineIndexAtTime(predictiveTime, 0);
|
|
2249
|
+
if (targetLineIdx !== null && targetLineIdx !== -1) {
|
|
2250
|
+
targetElement = this._getLineElement(targetLineIdx);
|
|
2251
|
+
}
|
|
2206
2252
|
}
|
|
2207
|
-
if (
|
|
2208
|
-
return;
|
|
2209
|
-
const targetLine = this._getLineElement(targetLineIndex);
|
|
2210
|
-
if (!targetLine)
|
|
2253
|
+
if (!targetElement)
|
|
2211
2254
|
return;
|
|
2212
2255
|
// Unblur the upcoming target line early (pre-active) so background
|
|
2213
2256
|
// vocals start their max-height/opacity transition in sync with scroll.
|
|
2214
|
-
if (!
|
|
2215
|
-
|
|
2216
|
-
if (!this.preActiveLineElements.includes(
|
|
2217
|
-
this.preActiveLineElements.push(
|
|
2257
|
+
if (!targetElement.classList.contains('active')) {
|
|
2258
|
+
targetElement.classList.add('pre-active');
|
|
2259
|
+
if (!this.preActiveLineElements.includes(targetElement)) {
|
|
2260
|
+
this.preActiveLineElements.push(targetElement);
|
|
2218
2261
|
}
|
|
2219
2262
|
}
|
|
2220
2263
|
const scrollDuration = scrollLookAheadMs;
|
|
2221
|
-
this.focusLine(
|
|
2264
|
+
this.focusLine(targetElement, forceScroll, scrollDuration);
|
|
2222
2265
|
}
|
|
2223
2266
|
_getTextWidth(text, font) {
|
|
2224
2267
|
if (!this._textWidthCanvas) {
|
|
@@ -3523,7 +3566,17 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3523
3566
|
syllable.style.removeProperty('--pre-wipe-delay');
|
|
3524
3567
|
const chars = syllable.querySelectorAll('span.char');
|
|
3525
3568
|
for (let ci = 0; ci < chars.length; ci += 1) {
|
|
3526
|
-
chars[ci]
|
|
3569
|
+
const charEl = chars[ci];
|
|
3570
|
+
const currentAnim = charEl.style.animation || '';
|
|
3571
|
+
if (currentAnim.includes('grow-dynamic') ||
|
|
3572
|
+
currentAnim.includes('rise-char')) {
|
|
3573
|
+
const parts = currentAnim.split(',').map(p => p.trim());
|
|
3574
|
+
const transformAnim = parts.find(p => p.includes('grow-dynamic') || p.includes('rise-char'));
|
|
3575
|
+
charEl.style.animation = transformAnim || '';
|
|
3576
|
+
}
|
|
3577
|
+
else {
|
|
3578
|
+
charEl.style.animation = '';
|
|
3579
|
+
}
|
|
3527
3580
|
}
|
|
3528
3581
|
}
|
|
3529
3582
|
}
|
|
@@ -4872,21 +4925,21 @@ AmLyrics$1.styles = i$3 `
|
|
|
4872
4925
|
.lyrics-line.active:not(.lyrics-gap)
|
|
4873
4926
|
.lyrics-word:not(.growable)
|
|
4874
4927
|
.lyrics-syllable.highlight {
|
|
4875
|
-
transform:
|
|
4928
|
+
transform: translate3d(0, var(--char-rise-y, -1.12px), 0);
|
|
4876
4929
|
}
|
|
4877
4930
|
|
|
4878
4931
|
.lyrics-line.persist-highlight:not(.lyrics-gap)
|
|
4879
4932
|
.lyrics-word:not(.growable)
|
|
4880
4933
|
.lyrics-syllable.finished {
|
|
4881
|
-
transform:
|
|
4934
|
+
transform: translate3d(0, var(--char-rise-y, -1.12px), 0);
|
|
4882
4935
|
}
|
|
4883
4936
|
|
|
4884
4937
|
.lyrics-word.growable .lyrics-syllable.cleanup .char {
|
|
4885
|
-
transform:
|
|
4938
|
+
transform: translate3d(0, var(--char-rise-y, -1.12px), 0);
|
|
4886
4939
|
}
|
|
4887
4940
|
|
|
4888
4941
|
.lyrics-word.char-rise .lyrics-syllable.cleanup .char {
|
|
4889
|
-
transform:
|
|
4942
|
+
transform: translate3d(0, var(--char-rise-y, -1.12px), 0);
|
|
4890
4943
|
}
|
|
4891
4944
|
|
|
4892
4945
|
.lyrics-line.persist-highlight
|
|
@@ -4897,7 +4950,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4897
4950
|
.lyrics-word.char-rise
|
|
4898
4951
|
.lyrics-syllable.finished
|
|
4899
4952
|
.char {
|
|
4900
|
-
transform:
|
|
4953
|
+
transform: translate3d(0, var(--char-rise-y, -1.12px), 0);
|
|
4901
4954
|
}
|
|
4902
4955
|
|
|
4903
4956
|
/* Background vocal overrides — placed AFTER main rules so they win
|
|
@@ -4991,6 +5044,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4991
5044
|
background-clip: text;
|
|
4992
5045
|
-webkit-background-clip: text;
|
|
4993
5046
|
backface-visibility: hidden;
|
|
5047
|
+
transform-origin: 50% 80%;
|
|
4994
5048
|
transition:
|
|
4995
5049
|
color 0.7s,
|
|
4996
5050
|
background-color 0.7s,
|
|
@@ -5028,7 +5082,6 @@ AmLyrics$1.styles = i$3 `
|
|
|
5028
5082
|
background-position:
|
|
5029
5083
|
-0.5em 0%,
|
|
5030
5084
|
-0.25em 0%;
|
|
5031
|
-
transform-origin: 50% 80%;
|
|
5032
5085
|
transition:
|
|
5033
5086
|
transform 0.7s ease,
|
|
5034
5087
|
color 0.18s;
|