### Install Dependencies with Yarn or Bun Source: https://github.com/binimum/am-lyrics/blob/main/README.md Installs project dependencies using either Yarn or Bun. These are recommended over npm for faster installation. ```bash yarn install ``` ```bash bun i ``` -------------------------------- ### Install @lit-labs/nextjs Source: https://github.com/binimum/am-lyrics/blob/main/next.md Install the necessary package for Next.js SSR support with Lit components. ```bash npm i @lit-labs/nextjs ``` -------------------------------- ### Start Local Development Server Source: https://github.com/binimum/am-lyrics/blob/main/README.md Starts the local development server using npm. This command is typically used for running the demo or development environment. ```bash npm start ``` -------------------------------- ### Install AM Lyrics Web Component Source: https://github.com/binimum/am-lyrics/blob/main/README.md Install the AM Lyrics web component using npm. This is recommended for React users or those not using a CDN. ```bash npm install @uimaxbai/am-lyrics ``` -------------------------------- ### Install Am Lyrics via npm Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Install the Am Lyrics package using npm for project integration. ```bash npm install @uimaxbai/am-lyrics ``` -------------------------------- ### Install Am Lyrics for React Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Install Am Lyrics along with React and Lit's React adapter for use in React applications. ```bash npm install @uimaxbai/am-lyrics react @lit/react ``` -------------------------------- ### Install React Integration for Am-Lyrics Source: https://github.com/binimum/am-lyrics/blob/main/README.md Install the necessary React packages before using the Am-Lyrics component within a React application. This step is crucial to avoid errors. ```bash npm install react @lit/react # Very important or errors will arise ``` -------------------------------- ### Example Usage of fetchLyricsFromUnison Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/lyrics-providers.md An example demonstrating how to call the fetchLyricsFromUnison method with song metadata. Ensure the SongMetadata object is correctly populated. ```typescript const result = await AmLyrics.fetchLyricsFromUnison({ title: "爱你", artist: "王心凌", durationMs: 225000 }); ``` -------------------------------- ### React Integration Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Integrate AM Lyrics into your React application. This example shows how to pass props and handle line clicks. ```jsx import { AmLyrics } from '@uimaxbai/am-lyrics/react'; audio.currentTime = e.detail.timestamp / 1000} /> ``` -------------------------------- ### YouLyPlus Response Format Example Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/lyrics-providers.md An example of the JSON response format from the YouLyPlus provider, detailing metadata and lyrics structure, including syllabus, transliteration, and translation. ```json { "metadata": { "source": "apple", "provider": "LyricsPlus", "agents": { "v1": { "type": "person", "alias": "Singer1" } } }, "lyrics": [ { "time": 0, "duration": 1000, "text": "Line text", "syllabus": [ { "time": 0, "duration": 500, "text": "Word", "part": true } ], "transliteration": { "text": "Romanized", "syllabus": [] }, "translation": { "text": "Translation" }, "element": { "singer": "v1", "songPart": "Verse 1" } } ] } ``` -------------------------------- ### Fetch Lyrics from YouLyPlus Example Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/lyrics-providers.md Example of how to call the fetchLyricsFromYouLyPlus function with song title, artist, and ISRC. The results are returned ranked by preference. ```typescript const results = await AmLyrics.fetchLyricsFromYouLyPlus( "Blinding Lights", "The Weeknd", "USRC17607839" ); // Returns array of results ranked by preference ``` -------------------------------- ### am-lyrics Web Component Usage Source: https://github.com/binimum/am-lyrics/blob/main/README.md Demonstrates how to install and use the am-lyrics web component in an HTML document, including importing the script and configuring its attributes. ```APIDOC ## Installation ```bash npm install @uimaxbai/am-lyrics ``` ## Usage ```html ``` ``` -------------------------------- ### Install am-lyrics React Package Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md Install the am-lyrics package along with React and @lit/react. Ensure you have React version 17.0.0 or higher and @lit/react version 1.0.0 or higher. ```bash npm install @uimaxbai/am-lyrics react @lit/react # or yarn add @uimaxbai/am-lyrics react @lit/react ``` -------------------------------- ### Complete AmLyrics React Player Example Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md A full React component demonstrating how to integrate AmLyrics with an audio player. It includes state management for playback, time synchronization, and error handling. ```tsx 'use client'; // Required for Next.js App Router import React, { useState, useRef, useEffect, useCallback } from 'react'; import { AmLyrics } from '@uimaxbai/am-lyrics/react'; interface SongData { title: string; artist: string; album?: string; duration: number; src: string; } interface LyricsPlayerProps { song: SongData; } export default function LyricsPlayer({ song }: LyricsPlayerProps) { const [currentTime, setCurrentTime] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const [error, setError] = useState(null); const audioRef = useRef(null); // Sync audio time with lyrics component useEffect(() => { const audio = audioRef.current; if (!audio) return; let animationFrameId: number; const updateCurrentTime = () => { setCurrentTime(audio.currentTime * 1000); animationFrameId = requestAnimationFrame(updateCurrentTime); }; const handlePlay = () => { setIsPlaying(true); animationFrameId = requestAnimationFrame(updateCurrentTime); }; const handlePause = () => { setIsPlaying(false); cancelAnimationFrame(animationFrameId); }; const handleError = () => { setError('Failed to load audio'); }; audio.addEventListener('play', handlePlay); audio.addEventListener('pause', handlePause); audio.addEventListener('error', handleError); return () => { cancelAnimationFrame(animationFrameId); audio.removeEventListener('play', handlePlay); audio.removeEventListener('pause', handlePause); audio.removeEventListener('error', handleError); }; }, []); // Handle line click to seek const handleLineClick = useCallback((event: CustomEvent<{ timestamp: number }>) => { const { timestamp } = event.detail; if (audioRef.current) { audioRef.current.currentTime = timestamp / 1000; audioRef.current.play(); } }, []); return (
{error && (
{error}
)}
); } ``` -------------------------------- ### Standalone Translation and Romanization Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/google-service.md Provides examples for standalone usage of the Google Service module, demonstrating how to translate song titles and artists, and romanize CJK names. ```typescript // Translate song title and artist const [translatedTitle, translatedArtist] = await GoogleService.translate( ['花火', '高木正博'], 'en' ); // Romanize artist name (CJK to Latin) const [romanizedName] = await GoogleService.romanizeTexts(['藤原道山']); ``` -------------------------------- ### Next.js App Router Setup Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Set up the AmLyrics component in a Next.js App Router (v13+) application. Ensure 'use client' directive is included at the top of the file. ```tsx 'use client'; // Required! import { AmLyrics } from '@uimaxbai/am-lyrics/react'; export default function Page() { return ; } ``` -------------------------------- ### Initialize and Control am-lyrics Component Source: https://github.com/binimum/am-lyrics/blob/main/demo/index.html Sets up event listeners for user interactions and manages the playback state of the am-lyrics component. It handles loading metadata, starting playback, and resetting the component. ```javascript import '../dist/src/am-lyrics.js'; let animationFrameId; let songStartTime = 0; let systemStartTime = 0; function stopAnimation() { if (animationFrameId) { cancelAnimationFrame(animationFrameId); animationFrameId = null; } } function animate() { const amLyrics = document.querySelector('am-lyrics'); if (!amLyrics) return; const elapsedTime = Date.now() - systemStartTime; amLyrics.currentTime = songStartTime + elapsedTime; // Convert to milliseconds animationFrameId = requestAnimationFrame(animate); } function startPlayback() { stopAnimation(); songStartTime = 0; systemStartTime = Date.now(); animate(); } function handleLineClick(e) { stopAnimation(); songStartTime = e.detail.timestamp; systemStartTime = Date.now(); animate(); } function handleLoadMetadata() { const titleInput = document.querySelector('#title-input'); const artistInput = document.querySelector('#artist-input'); const durationInput = document.querySelector('#duration-input'); const queryInput = document.querySelector('#query-input'); const amLyrics = document.querySelector('am-lyrics'); if (!amLyrics) return; const title = titleInput?.value.trim() ?? ''; const artist = artistInput?.value.trim() ?? ''; const queryText = queryInput?.value.trim() ?? ''; const durationText = durationInput?.value.trim() ?? ''; const durationMs = durationText ? Number(durationText) : NaN; if (titleInput) { amLyrics.songTitle = title; } if (artistInput) { amLyrics.songArtist = artist; } if (!Number.isNaN(durationMs) && durationMs > 0) { amLyrics.songDurationMs = durationMs; } else if (durationText === '') { amLyrics.songDurationMs = undefined; } amLyrics.songAlbum = ''; const fallbackQuery = queryText || [title, artist].filter(Boolean).join(' '); if (fallbackQuery) { amLyrics.query = fallbackQuery; } else { amLyrics.query = ''; } amLyrics.isrc = ''; amLyrics.musicId = ''; } function resetPlayback() { stopAnimation(); const amLyrics = document.querySelector('am-lyrics'); if (amLyrics) { // Set duration to -1 to trigger reset amLyrics.duration = -1; } songStartTime = 0; } document.addEventListener('DOMContentLoaded', () => { const amLyrics = document.querySelector('am-lyrics'); const loadButton = document.querySelector('#load-button'); const startButton = document.querySelector('#start-button'); const resetButton = document.querySelector('#reset-button'); const titleInput = document.querySelector('#title-input'); const artistInput = document.querySelector('#artist-input'); const queryInput = document.querySelector('#query-input'); const durationInput = document.querySelector('#duration-input'); if (amLyrics) { amLyrics.addEventListener('line-click', handleLineClick); } if (titleInput && amLyrics?.songTitle) { titleInput.value = amLyrics.songTitle; } if (artistInput && amLyrics?.songArtist) { artistInput.value = amLyrics.songArtist; } if (queryInput && amLyrics?.query) { queryInput.value = amLyrics.query; } if (durationInput && typeof amLyrics?.songDurationMs === 'number') { durationInput.value = String(amLyrics.songDurationMs); } if (loadButton) { loadButton.addEventListener('click', handleLoadMetadata); } if (startButton) { startButton.addEventListener('click', startPlayback); } if (resetButton) { resetButton.addEventListener('click', resetPlayback); } }); ``` -------------------------------- ### Install Am Lyrics via CDN Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Include Am Lyrics in your HTML using a CDN script tag. This also shows basic usage with song title and artist attributes. ```html ``` -------------------------------- ### AmLyrics Layout Examples Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md Demonstrates common layout patterns for the AmLyrics component within different container types like full viewport, fixed height, and flex layouts. ```tsx // Full viewport
``` ```tsx // Fixed height
``` ```tsx // Flex layout
Header
Player controls
``` -------------------------------- ### TypeScript: Start Animation from Time Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/animation-system.md Initiates animations for syllables based on a given time. It finds active syllables, computes their elapsed time, and applies necessary animation classes and metadata. ```typescript for (const lineIndex of activeLineIndices) { const line = this.lyrics[lineIndex]; for (const syllable of line.text) { const elapsed = newTime - syllable.timestamp; if (elapsed > 0 && elapsed < syllable.endtime - syllable.timestamp) { // Create animation const duration = syllable.endtime - syllable.timestamp; mainWordAnimations.set(syllableIndex, { startTime: syllable.timestamp, duration }); // Apply classes syllableEl.classList.add('highlight'); } } } ``` -------------------------------- ### Handle 'line-click' Event Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Listen for the 'line-click' event to get the timestamp of the clicked lyric line. Use this to synchronize audio playback. ```javascript amLyrics.addEventListener('line-click', (event) => { const { timestamp } = event.detail; // milliseconds audio.currentTime = timestamp / 1000; }); ``` -------------------------------- ### Use Am-Lyrics Component in React Source: https://github.com/binimum/am-lyrics/blob/main/README.md Import and use the AmLyrics component from '@uimaxbai/am-lyrics/react'. Ensure 'use client' is declared at the top of the file for Next.js. This example demonstrates syncing an audio player's time with the lyrics component and handling line clicks to seek the audio. ```jsx 'use client'; // VERY IMPORTANT!!! import React, { useState, useCallback, useRef, useEffect } from 'react'; import { AmLyrics } from '@uimaxbai/am-lyrics/react'; export default function App() { const [currentTime, setCurrentTime] = useState(0); const audioRef = useRef(null); // Sync audio player time with the component useEffect(() => { const audio = audioRef.current; if (!audio) return; let animationFrameId: number; const updateCurrentTime = () => { setCurrentTime(audio.currentTime * 1000); animationFrameId = requestAnimationFrame(updateCurrentTime); // Use requestAnimationFrame to prevent choppy scrolling }; const handlePlay = () => { animationFrameId = requestAnimationFrame(updateCurrentTime); }; const handlePause = () => { cancelAnimationFrame(animationFrameId); }; const handleTimeUpdate = () => { setCurrentTime(audio.currentTime * 1000); // Convert to milliseconds }; audio.addEventListener('play', handlePlay); audio.addEventListener('pause', handlePause); audio.addEventListener('timeupdate', handleTimeUpdate); return () => { cancelAnimationFrame(animationFrameId); audio.removeEventListener('play', handlePlay); audio.removeEventListener('pause', handlePause); audio.removeEventListener('timeupdate', handleTimeUpdate); }; }, []); // Handle line clicks to seek the audio const handleLineClick = useCallback((event: Event) => { const customEvent = event as CustomEvent<{ timestamp: number }>; const audio = audioRef.current; if (audio) { audio.currentTime = customEvent.detail.timestamp / 1000; // Convert to seconds audio.play(); } }, []); return (
); } ``` -------------------------------- ### Next.js Pages Router Setup Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Set up the AmLyrics component in a Next.js Pages Router application using dynamic import for server-side rendering (SSR) disabled. ```typescript import dynamic from 'next/dynamic'; const AmLyrics = dynamic( () => import('@uimaxbai/am-lyrics/react').then(m => ({ default: m.AmLyrics })), { ssr: false } ); ``` -------------------------------- ### Parsing Search Queries for AmLyrics Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md This example demonstrates how to handle user input for searching lyrics. The AmLyrics component automatically parses queries in the 'Title - Artist' format. ```tsx import { useState } from 'react'; import { AmLyrics } from '@uimaxbai/am-lyrics/react'; export function SearchLyrics() { const [query, setQuery] = useState(''); const handleSearch = (e: React.FormEvent) => { e.preventDefault(); // Component automatically parses "Title - Artist" format }; return ( <>
setQuery(e.target.value)} placeholder="Song Title - Artist" />
); } ``` -------------------------------- ### Syllable Animation Progress Calculation Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/animation-system.md Calculates the progress percentage for syllable highlighting based on the current time, syllable start time, and duration. This is essential for driving the 'wipe' animation. ```typescript const syllableDurationMs = syllable.endtime - syllable.timestamp; const elapsedMs = currentTime - syllable.timestamp; const progressPercent = (elapsedMs / syllableDurationMs) * 100; ``` -------------------------------- ### Basic am-lyrics React Component Usage Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md Integrate the AmLyrics component into your React application. This example shows how to manage audio playback time and pass it to the component for synchronized lyrics display. ```tsx import React, { useState, useRef, useEffect } from 'react'; import { AmLyrics } from '@uimaxbai/am-lyrics/react'; export default function LyricsPlayer() { const [currentTime, setCurrentTime] = useState(0); const audioRef = useRef(null); useEffect(() => { const audio = audioRef.current; if (!audio) return; const handleTimeUpdate = () => { setCurrentTime(audio.currentTime * 1000); // Convert to milliseconds }; audio.addEventListener('timeupdate', handleTimeUpdate); return () => audio.removeEventListener('timeupdate', handleTimeUpdate); }, []); return (
); } ``` -------------------------------- ### Unison API Endpoint Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/lyrics-providers.md The GET endpoint for the Unison lyrics API. Parameters include song title, artist, album, and duration. ```http GET https://unison.boidu.dev/lyrics?song={title}&artist={artist}&album={album}&duration={durationSeconds} ``` -------------------------------- ### Format Project Files Source: https://github.com/binimum/am-lyrics/blob/main/README.md Automatically fixes linting and formatting errors in the project. Run this command to ensure code style compliance. ```bash npm run format ``` -------------------------------- ### User Interaction Data Flow Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Explains how user interactions, specifically clicking a line, trigger events and subsequent playback synchronization. ```text User clicks line ↓ Dispatch CustomEvent 'line-click' with timestamp ↓ Consumer code seeks audio to timestamp ↓ currentTime updates ↓ (see Playback Synchronization) ``` -------------------------------- ### Import GoogleService Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/google-service.md Import the GoogleService class from the library. ```typescript import { GoogleService } from '@uimaxbai/am-lyrics'; ``` -------------------------------- ### Configure next.config.js Source: https://github.com/binimum/am-lyrics/blob/main/next.md Update your Next.js configuration file to enable Lit SSR support. This involves wrapping your existing config with the `withLitSSR` function. ```javascript // next.config.js const withLitSSR = require('@lit-labs/nextjs')(); /** @type {import('next').NextConfig} */ const nextConfig = { // Add your own config here reactStrictMode: true, }; module.exports = withLitSSR(nextConfig); ``` -------------------------------- ### Define API Endpoints and Defaults Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/types.md Lists the available KPOE (Knowledgebase of Popular Entertainment) server URLs, the default source order for fetching lyrics, and the URL for the Genius worker. These are crucial for API interactions. ```typescript const KPOE_SERVERS = [ 'https://lyricsplus.binimum.org', 'https://lyricsplus-seven.vercel.app', 'https://lyricsplus.prjktla.workers.dev', 'https://lyrics-plus-backend.vercel.app', ]; const DEFAULT_KPOE_SOURCE_ORDER = 'apple,lyricsplus,musixmatch,spotify,qq,deezer,musixmatch-word'; const GENIUS_WORKER_URL = 'https://fetch-genius.samidy.workers.dev/'; ``` -------------------------------- ### React Component Usage Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md How to integrate the am-lyrics React component into your application, passing props for song details and playback time. ```APIDOC ## React Component ```tsx import { AmLyrics } from '@uimaxbai/am-lyrics/react'; ``` ``` -------------------------------- ### Handle Line Click for Seeking Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Listen for the 'line-click' event to update the audio playback position. The event detail provides the timestamp in milliseconds. ```javascript amLyrics.addEventListener('line-click', e => { audio.currentTime = e.detail.timestamp / 1000; }); ``` -------------------------------- ### Lint Project Files Source: https://github.com/binimum/am-lyrics/blob/main/README.md Scans the project for linting and formatting errors. This command helps maintain code quality and consistency. ```bash npm run lint ``` -------------------------------- ### Lyrics Fetching Data Flow Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Illustrates the process of fetching lyrics, from property changes to rendering. It shows the various sources Am-Lyrics attempts to retrieve lyrics from. ```text Property Change (query/musicId/songTitle/etc) ↓ fetchLyrics() ├→ Resolve metadata (parseQuery, searchLyricsCatalog) ├→ Try BiniLyrics (TTML) ├→ Try Unison (LRC/TTML) ├→ Try YouLyPlus (KPoe JSON) ├→ Try LRCLIB (LRC) ├→ Try Genius (plain text) ↓ onLyricsLoaded() ├→ Reset animation state ├→ Apply romanization (if enabled) ├→ Apply translation (if enabled) ↓ Template renders lyrics with LyricsLine data ``` -------------------------------- ### Import AM Lyrics Web Component via CDN Source: https://github.com/binimum/am-lyrics/blob/main/README.md Import the AM Lyrics web component using a CDN link. This is a convenient way to include the component in your project. ```html ``` -------------------------------- ### Web Component Usage Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md How to use the am-lyrics web component by setting its attributes for song title, artist, and current time. ```APIDOC ## Web Component Tag ```html ``` ``` -------------------------------- ### Static Methods Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Utilize static methods provided by the AmLyrics class for parsing different lyrical formats. ```APIDOC ## Static Methods ```typescript AmLyrics.parseTTML(ttmlString) AmLyrics.convertKPoeLyrics(payload) AmLyrics.parseQueryMetadata(query) ``` ``` -------------------------------- ### Exported Classes and Components Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Shows the main AmLyrics class, the React component export, and the GoogleService export. ```typescript // Main class export { AmLyrics } from '@uimaxbai/am-lyrics'; // React component export { AmLyrics } from '@uimaxbai/am-lyrics/react'; // Google service (if exposed) export { GoogleService } from '@uimaxbai/am-lyrics'; ``` -------------------------------- ### GoogleService Static Methods Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Use the GoogleService class for language translation and romanization of lyrics. It supports translating text to a target language and romanizing single or multiple lyric strings. ```typescript import { GoogleService } from '@uimaxbai/am-lyrics'; GoogleService.translate(text, targetLang) GoogleService.romanize(lyrics) GoogleService.romanizeTexts(texts) ``` -------------------------------- ### Direct Class Import and Usage Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Import and instantiate the AmLyrics class directly for advanced use cases. Set properties like song title and current time after instantiation. ```typescript import { AmLyrics } from '@uimaxbai/am-lyrics'; const element = new AmLyrics(); element.songTitle = "Title"; element.currentTime = 0; ``` -------------------------------- ### Import am-lyrics React Component Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md Import the AmLyrics React wrapper component from the '@uimaxbai/am-lyrics/react' path. This component is built using createComponent() from @lit/react. ```typescript import { AmLyrics } from '@uimaxbai/am-lyrics/react'; ``` -------------------------------- ### GoogleService Static Methods Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Provides utility methods for interacting with Google services, such as translation and romanization. ```APIDOC ## GoogleService.translate ### Description Translates the given text or an array of strings to the target language. ### Method `GoogleService.translate(text: string | string[], targetLang: string)` ### Parameters * **text** (string | string[]) - The text or array of strings to translate. * **targetLang** (string) - The target language code (e.g., 'en', 'es'). ### Returns * `Promise` - A promise that resolves to the translated text or an array of translated strings. ## GoogleService.romanize ### Description Romanizes the provided lyrics data. ### Method `GoogleService.romanize(lyrics: { data?: T[] })` ### Parameters * **lyrics** ({ data?: T[] }) - An object containing lyrics data, potentially with a `data` property which is an array. ### Returns * `Promise` - A promise that resolves to the romanized lyrics data. ## GoogleService.romanizeTexts ### Description Romanizes an array of strings. ### Method `GoogleService.romanizeTexts(strings: string[])` ### Parameters * **strings** (string[]) - An array of strings to romanize. ### Returns * `Promise` - A promise that resolves to an array of romanized strings. ``` -------------------------------- ### Viewport Virtualization CSS Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/animation-system.md Applies to off-screen lyrics lines to reduce rendering overhead. Use when scrolling far from active content. ```css .lyrics-line.far-line { filter: none !important; will-change: auto !important; animation: none !important; } ``` -------------------------------- ### CSS Customization: Layout Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Set the height and width for the lyrics container and the AM Lyrics component itself to ensure proper layout. ```css #lyrics-container { height: 100vh; width: 100%; } am-lyrics { display: block; height: 100%; } ``` -------------------------------- ### CSS Keyframes for Static Grow Animation Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/animation-system.md Provides an alternative, more subtle grow style with a pulse effect, used for growable word animations and in the terminal state. It features a slight scale increase and text shadow. ```css @keyframes grow-static { 0%, 100% { transform: scale3d(1.01, 1.01, 1.1) translateY(-0.05%); text-shadow: 0 0 0 var(--lyplus-text-primary) transparent 100%; } 30%, 40% { transform: scale3d(1.1, 1.1, 1.1) translateY(-0.05%); text-shadow: 0 0 0.3em var(--lyplus-text-primary) transparent 50%; } } ``` -------------------------------- ### Syncing with RequestAnimationFrame Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Achieve smooth lyric synchronization using `requestAnimationFrame` for continuous updates during audio playback. ```javascript function animate() { lyrics.currentTime = audio.currentTime * 1000; requestAnimationFrame(animate); } audio.addEventListener('play', () => requestAnimationFrame(animate)); audio.addEventListener('pause', () => cancelAnimationFrame(rafId)); ``` -------------------------------- ### Am-Lyrics Distribution File Structure Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Outlines the generated file structure for the Am-Lyrics project after the build process. ```text dist/ ├── src/ │ ├── index.js │ ├── index.d.ts │ ├── AmLyrics.js │ ├── AmLyrics.d.ts │ ├── GoogleService.js │ ├── GoogleService.d.ts │ ├── react.js │ └── react.d.ts └── ... (minified versions) ``` -------------------------------- ### Direct Class Import Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Instantiate and configure the AmLyrics class directly in your TypeScript or JavaScript code. ```APIDOC ## Direct Class Import ```typescript import { AmLyrics } from '@uimaxbai/am-lyrics'; const element = new AmLyrics(); element.songTitle = "Title"; element.currentTime = 0; ``` ``` -------------------------------- ### Enable Debug Logging Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Enable debug logging for am-lyrics by setting the localStorage.debug variable. This is useful for debugging issues. ```javascript // Enable if needed localStorage.debug = 'am-lyrics:*'; ``` -------------------------------- ### Am-Lyrics Source File Structure Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Provides an overview of the source code directory structure for the Am-Lyrics project. ```text am-lyrics/ ├── src/ │ ├── AmLyrics.ts (6683 lines) - Main component │ ├── GoogleService.ts (330 lines) - Translation/romanization │ ├── am-lyrics.ts (4 lines) - Web component registration │ ├── react.ts (15 lines) - React wrapper │ └── index.ts (1 line) - Export AmLyrics class ├── package.json - Dependencies, exports, npm metadata ├── tsconfig.json - TypeScript configuration ├── rollup.config.js - Build configuration ├── custom-elements.json - Web components metadata (generated) └── README.md / next.md - Usage guides ``` -------------------------------- ### Fetch Lyrics from BiniLyrics Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/lyrics-providers.md Fetches TTML formatted lyrics with word synchronization from the BiniLyrics provider. Requires song title and artist; ISRC and duration are optional. ```typescript private static async fetchLyricsFromBiniLyrics( title: string, artist: string, isrc?: string, metadata: { durationMs?: number; album?: string } = {} ): Promise ``` ```typescript const result = await AmLyrics.fetchLyricsFromBiniLyrics( "Uptown Funk", "Mark Ronson", undefined, { durationMs: 269000 } ); if (result) { console.log(`Got ${result.lines.length} lines from ${result.source}`); } ``` -------------------------------- ### TypeScript Integration with AmLyrics Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md Demonstrates how to use the AmLyrics component with TypeScript, including handling custom events. Ensure you have the necessary types imported. ```tsx import React, { useRef, useState } from 'react'; import type { CustomEvent } from '@uimaxbai/am-lyrics'; import { AmLyrics } from '@uimaxbai/am-lyrics/react'; export function MyLyrics() { const [time, setTime] = useState(0); const handleClick = (event: CustomEvent<{ timestamp: number }>) => { console.log('Line clicked at:', event.detail.timestamp); }; return ( ); } ``` -------------------------------- ### AmLyrics Static Methods Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Provides utility methods for parsing and converting lyrics data. ```APIDOC ## AmLyrics.parseTTML ### Description Parses a TTML string into lyrics lines and optionally extracts songwriter information. ### Method `AmLyrics.parseTTML(ttmlString: string)` ### Parameters * **ttmlString** (string) - The TTML formatted string to parse. ### Returns * `{ lines: LyricsLine[], songwriters?: string } | null` - An object containing an array of LyricsLine objects and an optional songwriters string, or null if parsing fails. ## AmLyrics.convertKPoeLyrics ### Description Converts lyrics data from the KPoe format into an array of LyricsLine objects. ### Method `AmLyrics.convertKPoeLyrics(payload: any)` ### Parameters * **payload** (any) - The KPoe lyrics payload to convert. ### Returns * `LyricsLine[] | null` - An array of LyricsLine objects, or null if conversion fails. ``` -------------------------------- ### line-click Event Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/api-reference.md Fired when a user clicks on a specific lyrics line, providing the timestamp of that line. ```APIDOC ## line-click Event ### Description Fired when a user clicks on a lyrics line. ### Event Detail ```typescript interface LineClickDetail { timestamp: number; // Time in milliseconds where the click occurred } ``` ### Example ```javascript amLyrics.addEventListener('line-click', event => { console.log('Seek to:', event.detail.timestamp); audioElement.currentTime = event.detail.timestamp / 1000; }); ``` ``` -------------------------------- ### Configure next.config.ts Source: https://github.com/binimum/am-lyrics/blob/main/next.md Update your Next.js TypeScript configuration file to enable Lit SSR support. This involves wrapping your existing config with the `withLitSSR` function. ```typescript import type { NextConfig } from "next"; const withLitSSR = require('@lit-labs/nextjs')(); const nextConfig: NextConfig = { /* config options here */ reactStrictMode: true }; module.exports = withLitSSR(nextConfig); ``` -------------------------------- ### Playback Synchronization Data Flow Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Details the data flow for synchronizing lyrics playback with audio. It covers how time changes are handled and animations are updated. ```text currentTime Property Change ↓ _onTimeChanged(oldTime, newTime) ├→ Detect seek vs normal progression ├→ Find active lines at newTime ├→ Update DOM classes (.active, .pre-active, etc) ├→ Start animation from newTime ├→ Update scroll position (if autoScroll) ↓ Every frame via RAF: animateProgress() ├→ Update syllable wipe position ├→ Update character grow animations ├→ Update gap pulse state ↓ updateSyllablesForLine() ├→ Apply highlight class ├→ Compute animation timing ├→ Set CSS variables ``` -------------------------------- ### YouLyPlus Default Source Preference Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/lyrics-providers.md The default source preference order used by the KPoe query for YouLyPlus. This dictates the order in which lyric sources are queried. ```text apple, lyricsplus, musixmatch, spotify, qq, deezer, musixmatch-word ``` -------------------------------- ### Handle Translation Errors Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/google-service.md Demonstrates how to use a try-catch block to handle potential errors during the translation process. If an error occurs, it logs the error and the system falls back to the original text. ```typescript try { const result = await GoogleService.translate('Hello', 'es'); } catch (error) { console.error('Translation failed:', error); // Falls back to original text, so result will still be 'Hello' } ``` -------------------------------- ### Define Download Format Type Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/types.md Specifies the allowed formats for downloading lyrics. Use this type to ensure valid format selection. ```typescript type DownloadFormat = 'auto' | 'lrc' | 'ttml'; ``` -------------------------------- ### Basic HTML Integration Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Use this snippet to embed AM Lyrics directly in your HTML. Set the song title, artist, and current time. ```html ``` -------------------------------- ### Handling Server-Side Rendering Errors in Next.js Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md For Next.js applications using the App Router, prepend the file with the 'use client' directive. Alternatively, use dynamic import with `ssr: false` for older versions or specific scenarios. ```tsx 'use client'; // For App Router import { AmLyrics } from '@uimaxbai/am-lyrics/react'; ``` -------------------------------- ### Detection Thresholds Constants Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/animation-system.md Sets thresholds for detecting instrumental sections and user seeking actions. These constants help differentiate between normal playback and user-initiated seeking. ```typescript const INSTRUMENTAL_THRESHOLD_MS = 7000; // Show gap dots for gaps >= 7s const SEEK_THRESHOLD_MS = 500; // Threshold to detect seek vs normal progression ``` -------------------------------- ### Correct React Import for AmLyrics Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md Ensure you import the React component from the correct path '@uimaxbai/am-lyrics/react'. Incorrect imports can lead to 'am-lyrics is not defined' errors. ```tsx // ✓ Correct import { AmLyrics } from '@uimaxbai/am-lyrics/react'; // ✗ Wrong import { AmLyrics } from '@uimaxbai/am-lyrics'; ``` -------------------------------- ### Set Song Album for Provider Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/api-reference.md Optionally set the 'songAlbum' property to refine search accuracy with the LyricsPlus provider. ```javascript amLyrics.songAlbum = "Uptown Special"; ``` -------------------------------- ### AmLyrics Configuration Constants Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Lists configuration constants for timing and styling within AmLyrics. These values control animation durations, thresholds, and scaling factors for visual elements. ```typescript // Timing SCROLL_ANIMATION_DURATION_MS = 350 GAP_PULSE_DURATION_MS = 4000 SEEK_THRESHOLD_MS = 500 FETCH_TIMEOUT_MS = 8000 // Styling INSTRUMENTAL_THRESHOLD_MS = 7000 GAP_MIN_SCALE = 0.85 GAP_EXIT_LEAD_MS = 600 ``` -------------------------------- ### React Component Integration Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Integrate Am Lyrics into your React application using the provided wrapper component. Pass song details and time as props. ```tsx import { AmLyrics } from '@uimaxbai/am-lyrics/react'; ``` -------------------------------- ### Set Search Query Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/api-reference.md Set the 'query' property to search for lyrics metadata. The component will attempt to resolve it using LyricsPlus and fall back to Apple Music. ```javascript amLyrics.query = "Uptown Funk - Mark Ronson"; ``` -------------------------------- ### interpolate Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/api-reference.md Controls whether smooth word-by-word highlighting animation is enabled. If disabled, highlighting will occur on a line-by-line basis. ```APIDOC ## interpolate ### Description Enable smooth word-by-word highlighting animation. When disabled, uses line-by-line highlighting. ### Type `boolean` ### Attribute `interpolate` ### Default `true` ### Example ```javascript amLyrics.interpolate = false; ``` ``` -------------------------------- ### Dynamically Import Web Component in Next.js Source: https://github.com/binimum/am-lyrics/blob/main/next.md Dynamically import your custom web component and its React wrapper to ensure proper client-side rendering. This is crucial for components that rely on browser APIs. ```tsx // Put me at the start of the file: above the React example in README.md. import dynamic from 'next/dynamic'; const AmLyrics = dynamic( () => { // Dynamically import the custom element import('@uimaxbai/am-lyrics/am-lyrics.js'); // Then import the React component return import('@uimaxbai/am-lyrics/react').then((mod) => mod.AmLyrics); }, { ssr: false } ); ``` -------------------------------- ### will-change CSS Hints Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/animation-system.md Provides hints to the browser for optimizing rendering of elements expected to change. Use for elements with frequent transform, filter, or opacity changes. ```css .lyrics-line.active { will-change: transform, filter, opacity; } .background-vocal-container { will-change: max-height, opacity; } ``` -------------------------------- ### GoogleService Methods Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/INDEX.md Access utility functions within the GoogleService for text translation and romanization. ```APIDOC ## GoogleService ```typescript import { GoogleService } from '@uimaxbai/am-lyrics'; GoogleService.translate(text, targetLang) GoogleService.romanize(lyrics) GoogleService.romanizeTexts(texts) ``` ``` -------------------------------- ### Fetch Lyrics from LRCLIB Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/lyrics-providers.md Fetches lyrics from the LRCLIB API. It prioritizes synced lyrics (LRC format) and falls back to plain text if unavailable. Requires song metadata (title and artist). ```typescript private static async fetchLyricsFromLrclib( metadata: SongMetadata ): Promise ``` ```typescript const result = await AmLyrics.fetchLyricsFromLrclib({ title: "Levitating", artist: "Dua Lipa" }); ``` -------------------------------- ### Google Translate API Usage Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/quick-reference.md Demonstrates how to use the GoogleService.translate function to translate text. Supports both single strings and arrays of strings for batch translation. ```typescript // Single text const translated = await GoogleService.translate('Hello', 'es'); // Array of texts const translated = await GoogleService.translate( ['Hello', 'World'], 'es' ); ``` -------------------------------- ### Synchronize Lyrics with HTML Audio Element Source: https://github.com/binimum/am-lyrics/blob/main/README.md Integrates am-lyrics with an HTML audio element for synchronized playback. The lyrics component's `currentTime` is updated by the audio element's `timeupdate` event, and clicking a lyric line seeks and plays the audio. ```html ``` -------------------------------- ### Use AM Lyrics Web Component Source: https://github.com/binimum/am-lyrics/blob/main/README.md Use the AM Lyrics web component in your HTML. Configure it using attributes like song title, artist, duration, and highlight color. ```html ``` -------------------------------- ### Fetch with Timeout Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/google-service.md Wraps the fetch API to include a configurable timeout. Rejects with an AbortError if the timeout is exceeded, preventing hanging requests. ```typescript const response = await GoogleService['fetchWithTimeout']('https://api.example.com/data', 5000); ``` -------------------------------- ### GoogleService Configuration Object Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/types.md Defines retry and timeout settings for Google translation and romanization requests. Adjust these values to control request behavior. ```typescript const CONFIG = { GOOGLE: { MAX_RETRIES: 3, RETRY_DELAY_MS: 1000, FETCH_TIMEOUT_MS: 6000, }, }; ``` -------------------------------- ### am-lyrics Behavior Props Source: https://github.com/binimum/am-lyrics/blob/main/_autodocs/react-integration.md Configure the behavior of the lyrics component, such as enabling autoScroll and interpolation. ```tsx ```