diff --git a/README.md b/README.md index a026815..3164184 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,10 @@ In order to start the app in audio-only mode initially, provide `noOutgoingVideoInitially` in the query (search) string of the initial URL, e.g. `/index.html?noOutgoingVideoInitially#startCall`. +In order to completely disable incoming and outgoing video, +provide `disableVideoCompletely` in the query string of the URL. +See . + ## Contributing ### Installing Dependencies diff --git a/src/App.tsx b/src/App.tsx index 5dcd924..88ea346 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -21,6 +21,14 @@ export default function App() { const outVidRef = useRef(null); const incVidRef = useRef(null); + const disableVideoCompletelyRef = useRef(null); + if (disableVideoCompletelyRef.current == null) { + disableVideoCompletelyRef.current = location.search.includes( + "disableVideoCompletely", + ); + } + const disableVideoCompletely = disableVideoCompletelyRef.current; + const enableVideoInitiallyRef = useRef(null); if (enableVideoInitiallyRef.current == null) { enableVideoInitiallyRef.current = !location.search.includes( @@ -30,8 +38,9 @@ export default function App() { const enableVideoInitially = enableVideoInitiallyRef.current; const [isOutAudioEnabled, setIsOutAudioEnabled] = useState(true); - const [isOutVideoEnabled, setIsOutVideoEnabled] = + const [isOutVideoEnabled_, setIsOutVideoEnabled] = useState(enableVideoInitially); + const isOutVideoEnabled = disableVideoCompletely ? false : isOutVideoEnabled_; const isOutAudioEnabledRef = useRef(isOutAudioEnabled); isOutAudioEnabledRef.current = isOutAudioEnabled; const isOutVideoEnabledRef = useRef(isOutVideoEnabled); @@ -41,7 +50,7 @@ export default function App() { let stream: MediaStream; try { stream = await navigator.mediaDevices.getUserMedia({ - video: true, + video: !disableVideoCompletely, audio: true, }); } catch (error) { @@ -62,7 +71,7 @@ export default function App() { .forEach((t) => (t.enabled = isOutVideoEnabledRef.current)); return stream; - }, []); + }, [disableVideoCompletely]); const [outStream, setOutStream] = useState(null); useEffect(() => { let outdated = false; @@ -89,6 +98,16 @@ export default function App() { const manager = useMemo(() => { const onIncStream = (incStream: MediaStream) => { + if (disableVideoCompletely) { + incStream.getVideoTracks().forEach((t) => incStream.removeTrack(t)); + incStream.addEventListener("addtrack", (e) => { + if (e.track.kind !== "video") { + return; + } + incStream.removeTrack(e.track); + }); + } + const vid = incVidRef.current!; vid.srcObject = incStream; @@ -108,7 +127,7 @@ export default function App() { playIfPaused(); }; return new CallsManager(outStreamPromise, onIncStream, setState); - }, [outStreamPromise]); + }, [outStreamPromise, disableVideoCompletely]); useEffect(() => { if (outStream == undefined) { @@ -134,7 +153,8 @@ export default function App() { }, [outStream, isOutAudioEnabled, isOutVideoEnabled]); const outStreamHasVideoTrack = - outStream == undefined || outStream.getVideoTracks().length >= 1; + !disableVideoCompletely && + (outStream == undefined || outStream.getVideoTracks().length >= 1); const acceptCall: null | (() => void) = state === "promptingUserToAcceptCall" ? () => manager.acceptCall() : null;