import {roomTime, useRoomRunningAndReadyChanged, useRoomTime, useTimelineSongFileChanged} from "../lib/Connection"; import {useRef, useState} from "react"; const Player = () => { const roomRunning = useRoomRunningAndReadyChanged(); const _ = useRoomTime() const timeline = useTimelineSongFileChanged(); const player = useRef(timeline ? new Audio(timeline.songFile) : null); const [timesSeeked, setTimesSeeked] = useState(0); // If our time synchronisation algorithm thing thinks the time is off by more // than this value, we seek the running player to correct it. const diffSecondsRequiredToSeekRunningPlayer = 0.20; // Hard cap we are allowed to seek this player. Some browsers are slow or inaccurate // and will always be off. To avoid endless skipping of the song this cap stops seeking the // player. const maxTimesSeekAllow = 20; if (player.current && roomRunning?.running && roomRunning.readyToParticipate) { let targetTime = roomTime() / 1000; let diff = player.current.currentTime - targetTime; console.log('PLAYER DIFF', 'Our time diff with the server: ', diff, 'Time required to seek (seconds): ', diffSecondsRequiredToSeekRunningPlayer); if (Math.abs(diff) > diffSecondsRequiredToSeekRunningPlayer) { if (roomRunning.speedFactor != 1 || timesSeeked < maxTimesSeekAllow) { player.current.currentTime = targetTime; player.current.playbackRate = Math.max(Math.min(4.0, roomRunning.speedFactor), 0.25); setTimesSeeked(timesSeeked + 1); console.log('SEEKED', 'The running player time was seeked, times seeked in total: ' + timesSeeked); } else { console.warn('The running player is off, but we\'ve changed the time ' + 'too often, skipping synchronizing the player.'); } } if (player.current.paused) { player.current.play().catch(e => { console.error('Error playing', e); }) } } else { if (player.current) { player.current.pause(); } } return null; } export default Player;