diff --git a/packages/app/src/pages/lyrics/components/controller/index.jsx b/packages/app/src/pages/lyrics/components/controller/index.jsx
index 94265cf3..116c287d 100644
--- a/packages/app/src/pages/lyrics/components/controller/index.jsx
+++ b/packages/app/src/pages/lyrics/components/controller/index.jsx
@@ -177,7 +177,7 @@ const PlayerController = React.forwardRef((props, ref) => {
)}
- {playerState.track_manifest?.metadata.lossless && (
+ {playerState.track_manifest?.metadata?.lossless && (
{
- const [playerState] = usePlayerStateContext()
+ const [playerState] = usePlayerStateContext()
- const { lyrics } = props
+ const { lyrics } = props
- const [initialLoading, setInitialLoading] = React.useState(true)
- const [syncInterval, setSyncInterval] = React.useState(null)
- const [syncingVideo, setSyncingVideo] = React.useState(false)
- const [currentVideoLatency, setCurrentVideoLatency] = React.useState(0)
- const hls = React.useRef(new HLS())
+ const [initialLoading, setInitialLoading] = React.useState(true)
+ const [syncInterval, setSyncInterval] = React.useState(null)
+ const [syncingVideo, setSyncingVideo] = React.useState(false)
+ const [currentVideoLatency, setCurrentVideoLatency] = React.useState(0)
+ const hls = React.useRef(new HLS())
- async function seekVideoToSyncAudio() {
- if (!lyrics) {
- return null
- }
+ async function seekVideoToSyncAudio() {
+ if (!lyrics) {
+ return null
+ }
- if (!lyrics.video_source || typeof lyrics.sync_audio_at_ms === "undefined") {
- return null
- }
+ if (
+ !lyrics.video_source ||
+ typeof lyrics.sync_audio_at_ms === "undefined"
+ ) {
+ return null
+ }
- const currentTrackTime = app.cores.player.controls.seek()
+ const currentTrackTime = app.cores.player.controls.seek()
- setSyncingVideo(true)
+ setSyncingVideo(true)
- let newTime = currentTrackTime + (lyrics.sync_audio_at_ms / 1000) + app.cores.player.gradualFadeMs / 1000
+ let newTime =
+ currentTrackTime + lyrics.sync_audio_at_ms / 1000 + 150 / 1000
- // dec some ms to ensure the video seeks correctly
- newTime -= 5 / 1000
+ // dec some ms to ensure the video seeks correctly
+ newTime -= 5 / 1000
- videoRef.current.currentTime = newTime
- }
+ videoRef.current.currentTime = newTime
+ }
- async function syncPlayback() {
- // if something is wrong, stop syncing
- if (videoRef.current === null || !lyrics || !lyrics.video_source || typeof lyrics.sync_audio_at_ms === "undefined" || playerState.playback_status !== "playing") {
- return stopSyncInterval()
- }
+ async function syncPlayback() {
+ // if something is wrong, stop syncing
+ if (
+ videoRef.current === null ||
+ !lyrics ||
+ !lyrics.video_source ||
+ typeof lyrics.sync_audio_at_ms === "undefined" ||
+ playerState.playback_status !== "playing"
+ ) {
+ return stopSyncInterval()
+ }
- const currentTrackTime = app.cores.player.controls.seek()
- const currentVideoTime = videoRef.current.currentTime - (lyrics.sync_audio_at_ms / 1000)
+ const currentTrackTime = app.cores.player.controls.seek()
+ const currentVideoTime =
+ videoRef.current.currentTime - lyrics.sync_audio_at_ms / 1000
- //console.log(`Current track time: ${currentTrackTime}, current video time: ${currentVideoTime}`)
+ //console.log(`Current track time: ${currentTrackTime}, current video time: ${currentVideoTime}`)
- const maxOffset = maxLatencyInMs / 1000
- const currentVideoTimeDiff = Math.abs(currentVideoTime - currentTrackTime)
+ const maxOffset = maxLatencyInMs / 1000
+ const currentVideoTimeDiff = Math.abs(
+ currentVideoTime - currentTrackTime,
+ )
- setCurrentVideoLatency(currentVideoTimeDiff)
+ setCurrentVideoLatency(currentVideoTimeDiff)
- if (syncingVideo === true) {
- return false
- }
+ if (syncingVideo === true) {
+ return false
+ }
- if (currentVideoTimeDiff > maxOffset) {
- seekVideoToSyncAudio()
- }
- }
+ if (currentVideoTimeDiff > maxOffset) {
+ seekVideoToSyncAudio()
+ }
+ }
- function startSyncInterval() {
- setSyncInterval(setInterval(syncPlayback, 300))
- }
+ function startSyncInterval() {
+ setSyncInterval(setInterval(syncPlayback, 300))
+ }
- function stopSyncInterval() {
- setSyncingVideo(false)
- setSyncInterval(null)
- clearInterval(syncInterval)
- }
+ function stopSyncInterval() {
+ setSyncingVideo(false)
+ setSyncInterval(null)
+ clearInterval(syncInterval)
+ }
- //* handle when player is loading
- React.useEffect(() => {
- if (lyrics?.video_source && playerState.loading === true && playerState.playback_status === "playing") {
- videoRef.current.pause()
- }
+ //* handle when player is loading
+ React.useEffect(() => {
+ if (
+ lyrics?.video_source &&
+ playerState.loading === true &&
+ playerState.playback_status === "playing"
+ ) {
+ videoRef.current.pause()
+ }
- if (lyrics?.video_source && playerState.loading === false && playerState.playback_status === "playing") {
- videoRef.current.play()
- }
- }, [playerState.loading])
+ if (
+ lyrics?.video_source &&
+ playerState.loading === false &&
+ playerState.playback_status === "playing"
+ ) {
+ videoRef.current.play()
+ }
+ }, [playerState.loading])
- //* Handle when playback status change
- React.useEffect(() => {
- if (initialLoading === false) {
- console.log(`VIDEO:: Playback status changed to ${playerState.playback_status}`)
+ //* Handle when playback status change
+ React.useEffect(() => {
+ if (initialLoading === false) {
+ console.log(
+ `VIDEO:: Playback status changed to ${playerState.playback_status}`,
+ )
- if (lyrics && lyrics.video_source) {
- if (playerState.playback_status === "playing") {
- videoRef.current.play()
- startSyncInterval()
- } else {
- videoRef.current.pause()
- stopSyncInterval()
- }
- }
- }
- }, [playerState.playback_status])
+ if (lyrics && lyrics.video_source) {
+ if (playerState.playback_status === "playing") {
+ videoRef.current.play()
+ startSyncInterval()
+ } else {
+ videoRef.current.pause()
+ stopSyncInterval()
+ }
+ }
+ }
+ }, [playerState.playback_status])
- //* Handle when lyrics object change
- React.useEffect(() => {
- setCurrentVideoLatency(0)
- stopSyncInterval()
+ //* Handle when lyrics object change
+ React.useEffect(() => {
+ setCurrentVideoLatency(0)
+ stopSyncInterval()
- if (lyrics) {
- if (lyrics.video_source) {
- console.log("Loading video source >", lyrics.video_source)
+ if (lyrics) {
+ if (lyrics.video_source) {
+ console.log("Loading video source >", lyrics.video_source)
- if (lyrics.video_source.endsWith(".mp4")) {
- videoRef.current.src = lyrics.video_source
- } else {
- hls.current.loadSource(lyrics.video_source)
- }
+ if (lyrics.video_source.endsWith(".mp4")) {
+ videoRef.current.src = lyrics.video_source
+ } else {
+ hls.current.loadSource(lyrics.video_source)
+ }
- if (typeof lyrics.sync_audio_at_ms !== "undefined") {
- videoRef.current.loop = false
- videoRef.current.currentTime = lyrics.sync_audio_at_ms / 1000
+ if (typeof lyrics.sync_audio_at_ms !== "undefined") {
+ videoRef.current.loop = false
+ videoRef.current.currentTime =
+ lyrics.sync_audio_at_ms / 1000
- startSyncInterval()
- } else {
- videoRef.current.loop = true
- videoRef.current.currentTime = 0
- }
+ startSyncInterval()
+ } else {
+ videoRef.current.loop = true
+ videoRef.current.currentTime = 0
+ }
- if (playerState.playback_status === "playing") {
- videoRef.current.play()
- }
- }
- }
+ if (playerState.playback_status === "playing") {
+ videoRef.current.play()
+ }
+ }
+ }
- setInitialLoading(false)
- }, [lyrics])
+ setInitialLoading(false)
+ }, [lyrics])
- React.useEffect(() => {
- videoRef.current.addEventListener("seeked", (event) => {
- setSyncingVideo(false)
- })
+ React.useEffect(() => {
+ videoRef.current.addEventListener("seeked", (event) => {
+ setSyncingVideo(false)
+ })
- hls.current.attachMedia(videoRef.current)
+ hls.current.attachMedia(videoRef.current)
- return () => {
- stopSyncInterval()
- }
- }, [])
+ return () => {
+ stopSyncInterval()
+ }
+ }, [])
- return <>
- {
- props.lyrics?.sync_audio_at &&
-
-
Maximun latency
-
{maxLatencyInMs}ms
-
-
-
Video Latency
-
{(currentVideoLatency * 1000).toFixed(2)}ms
-
- {syncingVideo ?
Syncing video...
: null}
-
- }
+ return (
+ <>
+ {props.lyrics?.sync_audio_at && (
+
+
+
Maximun latency
+
{maxLatencyInMs}ms
+
+
+
Video Latency
+
{(currentVideoLatency * 1000).toFixed(2)}ms
+
+ {syncingVideo ?
Syncing video...
: null}
+
+ )}
-
- >
+
+ >
+ )
})
-export default LyricsVideo
\ No newline at end of file
+export default LyricsVideo
diff --git a/packages/app/src/pages/lyrics/index.jsx b/packages/app/src/pages/lyrics/index.jsx
index 3f0428ad..320ca842 100644
--- a/packages/app/src/pages/lyrics/index.jsx
+++ b/packages/app/src/pages/lyrics/index.jsx
@@ -89,7 +89,8 @@ const EnhancedLyricsPage = () => {
// Track manifest comparison
useEffect(() => {
- const newManifest = playerState.track_manifest?.toSeriableObject()
+ const newManifest = playerState.track_manifest
+
if (JSON.stringify(newManifest) !== JSON.stringify(trackManifest)) {
setTrackManifest(newManifest)
}