mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
unmute me
This commit is contained in:
@@ -12,6 +12,7 @@ import { isFeatureEnabled } from '../../lib/features.js';
|
||||
import { innerFlowClass } from './constants.js';
|
||||
|
||||
const PTZ_CAMERA_ID = 'ptz-camera';
|
||||
const PTZ_AUDIO_RETRY_MS = 1000;
|
||||
|
||||
function formatRemaining(deadline) {
|
||||
const remaining = Math.max(0, Math.ceil((Number(deadline || 0) - Date.now()) / 1000));
|
||||
@@ -81,6 +82,7 @@ function PtzLiveVideo({ enabled }) {
|
||||
const videoRef = useRef(null);
|
||||
const playerRef = useRef(null);
|
||||
const retryTimerRef = useRef(null);
|
||||
const playTimerRef = useRef(null);
|
||||
const [status, setStatus] = useState('idle');
|
||||
const [retryVersion, setRetryVersion] = useState(0);
|
||||
const sources = useVideoRequests(
|
||||
@@ -114,6 +116,7 @@ function PtzLiveVideo({ enabled }) {
|
||||
url: source.url,
|
||||
token: source.token,
|
||||
video: videoRef.current,
|
||||
startMuted: false,
|
||||
onStatus: (nextStatus) => {
|
||||
setStatus(nextStatus);
|
||||
if (['error', 'failed', 'disconnected', 'closed'].includes(String(nextStatus || '').toLowerCase())) {
|
||||
@@ -132,12 +135,45 @@ function PtzLiveVideo({ enabled }) {
|
||||
};
|
||||
}, [enabled, scheduleRetry, source?.token, source?.url]);
|
||||
|
||||
useEffect(() => {
|
||||
const video = videoRef.current;
|
||||
if (!enabled || !source?.url || !video) {
|
||||
if (playTimerRef.current) clearInterval(playTimerRef.current);
|
||||
playTimerRef.current = null;
|
||||
return undefined;
|
||||
}
|
||||
/*
|
||||
The server now publishes inline Opus audio on the PTZ WHEP stream. The
|
||||
shared WHEP helper starts playback once, but browsers can still reject or
|
||||
pause audible media depending on the exact timing of the fullscreen/user
|
||||
gesture. Retry the same element with muted=false so unmuting is not a
|
||||
manual DevTools-only operation.
|
||||
*/
|
||||
const attemptPlay = () => {
|
||||
const target = videoRef.current;
|
||||
if (!target) return;
|
||||
target.muted = false;
|
||||
if (!target.paused && !target.ended) return;
|
||||
target.play().catch(() => {});
|
||||
};
|
||||
attemptPlay();
|
||||
playTimerRef.current = setInterval(attemptPlay, PTZ_AUDIO_RETRY_MS);
|
||||
return () => {
|
||||
if (playTimerRef.current) clearInterval(playTimerRef.current);
|
||||
playTimerRef.current = null;
|
||||
};
|
||||
}, [enabled, source?.url, status]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (retryTimerRef.current) {
|
||||
clearTimeout(retryTimerRef.current);
|
||||
retryTimerRef.current = null;
|
||||
}
|
||||
if (playTimerRef.current) {
|
||||
clearInterval(playTimerRef.current);
|
||||
playTimerRef.current = null;
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -29,12 +29,19 @@ function buildAuthHeader(token) {
|
||||
}
|
||||
|
||||
export class WhepPlayer {
|
||||
constructor({ url, token, video, onStatus, audioOnly = false, receiveAudio = true }) {
|
||||
constructor({ url, token, video, onStatus, audioOnly = false, receiveAudio = true, startMuted = null }) {
|
||||
this.url = url;
|
||||
this.token = token;
|
||||
this.video = video;
|
||||
this.audioOnly = audioOnly;
|
||||
this.receiveAudio = receiveAudio;
|
||||
/*
|
||||
Browser autoplay usually requires normal video streams to start muted,
|
||||
while audio-only streams need to start audible. Keep that historical
|
||||
default, but allow a caller that is already behind a user gesture, such as
|
||||
the PTZ fullscreen controller, to request audible inline audio.
|
||||
*/
|
||||
this.startMuted = startMuted === null ? !audioOnly : Boolean(startMuted);
|
||||
this.pc = null;
|
||||
this.abortController = null;
|
||||
this.onStatus = onStatus;
|
||||
@@ -50,7 +57,7 @@ export class WhepPlayer {
|
||||
if (!this.video) return;
|
||||
this.video.playsInline = true;
|
||||
this.video.autoplay = true;
|
||||
this.video.muted = this.audioOnly ? false : true;
|
||||
this.video.muted = this.startMuted;
|
||||
if (typeof this.video.disableRemotePlayback !== 'undefined') {
|
||||
this.video.disableRemotePlayback = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user