function simpleFramwork() { let obj = {}; return new Proxy(obj, { get(_, prop) { const [id, param] = prop.split("_"); let elm = document.getElementById(id); if (!elm) { console.log(`Element with id ${id} not found`); return false; } switch (param) { case "value": return elm.value; case "href": return elm.href; case "style": return elm.getAttribute("style"); case "text": return elm.innerText; case undefined: return elm; } }, set(_, prop, value) { const [id, param] = prop.split("_"); let elm = document.getElementById(id); if (!elm) { console.log(`Element with id ${id} not found`); return false; } switch (param) { case "value": elm.value = value; break; case "href": elm.href = value; break; case "click": elm.addEventListener("click", value); break; case "style": elm.setAttribute("style", value); break; case "text": elm.innerText = value; break; case undefined: break; } return true; }, }); } let sf = simpleFramwork(); sf.streamId_text = "Loading..."; sf.streamURL_text = "Loading..."; let connectToId = new URL(window.location.href).searchParams.get("id"); let bitrate = new URL(window.location.href).searchParams.get("br") || 50000; if (connectToId) { sf.streamURLCont_style = "display:none"; sf.connectToCont_style = "display:block"; sf.connectToID_text = connectToId; } else { sf.streamURLCont_style = "display:block"; sf.connectToCont_style = "display:none"; } var peer = new Peer({ host: window.location.hostname, port: window.location.port, path: "/peerjs", }); function bitrateTransform(sdp) { // return sdp; var arr = sdp.split("\r\n"); arr.forEach((str, i) => { if (/^a=fmtp:\d*/.test(str)) { console.log("found fmtp"); arr[i] = str + `;x-google-max-bitrate=${bitrate};x-google-min-bitrate=0;x-google-start-bitrate=12000`; } else if (/^a=mid:(1|video)/.test(str)) { console.log("found mid"); arr[i] += "\r\nb=AS:" + bitrate; } }); let res = arr.join("\r\n"); console.log(sdp, res); return res; } let currentStream = undefined; let connections = []; function sendStream(id) { const conn = peer.call(id, currentStream, { sdpTransform: bitrateTransform, }); conn.on("stream", console.log); conn.on("close", console.log); conn.on("error", console.log); } if (!connectToId) { sf.startStramBTN_click = () => { navigator.mediaDevices .getDisplayMedia({ video: true, }) .then((stream) => { if (currentStream) { currentStream.getTracks().forEach((track) => track.stop()); } currentStream = stream; let v = sf.localVideo; v.srcObject = stream; v.play(); connections.forEach((id) => { sendStream(id); }); }); }; } peer.on("open", (id) => { console.log("ID", id); sf.streamId_text = id; let url = new URL(window.location.href); url.searchParams.set("id", id); sf.streamURL_text = url.href; sf.streamURL_href = url.href; if (connectToId) { let con = peer.connect(connectToId); con.on("data", console.log); con.on("open", () => con.send("Hello")); } }); peer.on("connection", (conn) => { console.log("connection", conn); conn.on("data", console.log); connections.push(conn.peer); if (currentStream) { sendStream(conn.peer); } }); peer.on("error", console.error); peer.on("close", console.log); peer.on("disconnected", console.log); peer.on("error", console.log); peer.on("call", (call) => { console.log("Call", call); call.answer(undefined); call.on("stream", console.log); call.on("close", console.log); call.on("error", console.log); call.on("stream", (remoteStream) => { console.log("stream", remoteStream); let v = sf.localVideo; v.srcObject = remoteStream; v.play(); }); }); function createEmptyVideoTrack({ width, height }) { const canvas = Object.assign(document.createElement("canvas"), { width, height, }); canvas.getContext("2d").fillRect(0, 0, width, height); const stream = canvas.captureStream(); const track = stream.getVideoTracks()[0]; return Object.assign(track, { enabled: false }); }