(async () => { const globalConnnection = Symbol("grab-canvas-connection") const currentScriptSrc = document.currentScript.src; const sourceElt = document.querySelector("canvas,video"); console.log("Grabbing", sourceElt) if(!sourceElt){ console.error("No canvas found on this page") } const conn = new RTCPeerConnection({ iceServers: [ {urls: ["stun:stun.nextcloud.com:443"]} ] }); const iceCandidates = [] conn.addEventListener("icecandidate", e => { iceCandidates.push(e.candidate) }) const allCandidatesCollected = new Promise(res => conn.addEventListener("icecandidate", e => e.candidate == null && res() )) let captureFn = sourceElt.captureStream; if(!captureFn){ captureFn = sourceElt.mozCaptureStream; } if(sourceElt instanceof HTMLCanvasElement){ captureFn = sourceElt.captureStream.bind(sourceElt) } else { if(sourceElt.mozCaptureStream){ captureFn = sourceElt.mozCaptureStream.bind(sourceElt) } else { captureFn = sourceElt.captureStream.bind(sourceElt) } } const canvasStream = captureFn() const canvasStreamTracks = canvasStream.getVideoTracks() if(canvasStreamTracks.length > 0){ conn.addTrack(canvasStreamTracks[0], canvasStream) } else { throw new Error("Element don't habe video track") } try { const AudioContext = window.AudioContext || window.webkitAudioContext; if(AudioContext){ const audioContext = new AudioContext(); audioContext.createMediaStreamSource(canvasStream) .connect(audioContext.destination) } } catch(e){ console.warn(e) } const offer = await conn.createOffer(); await conn.setLocalDescription(offer); await allCandidatesCollected const res = await fetch(new URL("/_loled/grab-display", currentScriptSrc), { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ offer, iceCandidates }) }) const response = new RTCSessionDescription(await res.json()); conn.setRemoteDescription(response); window[globalConnnection] = conn })()