!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e.SENTRY_RELEASE={id:"substack@538433c"};var r=(new e.Error).stack;r&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[r]="b2c7813d-5c3f-475d-9f9a-82d866398af7",e._sentryDebugIdIdentifier="sentry-dbid-b2c7813d-5c3f-475d-9f9a-82d866398af7")}catch(e){}}();"use strict";(self.webpackChunksubstack=self.webpackChunksubstack||[]).push([["95127"],{59690:function(e,r,t){t.d(r,{F:()=>T});var n=t(79785),o=t(4006),a=t(13369),c=t(88007),l=t(7611),i=t(45773),u=t(17402),s=t(84605),d=t(85478),f=t(46271),p=t(57820),m=t(63136),_=t(66511),g=t(69277),k=t(86500);async function h(){let e=Date.now();try{let r=await fetch("https://www.cloudflare.com/cdn-cgi/trace");if(!r.ok)return null;let t=Date.now(),n=await r.text(),o=function(e){let r;for(let t of e.split("\n")){let[e,n]=t.split("=");if("ts"===e&&n){r=1e3*parseFloat(n);break}}return void 0===r||isNaN(r)?null:{ts:r}}(n);if(!o)return null;return{localTimeBefore:e,serverTime:o.ts,localTimeAfter:t,rtt:t-e}}catch(e){return null}}function b(e){let r=e.localTimeBefore+e.rtt/2;return e.serverTime-r}async function w(){var e,r,t;let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:5,o=[];for(let e=0;esetTimeout(e,100))}if(0===o.length)throw Error("Time synchronization failed: no successful samples collected");let a=o.map(b);a.sort((e,r)=>e-r);let c=Math.floor(a.length/2),l=a.length%2==0?((null!=(e=a[c-1])?e:0)+(null!=(r=a[c])?r:0))/2:null!=(t=a[c])?t:0,i=o.map(e=>e.rtt);return{offset:Math.round(l),accuracy:Math.round(Math.max((i.length>0?Math.min(...i):0)/2,(a.length>0?Math.max(...a)-Math.min(...a):0)/2)),samples:o.length}}function y(e){return Date.now()+e}let E=["video/webm;codecs=av01,opus","video/mp4;codecs=av01,mp4a.40.2","video/webm;codecs=vp9,opus","video/mp4;codecs=hvc1,mp4a.40.2","video/mp4;codecs=hevc,mp4a.40.2","video/webm;codecs=h264,opus","video/mp4;codecs=avc1,mp4a.40.2","video/webm","video/mp4"];function R(e){return{live_stream_id:e.live_stream_id,worker_instance_id:e.worker_instance_id,worker_user_id:e.worker_user_id,worker_start_timestamp:e.worker_start_timestamp,worker_time_offset:e.worker_time_offset}}function v(){let e=(0,n._)(["Uploading high-res video: (","%)"]);return v=function(){return e},e}function S(){let e=(0,n._)(["High-res upload error: ",""]);return S=function(){return e},e}function T(e){var r,t,n;let{liveStreamId:h,onBackgroundRecordingUpdate:b}=e,T=(0,a.mP)(),C=(0,f.Jd)(),{getConfigFor:I}=(0,d.mJ)(),{iString:A,iTemplate:F}=(0,s.GO)(),[D,M]=(0,u.useState)(null),[U,x]=(0,u.useState)(null),[P,N]=(0,u.useState)(null),O=(0,u.useRef)(!1),H=!!I("enable_high_res_background_uploading"),{progress:L,start:Y,stop:z}=function(e){let{enabled:r,liveStreamId:t,userId:n,localVideoTrack:o,localAudioTrack:a,connectionQuality:c}=e,{getProxyStream:l}=function(e){let{localVideoTrack:r,localAudioTrack:t}=e,n=(0,u.useRef)(null),[o,a]=(0,u.useState)(!1),c=(0,u.useRef)(0),l=(0,u.useRef)(0),i=(0,u.useRef)(null),s=(0,u.useRef)(null),d=(0,u.useCallback)(()=>{if(n.current)return n.current;let e=document.createElement("canvas");e.width=1920,e.height=1080;let r=e.getContext("2d");if(!r)throw Error("Failed to get 2d context for proxy recording canvas");r.fillStyle="black",r.fillRect(0,0,e.width,e.height);let t=document.createElement("video");t.muted=!0,t.playsInline=!0;let o=new AudioContext,c=o.createMediaStreamDestination(),l=e.captureStream(30).getVideoTracks()[0],i=c.stream.getAudioTracks()[0];if(!l||!i)throw Error("Failed to initialize proxy media stream tracks");let u={canvas:e,canvasCtx:r,videoEl:t,audioContext:o,audioDestination:c,stream:new MediaStream([l,i])};return n.current=u,a(!0),u},[]),f=(0,u.useCallback)(()=>d().stream,[d]);return(0,u.useEffect)(()=>{let e=n.current;if(!e)return;let{canvas:t,canvasCtx:o,videoEl:a}=e;if(cancelAnimationFrame(c.current),r){let e=()=>{var e;let t=r.mediaStreamTrack,n=a.srcObject instanceof MediaStream?a.srcObject:null;(null!=(e=null==n?void 0:n.getVideoTracks()[0])?e:null)!==t&&(a.srcObject=new MediaStream([t]),a.play().catch(e=>{console.warn("Failed to play proxy video track",e)}))};e();let n=()=>{if(e(),a.readyState>=a.HAVE_CURRENT_DATA)try{o.drawImage(a,0,0,t.width,t.height)}catch(e){o.fillStyle="black",o.fillRect(0,0,t.width,t.height)}else o.fillStyle="black",o.fillRect(0,0,t.width,t.height);c.current=requestAnimationFrame(n)};c.current=requestAnimationFrame(n)}else{a.srcObject=null;let e=12,r=()=>{o.fillStyle="black",o.fillRect(0,0,t.width,t.height),--e>0&&(c.current=requestAnimationFrame(r))};c.current=requestAnimationFrame(r)}return()=>{cancelAnimationFrame(c.current)}},[r,o]),(0,u.useEffect)(()=>{let e=n.current;if(!e)return;let{audioContext:r,audioDestination:o}=e;if(cancelAnimationFrame(l.current),t){let e=()=>{let e=t.mediaStreamTrack;if(s.current===e)return;i.current&&(i.current.disconnect(),i.current=null),s.current=null,"suspended"===r.state&&r.resume().catch(e=>{console.warn("Failed to resume proxy audio context",e)});let n=r.createMediaStreamSource(new MediaStream([e]));n.connect(o),i.current=n,s.current=e};e();let n=()=>{e(),l.current=requestAnimationFrame(n)};l.current=requestAnimationFrame(n)}else i.current&&(i.current.disconnect(),i.current=null),s.current=null;return()=>{cancelAnimationFrame(l.current),i.current&&(i.current.disconnect(),i.current=null),s.current=null}},[t,o]),(0,u.useEffect)(()=>()=>{cancelAnimationFrame(c.current),cancelAnimationFrame(l.current),i.current&&i.current.disconnect();let e=n.current;e&&(e.videoEl.srcObject=null,e.audioContext.close().catch(e=>{console.warn("Failed to close proxy audio context",e)}),e.stream.getTracks().forEach(e=>e.stop()))},[]),{getProxyStream:f}}({localVideoTrack:o,localAudioTrack:a}),[i,s]=(0,u.useState)("waiting_for_init"),[d,f]=(0,u.useState)(),[p,m]=(0,u.useState)("waiting_for_init"),[_,h]=(0,u.useState)(0),b=(0,u.useRef)(null),v=(0,u.useRef)(null),S=(0,u.useRef)(0),T=(0,u.useRef)(0),C=(0,u.useRef)(0),I=(0,u.useRef)(Promise.resolve()),A=(0,u.useMemo)(()=>({live_stream_id:t,worker_user_id:n}),[t,n]),F=(0,u.useCallback)(e=>{var r;(0,k.u4)(k.qY.LIVE_STREAM_HIGH_RES_RECORDING_UPDATED,(0,g._)({source:"message_to_worker",messageType:e.type},A)),null==(r=b.current)||r.postMessage(e,"WRITE_CHUNK"===e.type?[e.data]:[])},[A]),D=(0,u.useCallback)(e=>{let r=e.data;(0,k.u4)(k.qY.LIVE_STREAM_HIGH_RES_RECORDING_UPDATED,(0,g._)({action:"message_from_worker",messageType:r.type},R(r)));let t=r.type;switch(t){case"INIT_SUCCESS":s("recording");break;case"INIT_ERROR":case"FINALIZE_ERROR":s("error"),f(r.error);break;case"CHUNK_WRITE_ERROR":console.error("Chunk write error:",r.error);break;case"CHUNK_UPLOAD_ERROR":console.error("Chunk upload error:",r.error);break;case"FINALIZE_SUCCESS":s("complete");break;case"STATUS":m(r.status.backgroundUploadState),h(r.status.percentComplete);break;case"FIRE_EVENT":(0,k.u4)(k.qY.LIVE_STREAM_HIGH_RES_RECORDING_UPDATED,(0,g._)({source:"event_message_to_worker",messageType:r.type,workerAction:r.action},R(r),r.props));break;default:console.warn("Unknown message type from worker:",t)}},[]),M=(0,u.useCallback)(async()=>{if(!r||"waiting_for_init"!==i)return;if(!("undefined"!=typeof navigator&&"storage"in navigator&&"function"==typeof navigator.storage.getDirectory&&"undefined"!=typeof Worker&&"undefined"!=typeof MediaRecorder))return void console.warn("High-res recording not supported in this browser");let e=function(){for(let e of E)if(MediaRecorder.isTypeSupported(e))return e;return null}();if(!e)return void console.warn("No supported MIME type for MediaRecorder");s("initializing"),m("preparing_background_upload"),f(void 0),C.current=0;try{T.current=(await w()).offset,S.current=y(T.current);let r=new Worker("/high_res_uploader_worker.js",{type:"module"});r.onmessage=D,r.onerror=e=>{console.error("HighResUploaderWorker error:",e),s("error"),f(e.message)},b.current=r,F({type:"INIT",liveStreamId:t,userId:n,startTimestamp:S.current,timeOffset:T.current,codec:e});let o=l(),a=new MediaRecorder(o,{mimeType:e,videoBitsPerSecond:4e7,audioBitsPerSecond:256e3});a.ondataavailable=async e=>{if(e.data.size>0){let r=I.current.then(async()=>{let r=await e.data.arrayBuffer(),t=y(T.current);F({type:"WRITE_CHUNK",chunkIndex:C.current,data:r,timestamp:t}),C.current++}).catch(e=>{console.error("Error processing chunk:",e)});I.current=r}},a.onerror=e=>{console.error("MediaRecorder error:",e),s("error"),f("MediaRecorder error")},a.onstop=()=>{I.current.finally(()=>{s("finalizing"),F({type:"RECORDING_STOPPED",expectedChunkCount:C.current})})},v.current=a,a.start(1e4)}catch(e){console.error("Failed to start recording:",e),s("error"),f(e instanceof Error?e.message:"Failed to start recording")}},[r,i,t,n,F,D,l]),U=(0,u.useCallback)(async()=>{"recording"===i&&(s("stopping"),v.current&&"inactive"!==v.current.state&&v.current.stop())},[i]);return(0,u.useEffect)(()=>{"recording"===i&&c&&F({type:"SET_UPLOAD_PAUSED",paused:"poor"===c||"lost"===c})},[c,i,F]),(0,u.useEffect)(()=>()=>{v.current&&"inactive"!==v.current.state&&v.current.stop(),b.current&&b.current.terminate()},[]),{progress:(0,u.useMemo)(()=>({backgroundUploadState:p,isComplete:"background_upload_complete"===p||"background_upload_error"===p,percentComplete:_,error:d}),[p,_,d]),start:M,stop:U}}({enabled:H,liveStreamId:h,userId:null!=(r=null==C?void 0:C.id)?r:0,localVideoTrack:D,localAudioTrack:U,connectionQuality:P});(0,u.useEffect)(()=>{if(!T||!H)return;let e=()=>{let e=null;for(let r of T.localParticipant.videoTrackPublications.values())if(r.track){e=r.track;break}let r=null;for(let e of T.localParticipant.audioTrackPublications.values())if(e.track){r=e.track;break}M(e),x(r)},r=(e,r)=>{r.isLocal&&N(e)},t=null,n=()=>{e(),null!==t&&clearTimeout(t),t=setTimeout(()=>{t=null,e()},0)};return e(),T.on(c.RoomEvent.LocalTrackPublished,n),T.on(c.RoomEvent.LocalTrackUnpublished,n),T.on(c.RoomEvent.ConnectionQualityChanged,r),()=>{null!==t&&clearTimeout(t),T.off(c.RoomEvent.LocalTrackPublished,n),T.off(c.RoomEvent.LocalTrackUnpublished,n),T.off(c.RoomEvent.ConnectionQualityChanged,r)}},[T,H]),(0,u.useEffect)(()=>{H&&!O.current&&"waiting_for_init"===L.backgroundUploadState&&(O.current=!0,Y().catch(e=>{console.error("Failed to start high-res recording:",e)}))},[H,L.backgroundUploadState,Y]),(0,u.useEffect)(()=>{if(!T||!H)return;let e=()=>{z().catch(e=>{console.error("Failed to stop high-res recording:",e)})};return T.on(c.RoomEvent.Disconnected,e),()=>{T.off(c.RoomEvent.Disconnected,e)}},[T,H,z]),(0,u.useEffect)(()=>{null==b||b({progress:L})},[b,L]);let q=L.backgroundUploadState,G=function(e){let{percentComplete:r,backgroundUploadState:t}=e;switch(t){case"preparing_background_upload":return(0,o.Y)(p.y$,{size:14,padding:0});case"background_upload_in_progress":return(0,o.FD)(m.EY,{children:[r.toFixed(0),"%"]});case"background_upload_paused":return(0,o.Y)(l.A,{size:14,style:{color:"var(--color-utility-success)"}});case"background_upload_complete":return(0,o.Y)(i.A,{size:14,style:{color:"var(--color-utility-success)"}});case"background_upload_error":return(0,o.Y)(i.A,{size:14,style:{color:"var(--color-utility-danger)"}});case"waiting_for_init":return null;default:return console.warn("Unknown background upload state: ".concat(t)),null}}({percentComplete:L.percentComplete,backgroundUploadState:q});if(!G)return null;let V={waiting_for_init:A("Getting ready..."),preparing_background_upload:A("Preparing backup..."),background_upload_paused:A("High-res upload paused - poor connection"),background_upload_in_progress:F(v(),L.percentComplete.toFixed(0)),background_upload_complete:A("High-res upload complete"),background_upload_error:F(S(),null!=(t=L.error)?t:"Unknown error")};return(0,o.Y)(_.m_,{text:null!=(n=V[q])?n:"",side:"bottom",children:(0,o.Y)("div",{style:{display:"flex",alignItems:"center",gap:4,padding:"4px 8px",borderRadius:4,background:"rgba(0,0,0,0.6)",cursor:"default",zIndex:10},children:G})})}}}]);