Fix video
This commit is contained in:
@@ -226,13 +226,17 @@ export default function CallModal({ isOpen, onClose, targetUser, callType: initi
|
|||||||
const streams = event.streams;
|
const streams = event.streams;
|
||||||
console.log(`[WebRTC] Received track: ${track.kind} state: ${track.readyState} streams: ${streams.length}`);
|
console.log(`[WebRTC] Received track: ${track.kind} state: ${track.readyState} streams: ${streams.length}`);
|
||||||
|
|
||||||
|
// Ensure we have a stable remote stream object
|
||||||
|
if (!remoteStreamRef.current) {
|
||||||
|
remoteStreamRef.current = streams[0] || new MediaStream([track]);
|
||||||
|
} else if (!remoteStreamRef.current.getTracks().includes(track)) {
|
||||||
|
remoteStreamRef.current.addTrack(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
const stream = remoteStreamRef.current;
|
||||||
|
|
||||||
// Helper to update video UI state
|
// Helper to update video UI state
|
||||||
const checkVideo = () => {
|
const checkVideo = () => {
|
||||||
const stream = remoteStreamRef.current;
|
|
||||||
if (!stream) {
|
|
||||||
setHasRemoteVideo(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const videoTracks = stream.getVideoTracks();
|
const videoTracks = stream.getVideoTracks();
|
||||||
const hasVideo = videoTracks.length > 0 && videoTracks.some(
|
const hasVideo = videoTracks.length > 0 && videoTracks.some(
|
||||||
t => t.readyState === 'live' && t.enabled && !t.muted
|
t => t.readyState === 'live' && t.enabled && !t.muted
|
||||||
@@ -244,36 +248,35 @@ export default function CallModal({ isOpen, onClose, targetUser, callType: initi
|
|||||||
|
|
||||||
setHasRemoteVideo(hasVideo);
|
setHasRemoteVideo(hasVideo);
|
||||||
if (hasVideo && callType !== 'video') {
|
if (hasVideo && callType !== 'video') {
|
||||||
console.log('[checkVideo] Auto-switching to video mode');
|
|
||||||
setCallType('video');
|
setCallType('video');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure we have a stream object
|
// Force binding to the SINGLE stable video element
|
||||||
if (!remoteStreamRef.current) {
|
if (remoteVideoRef.current) {
|
||||||
remoteStreamRef.current = streams[0] || new MediaStream([track]);
|
if (remoteVideoRef.current.srcObject !== stream) {
|
||||||
} else if (!remoteStreamRef.current.getTracks().includes(track)) {
|
console.log('[WebRTC] Binding stream to video element');
|
||||||
remoteStreamRef.current.addTrack(track);
|
remoteVideoRef.current.srcObject = stream;
|
||||||
|
}
|
||||||
|
// Try to play. If fails, it's usually autoplay policy
|
||||||
|
remoteVideoRef.current.play().catch(() => {
|
||||||
|
console.warn('[WebRTC] Autoplay blocked, waiting for interaction');
|
||||||
|
// Important: we keep trying to play because users often click the UI
|
||||||
|
const retryPlay = () => {
|
||||||
|
remoteVideoRef.current?.play().then(() => {
|
||||||
|
console.log('[WebRTC] Video started after retry');
|
||||||
|
}).catch(() => setTimeout(retryPlay, 2000));
|
||||||
|
};
|
||||||
|
retryPlay();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const stream = remoteStreamRef.current;
|
// Handle audio via stable audio element
|
||||||
|
if (remoteAudioRef.current) {
|
||||||
// Link to DOM elements
|
if (remoteAudioRef.current.srcObject !== stream) {
|
||||||
if (track.kind === 'video' && remoteVideoRef.current) {
|
remoteAudioRef.current.srcObject = stream;
|
||||||
remoteVideoRef.current.srcObject = stream;
|
|
||||||
// MUST be muted to autoplay in most browsers
|
|
||||||
remoteVideoRef.current.muted = true;
|
|
||||||
remoteVideoRef.current.play().catch(err => console.warn('[WebRTC] video play failed:', err));
|
|
||||||
checkVideo();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (track.kind === 'audio' || (track.kind === 'video' && !remoteAudioRef.current?.srcObject)) {
|
|
||||||
if (remoteAudioRef?.current) {
|
|
||||||
remoteAudioRef.current.srcObject = stream;
|
|
||||||
remoteAudioRef.current.play().catch(err => {
|
|
||||||
console.warn('[WebRTC] Audio play failed, user gesture needed:', err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
remoteAudioRef.current.play().catch(e => console.warn('[WebRTC] Audio play failed:', e));
|
||||||
}
|
}
|
||||||
|
|
||||||
track.onunmute = checkVideo;
|
track.onunmute = checkVideo;
|
||||||
@@ -1437,9 +1440,7 @@ export default function CallModal({ isOpen, onClose, targetUser, callType: initi
|
|||||||
<PhoneOff size={14} />
|
<PhoneOff size={14} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/* Hidden remote video/audio elements for background processing */}
|
{/* No hidden elements here - they are managed in the main content area */}
|
||||||
<video ref={remoteVideoRef} autoPlay playsInline muted className="hidden" />
|
|
||||||
<audio ref={remoteAudioRef} autoPlay className="hidden" />
|
|
||||||
</motion.div>
|
</motion.div>
|
||||||
) : (
|
) : (
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user