Use dashjs

This commit is contained in:
srgooglo 2025-07-04 16:41:10 +02:00
parent 105fff2009
commit 392e356ba5

View File

@ -1,5 +1,5 @@
import React, { useEffect, useCallback } from "react" import React from "react"
import shaka from "shaka-player/dist/shaka-player.compiled.js" import * as dashjs from "dashjs"
import { useLyricsEditor } from "../context/LyricsEditorContext" import { useLyricsEditor } from "../context/LyricsEditorContext"
export const useAudioPlayer = (src) => { export const useAudioPlayer = (src) => {
@ -8,10 +8,10 @@ export const useAudioPlayer = (src) => {
const audioRef = React.useRef(new Audio()) const audioRef = React.useRef(new Audio())
const playerRef = React.useRef(null) const playerRef = React.useRef(null)
const waitTimeoutRef = React.useRef(null) const waitTimeoutRef = React.useRef(null)
const lastSeekTimeRef = React.useRef(0)
const scrubTimeoutRef = React.useRef(null) const scrubTimeoutRef = React.useRef(null)
const initializePlayer = useCallback(async () => { const initializePlayer = React.useCallback(async () => {
if (!src) { if (!src) {
return null return null
} }
@ -22,25 +22,15 @@ export const useAudioPlayer = (src) => {
audioRef.current.loop = true audioRef.current.loop = true
// Cleanup existing player
if (playerRef.current) { if (playerRef.current) {
await playerRef.current.destroy() playerRef.current.destroy()
playerRef.current = null playerRef.current = null
} }
// Check browser support playerRef.current = dashjs.MediaPlayer().create()
if (!shaka.Player.isBrowserSupported()) {
throw new Error("Browser does not support DASH playback")
}
// Create new player playerRef.current.on(dashjs.MediaPlayer.events.ERROR, (event) => {
playerRef.current = new shaka.Player() const error = event.error
await playerRef.current.attach(audioRef.current)
// Setup DASH error handling
playerRef.current.addEventListener("error", (event) => {
const error = event.detail
dispatch({ dispatch({
type: "SET_AUDIO_ERROR", type: "SET_AUDIO_ERROR",
@ -48,9 +38,26 @@ export const useAudioPlayer = (src) => {
}) })
}) })
// Load the source // setup other events
await playerRef.current.load(src) playerRef.current.on(
dispatch({ type: "SET_AUDIO_LOADING", payload: false }) dashjs.MediaPlayer.events.STREAM_INITIALIZED,
() => {
dispatch({ type: "SET_AUDIO_LOADING", payload: false })
},
)
playerRef.current.on(
dashjs.MediaPlayer.events.PLAYBACK_ERROR,
(event) => {
dispatch({
type: "SET_AUDIO_ERROR",
payload: `Playback Error: ${event.error || "Unknown error"}`,
})
},
)
// initialize player with audio element
playerRef.current.initialize(audioRef.current, src, false)
} catch (error) { } catch (error) {
console.error("Player initialization error:", error) console.error("Player initialization error:", error)
dispatch({ type: "SET_AUDIO_ERROR", payload: error.message }) dispatch({ type: "SET_AUDIO_ERROR", payload: error.message })
@ -59,7 +66,7 @@ export const useAudioPlayer = (src) => {
}, [src, dispatch]) }, [src, dispatch])
// Audio controls // Audio controls
const play = useCallback(async () => { const play = React.useCallback(async () => {
if (!audioRef.current) return if (!audioRef.current) return
try { try {
@ -75,13 +82,13 @@ export const useAudioPlayer = (src) => {
} }
}, [dispatch]) }, [dispatch])
const pause = useCallback(() => { const pause = React.useCallback(() => {
if (audioRef.current) { if (audioRef.current) {
audioRef.current.pause() audioRef.current.pause()
} }
}, []) }, [])
const toggle = useCallback(() => { const toggle = React.useCallback(() => {
if (audioRef.current.paused) { if (audioRef.current.paused) {
play() play()
} else { } else {
@ -89,19 +96,19 @@ export const useAudioPlayer = (src) => {
} }
}, [audioRef.current]) }, [audioRef.current])
const seek = useCallback((time, scrub = false) => { const seek = React.useCallback((time, scrub = false) => {
if (audioRef.current && audioRef.current.duration > 0) { if (audioRef.current && audioRef.current.duration > 0) {
const clampedTime = Math.max( const clampedTime = Math.max(
0, 0,
Math.min(time, audioRef.current.duration), Math.min(time, audioRef.current.duration),
) )
// Update currentTime immediately for responsive UI // update currentTime
audioRef.current.currentTime = clampedTime audioRef.current.currentTime = clampedTime
if (audioRef.current.paused) { if (audioRef.current.paused) {
if (scrub === true) { if (scrub === true) {
// Clear any pending scrub preview // clear any pending scrub preview
if (scrubTimeoutRef.current) { if (scrubTimeoutRef.current) {
clearTimeout(scrubTimeoutRef.current) clearTimeout(scrubTimeoutRef.current)
} }
@ -121,7 +128,7 @@ export const useAudioPlayer = (src) => {
} }
}, []) }, [])
const setSpeed = useCallback( const setSpeed = React.useCallback(
(speed) => { (speed) => {
if (audioRef.current) { if (audioRef.current) {
const clampedSpeed = Math.max(0.25, Math.min(4, speed)) const clampedSpeed = Math.max(0.25, Math.min(4, speed))
@ -132,7 +139,7 @@ export const useAudioPlayer = (src) => {
[dispatch], [dispatch],
) )
const setVolume = useCallback( const setVolume = React.useCallback(
(volume) => { (volume) => {
if (audioRef.current) { if (audioRef.current) {
const clampedVolume = Math.max(0, Math.min(1, volume)) const clampedVolume = Math.max(0, Math.min(1, volume))
@ -143,19 +150,19 @@ export const useAudioPlayer = (src) => {
[dispatch], [dispatch],
) )
// Initialize player when src changes // initialize player when src changes
useEffect(() => { React.useEffect(() => {
initializePlayer() initializePlayer()
return () => { return () => {
if (playerRef.current) { if (playerRef.current) {
playerRef.current.destroy().catch(console.error) playerRef.current.destroy()
} }
} }
}, [initializePlayer]) }, [initializePlayer])
// Setup audio event listeners // setup audio event listeners
useEffect(() => { React.useEffect(() => {
const audio = audioRef.current const audio = audioRef.current
if (!audio) { if (!audio) {
@ -215,7 +222,6 @@ export const useAudioPlayer = (src) => {
dispatch({ type: "SET_AUDIO_ERROR", payload: errorMessage }) dispatch({ type: "SET_AUDIO_ERROR", payload: errorMessage })
} }
// Add event listeners
audio.addEventListener("play", handlePlay) audio.addEventListener("play", handlePlay)
audio.addEventListener("pause", handlePause) audio.addEventListener("pause", handlePause)
audio.addEventListener("waiting", handleWaiting) audio.addEventListener("waiting", handleWaiting)
@ -223,7 +229,6 @@ export const useAudioPlayer = (src) => {
audio.addEventListener("error", handleError) audio.addEventListener("error", handleError)
return () => { return () => {
// Remove event listeners
audio.removeEventListener("play", handlePlay) audio.removeEventListener("play", handlePlay)
audio.removeEventListener("pause", handlePause) audio.removeEventListener("pause", handlePause)
audio.removeEventListener("waiting", handleWaiting) audio.removeEventListener("waiting", handleWaiting)