@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/react.js CHANGED
@@ -322,7 +322,7 @@ class GoogleService {
322
322
  }
323
323
  }
324
324
 
325
- const VERSION = '1.5.0';
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
- if (collectedSources.length === 0) {
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
- if (collectedSources.length === 0 && resolvedMetadata?.metadata) {
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
- const currentAudioIndex = this.getLineIndexAtTime(this.currentTime, this.lastActiveIndex);
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 targetLineIndex;
2239
+ let targetElement = null;
2200
2240
  if (predictiveActiveIndices.length > 0) {
2201
- targetLineIndex = this.getPrimaryScrollLineIndex(predictiveActiveIndices, predictiveTime);
2241
+ const targetLineIdx = this.getPrimaryScrollLineIndex(predictiveActiveIndices, predictiveTime);
2242
+ if (targetLineIdx !== null && targetLineIdx !== -1) {
2243
+ targetElement = this._getLineElement(targetLineIdx);
2244
+ }
2202
2245
  }
2203
- else {
2246
+ if (!targetElement) {
2204
2247
  // Fallback: closest line before predictiveTime
2205
- targetLineIndex = this.getLineIndexAtTime(predictiveTime, 0);
2248
+ const targetLineIdx = this.getLineIndexAtTime(predictiveTime, 0);
2249
+ if (targetLineIdx !== null && targetLineIdx !== -1) {
2250
+ targetElement = this._getLineElement(targetLineIdx);
2251
+ }
2206
2252
  }
2207
- if (targetLineIndex === null || targetLineIndex === -1)
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 (!targetLine.classList.contains('active')) {
2215
- targetLine.classList.add('pre-active');
2216
- if (!this.preActiveLineElements.includes(targetLine)) {
2217
- this.preActiveLineElements.push(targetLine);
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(targetLine, forceScroll, scrollDuration);
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].style.animation = '';
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: translateY(-3.5%);
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: translateY(-3.5%);
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: translateY(-3.5%);
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: translateY(-3.5%);
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: translateY(-3.5%);
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;