mac-screen-cast 0.3.0

Stream macOS screen to browser over LAN. Zero-copy ScreenCaptureKit, hardware H.264 encoding via VideoToolbox, ~10ms pipeline latency, ~3% CPU.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>{{TITLE}}</title>
<style>
*{margin:0;background:#000}
body{display:flex;min-height:100vh;min-height:100dvh;align-items:center;justify-content:center}
video{width:100%;max-height:100vh;max-height:100dvh}
#b{position:fixed;bottom:0;left:0;right:0;display:flex;gap:12px;padding:3px 10px;background:rgba(0,0,0,.5);color:#aaa;font:11px/1.3 monospace;z-index:99;user-select:none}
.g{color:#4a4}
.r{color:#c44}
</style>
</head>
<body>
<video id=v autoplay muted playsinline></video>
<div id=b><span id=st class=r>{{FPS}}fps connecting</span></div>
<script>
	var v=document.getElementById('v'),st=document.getElementById('st'),pc;
	fetch('/offer').then(r=>r.text()).then(async o=>{
	pc=new RTCPeerConnection();
	pc.ontrack=e=>{v.srcObject=e.streams[0];v.play().catch(()=>{});v.onloadedmetadata=()=>st.className='g'};
	pc.oniceconnectionstatechange=()=>{var s=pc.iceConnectionState;st.textContent='{{FPS}}fps '+s;if(s==='failed')console.log('ICE failed')};
	pc.onicecandidateerror=e=>console.warn('ICE candidate error:',e.errorText||'timeout',e.url||'');
	setInterval(async()=>{
	  try{
	    var lat=await(await fetch('/latency')).text();
	    st.textContent='{{FPS}}fps | '+lat+'ms'
	  }catch(e){}
	},1000);
	var candidates=[];
	pc.onicecandidate=e=>{if(e.candidate)candidates.push({candidate:e.candidate.candidate,sdpMid:e.candidate.sdpMid,sdpMLineIndex:e.candidate.sdpMLineIndex})};
	pc.addTransceiver('video',{direction:'recvonly'});
	await pc.setRemoteDescription({type:'offer',sdp:o});
	var a=await pc.createAnswer();
	await pc.setLocalDescription(a);
	await new Promise(r=>{if(pc.iceGatheringState==='complete')r();else pc.onicegatheringstatechange=ev=>{if(pc.iceGatheringState==='complete')r()}});
	var msg={sdp:a.sdp,candidates:candidates};
	fetch('/signal',{method:'POST',body:JSON.stringify(msg)})
	}).catch(e=>{st.textContent='error: '+e.message;st.className='r'})
	</script>
</body>
</html>