import { useEffect, useRef, useState } from "react"; import axios from "axios"; import { toast } from "react-toastify"; const lines = ["line1"]; // todo: join different combinations of lines based on page params // for now, every browser tab/client joins all 5 lines and streams to one specific one export default function VideoChat() { const [selectedLine, setSelectedLine] = useState(lines[0]); const videoRef = useRef(); const incomingVideoRef = useRef(); const [localMediaStream, setLocalMediaStream] = useState(); // connect to media server for line connections as a broadcaster and consumer useEffect(() => { navigator.mediaDevices .getUserMedia({ video: true, audio: false }) .then((localMediaStream: any) => { console.log("localMediaStream", localMediaStream); console.log(`tracks: `, localMediaStream.getTracks()); setLocalMediaStream(localMediaStream); if (videoRef.current) { toast("got local user video stream"); videoRef.current.srcObject = localMediaStream; // create a unique peer connection to server for each line lines.forEach((lineId) => { // create the peer and add the tranceiver const peer = createPeer(lineId); // peer.onconnectionstatechange = console.log; // console.log(`peer connection for ${lineId}`, peer); // todo: understand this better peer.addTransceiver("video"); // peer.addTransceiver("video", { streams: [localMediaStream] }); // todo: add other tracks like screenshare and such localMediaStream.getTracks().forEach((track: any) => { console.log( `adding track to peer connection: different mediums | audio, video, screen based on selection` ); peer.addTrack(track, localMediaStream); }); }); } }); }, [lines]); const createPeer = (lineId: string) => { const peer = new RTCPeerConnection({ iceServers: [ { urls: "stun:stun.l.google.com:19302", }, ], }); peer.ontrack = handleTrackEvent; peer.onnegotiationneeded = () => handleNegotiationNeededEvent(peer, lineId); return peer; }; const handleNegotiationNeededEvent = async ( peer: RTCPeerConnection, lineId: string ) => { // create offer const offer = await peer.createOffer(); await peer.setLocalDescription(offer); const payload = { sdp: peer.localDescription, }; // send offer to server to accept const { data } = await axios.post( `http://localhost:5000/api/rtc/join/${lineId}`, payload ); // receive server acceptance and set remote configs const desc = new RTCSessionDescription(data.data.sdp); peer.setRemoteDescription(desc).catch((e) => console.log(e)); console.log( `done handling negotiation with media server | remote description: `, desc ); }; // render tracks on the server peer sending something // todo: memoize the line so that we can show user where stream is coming from const handleTrackEvent = (e: any) => { const incomingStream = e.streams[0]; console.log("incoming stream", incomingStream); if (incomingVideoRef.current) { toast(`setting incoming stream ref`); incomingVideoRef.current.srcObject = incomingStream; setInterval(() => { incomingVideoRef!.current!.play().then(console.log).catch(console.log); }, 2000); incomingVideoRef.current.oncanplay = () => console.log("cannn PLLLAYY VID!!!!"); incomingVideoRef.current.play().then(console.log).catch(console.log); } }; return (

This is a baller video app

  1. - user joins 5 lines hardcoded lines (stream to and accept any streams in those lines)
  2. - user can see which line certain content is coming from
  3. - user can set medium: share screen or video (along with audio)
  4. - user can select medium they want to send to
  5. - user hold tilde to stream selected medium in a specific line
  6. - user can receive transmitted stream content from any line, and see which line it's streamed to

Your Video

toggle medium (todo)
); }