lrc-audio-player 0.1.4 → 0.1.6

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/react.cjs CHANGED
@@ -402,9 +402,13 @@ function useLyricPlayer(options) {
402
402
  const [player, setPlayer] = (0, import_react.useState)(null);
403
403
  const [currentLine, setCurrentLine] = (0, import_react.useState)(null);
404
404
  const [currentIndex, setCurrentIndex] = (0, import_react.useState)(-1);
405
+ const [currentToken, setCurrentToken] = (0, import_react.useState)(null);
405
406
  const [lines, setLines] = (0, import_react.useState)([]);
406
407
  const [isLoading, setIsLoading] = (0, import_react.useState)(false);
407
408
  const [error, setError] = (0, import_react.useState)(null);
409
+ const [isPlaying, setIsPlaying] = (0, import_react.useState)(false);
410
+ const [currentTime, setCurrentTime] = (0, import_react.useState)(0);
411
+ const [duration, setDuration] = (0, import_react.useState)(0);
408
412
  const optionsRef = (0, import_react.useRef)(options);
409
413
  optionsRef.current = options;
410
414
  (0, import_react.useEffect)(() => {
@@ -419,6 +423,10 @@ function useLyricPlayer(options) {
419
423
  setLines([]);
420
424
  setCurrentLine(null);
421
425
  setCurrentIndex(-1);
426
+ setCurrentToken(null);
427
+ setIsPlaying(false);
428
+ setCurrentTime(0);
429
+ setDuration(0);
422
430
  LyricPlayer.create({
423
431
  audio: audioEl,
424
432
  lyrics,
@@ -433,10 +441,23 @@ function useLyricPlayer(options) {
433
441
  setPlayer(instance);
434
442
  setLines(instance.lines);
435
443
  setIsLoading(false);
444
+ if (!isNaN(instance.duration)) {
445
+ setDuration(instance.duration);
446
+ }
447
+ instance.audio.addEventListener("loadedmetadata", () => {
448
+ setDuration(instance.duration);
449
+ });
436
450
  instance.on("linechange", (line, index) => {
437
451
  setCurrentLine(line);
438
452
  setCurrentIndex(index);
439
453
  });
454
+ instance.on("timeupdate", (time) => {
455
+ setCurrentTime(time);
456
+ setCurrentToken(instance.getCurrentToken());
457
+ });
458
+ instance.on("play", () => setIsPlaying(true));
459
+ instance.on("pause", () => setIsPlaying(false));
460
+ instance.on("ended", () => setIsPlaying(false));
440
461
  }).catch((err) => {
441
462
  if (!cancelled) {
442
463
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -457,14 +478,44 @@ function useLyricPlayer(options) {
457
478
  options.skipCBR,
458
479
  options.cbrBitrate
459
480
  ]);
481
+ const seek = (0, import_react.useCallback)(
482
+ (timeSeconds) => {
483
+ player?.seek(timeSeconds);
484
+ },
485
+ [player]
486
+ );
487
+ const seekToLine = (0, import_react.useCallback)(
488
+ (index) => {
489
+ player?.seekToLine(index);
490
+ },
491
+ [player]
492
+ );
493
+ const play = (0, import_react.useCallback)(() => {
494
+ return player?.play() ?? Promise.resolve();
495
+ }, [player]);
496
+ const pause = (0, import_react.useCallback)(() => {
497
+ player?.pause();
498
+ }, [player]);
499
+ const toggle = (0, import_react.useCallback)(() => {
500
+ return player?.toggle();
501
+ }, [player]);
460
502
  return {
461
503
  player,
462
504
  audioRef,
463
505
  currentLine,
464
506
  currentIndex,
507
+ currentToken,
465
508
  lines,
466
509
  isLoading,
467
- error
510
+ error,
511
+ isPlaying,
512
+ currentTime,
513
+ duration,
514
+ seek,
515
+ seekToLine,
516
+ play,
517
+ pause,
518
+ toggle
468
519
  };
469
520
  }
470
521
  // Annotate the CommonJS export names for ESM import in node:
package/dist/react.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { h as LyricPlayerOptions, b as LyricPlayer, L as LyricLine } from './player-sLsiwLVO.cjs';
1
+ import { h as LyricPlayerOptions, b as LyricPlayer, L as LyricLine, g as LyricToken } from './player-sLsiwLVO.cjs';
2
2
  export { f as LyricSource } from './player-sLsiwLVO.cjs';
3
3
 
4
4
  interface UseLyricPlayerOptions extends Omit<LyricPlayerOptions, "audio"> {
@@ -18,12 +18,30 @@ interface UseLyricPlayerResult {
18
18
  currentLine: LyricLine | null;
19
19
  /** Index of the currently active lyric line (-1 if none yet). */
20
20
  currentIndex: number;
21
+ /** The currently active word/token (for word-level LRC), or null. */
22
+ currentToken: LyricToken | null;
21
23
  /** All parsed lyric lines (empty until lyrics are loaded). */
22
24
  lines: LyricLine[];
23
25
  /** Whether the player is initializing (CBR conversion in progress). */
24
26
  isLoading: boolean;
25
27
  /** Error if initialization failed. */
26
28
  error: Error | null;
29
+ /** Whether audio is currently playing. */
30
+ isPlaying: boolean;
31
+ /** Current playback time in seconds. */
32
+ currentTime: number;
33
+ /** Total audio duration in seconds (0 if unknown). */
34
+ duration: number;
35
+ /** Jump to a specific time in seconds. */
36
+ seek: (timeSeconds: number) => void;
37
+ /** Jump to the start of a specific lyric line. */
38
+ seekToLine: (index: number) => void;
39
+ /** Play the audio. */
40
+ play: () => Promise<void>;
41
+ /** Pause the audio. */
42
+ pause: () => void;
43
+ /** Toggle play/pause. */
44
+ toggle: () => Promise<void> | void;
27
45
  }
28
46
  /**
29
47
  * React hook that creates a {@link LyricPlayer} bound to an `<audio>`
@@ -36,7 +54,7 @@ interface UseLyricPlayerResult {
36
54
  * ```tsx
37
55
  * 'use client';
38
56
  *
39
- * const { audioRef, currentLine, lines, player, isLoading } = useLyricPlayer({
57
+ * const { audioRef, currentLine, lines, isLoading, isPlaying, currentTime } = useLyricPlayer({
40
58
  * audio: '/song.mp3',
41
59
  * lyrics: lrcText,
42
60
  * });
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { h as LyricPlayerOptions, b as LyricPlayer, L as LyricLine } from './player-sLsiwLVO.js';
1
+ import { h as LyricPlayerOptions, b as LyricPlayer, L as LyricLine, g as LyricToken } from './player-sLsiwLVO.js';
2
2
  export { f as LyricSource } from './player-sLsiwLVO.js';
3
3
 
4
4
  interface UseLyricPlayerOptions extends Omit<LyricPlayerOptions, "audio"> {
@@ -18,12 +18,30 @@ interface UseLyricPlayerResult {
18
18
  currentLine: LyricLine | null;
19
19
  /** Index of the currently active lyric line (-1 if none yet). */
20
20
  currentIndex: number;
21
+ /** The currently active word/token (for word-level LRC), or null. */
22
+ currentToken: LyricToken | null;
21
23
  /** All parsed lyric lines (empty until lyrics are loaded). */
22
24
  lines: LyricLine[];
23
25
  /** Whether the player is initializing (CBR conversion in progress). */
24
26
  isLoading: boolean;
25
27
  /** Error if initialization failed. */
26
28
  error: Error | null;
29
+ /** Whether audio is currently playing. */
30
+ isPlaying: boolean;
31
+ /** Current playback time in seconds. */
32
+ currentTime: number;
33
+ /** Total audio duration in seconds (0 if unknown). */
34
+ duration: number;
35
+ /** Jump to a specific time in seconds. */
36
+ seek: (timeSeconds: number) => void;
37
+ /** Jump to the start of a specific lyric line. */
38
+ seekToLine: (index: number) => void;
39
+ /** Play the audio. */
40
+ play: () => Promise<void>;
41
+ /** Pause the audio. */
42
+ pause: () => void;
43
+ /** Toggle play/pause. */
44
+ toggle: () => Promise<void> | void;
27
45
  }
28
46
  /**
29
47
  * React hook that creates a {@link LyricPlayer} bound to an `<audio>`
@@ -36,7 +54,7 @@ interface UseLyricPlayerResult {
36
54
  * ```tsx
37
55
  * 'use client';
38
56
  *
39
- * const { audioRef, currentLine, lines, player, isLoading } = useLyricPlayer({
57
+ * const { audioRef, currentLine, lines, isLoading, isPlaying, currentTime } = useLyricPlayer({
40
58
  * audio: '/song.mp3',
41
59
  * lyrics: lrcText,
42
60
  * });
package/dist/react.js CHANGED
@@ -4,15 +4,19 @@ import {
4
4
  } from "./chunk-3A2M5KTA.js";
5
5
 
6
6
  // src/react.ts
7
- import { useEffect, useRef, useState } from "react";
7
+ import { useEffect, useRef, useState, useCallback } from "react";
8
8
  function useLyricPlayer(options) {
9
9
  const audioRef = useRef(null);
10
10
  const [player, setPlayer] = useState(null);
11
11
  const [currentLine, setCurrentLine] = useState(null);
12
12
  const [currentIndex, setCurrentIndex] = useState(-1);
13
+ const [currentToken, setCurrentToken] = useState(null);
13
14
  const [lines, setLines] = useState([]);
14
15
  const [isLoading, setIsLoading] = useState(false);
15
16
  const [error, setError] = useState(null);
17
+ const [isPlaying, setIsPlaying] = useState(false);
18
+ const [currentTime, setCurrentTime] = useState(0);
19
+ const [duration, setDuration] = useState(0);
16
20
  const optionsRef = useRef(options);
17
21
  optionsRef.current = options;
18
22
  useEffect(() => {
@@ -27,6 +31,10 @@ function useLyricPlayer(options) {
27
31
  setLines([]);
28
32
  setCurrentLine(null);
29
33
  setCurrentIndex(-1);
34
+ setCurrentToken(null);
35
+ setIsPlaying(false);
36
+ setCurrentTime(0);
37
+ setDuration(0);
30
38
  LyricPlayer.create({
31
39
  audio: audioEl,
32
40
  lyrics,
@@ -41,10 +49,23 @@ function useLyricPlayer(options) {
41
49
  setPlayer(instance);
42
50
  setLines(instance.lines);
43
51
  setIsLoading(false);
52
+ if (!isNaN(instance.duration)) {
53
+ setDuration(instance.duration);
54
+ }
55
+ instance.audio.addEventListener("loadedmetadata", () => {
56
+ setDuration(instance.duration);
57
+ });
44
58
  instance.on("linechange", (line, index) => {
45
59
  setCurrentLine(line);
46
60
  setCurrentIndex(index);
47
61
  });
62
+ instance.on("timeupdate", (time) => {
63
+ setCurrentTime(time);
64
+ setCurrentToken(instance.getCurrentToken());
65
+ });
66
+ instance.on("play", () => setIsPlaying(true));
67
+ instance.on("pause", () => setIsPlaying(false));
68
+ instance.on("ended", () => setIsPlaying(false));
48
69
  }).catch((err) => {
49
70
  if (!cancelled) {
50
71
  setError(err instanceof Error ? err : new Error(String(err)));
@@ -65,14 +86,44 @@ function useLyricPlayer(options) {
65
86
  options.skipCBR,
66
87
  options.cbrBitrate
67
88
  ]);
89
+ const seek = useCallback(
90
+ (timeSeconds) => {
91
+ player?.seek(timeSeconds);
92
+ },
93
+ [player]
94
+ );
95
+ const seekToLine = useCallback(
96
+ (index) => {
97
+ player?.seekToLine(index);
98
+ },
99
+ [player]
100
+ );
101
+ const play = useCallback(() => {
102
+ return player?.play() ?? Promise.resolve();
103
+ }, [player]);
104
+ const pause = useCallback(() => {
105
+ player?.pause();
106
+ }, [player]);
107
+ const toggle = useCallback(() => {
108
+ return player?.toggle();
109
+ }, [player]);
68
110
  return {
69
111
  player,
70
112
  audioRef,
71
113
  currentLine,
72
114
  currentIndex,
115
+ currentToken,
73
116
  lines,
74
117
  isLoading,
75
- error
118
+ error,
119
+ isPlaying,
120
+ currentTime,
121
+ duration,
122
+ seek,
123
+ seekToLine,
124
+ play,
125
+ pause,
126
+ toggle
76
127
  };
77
128
  }
78
129
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lrc-audio-player",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Sync LRC/word-level lyrics to an HTML audio element with one constructor. Includes an optional React hook at lrc-audio-player/react.",
5
5
  "repository": {
6
6
  "type": "git",