1 line
16 KiB
JavaScript
Vendored
1 line
16 KiB
JavaScript
Vendored
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6864],{6680:function(e,t,i){"use strict";i.r(t),i.d(t,{OwncastPlayer:function(){return O}});var n=i(85893),s=i(67294),r=i(4480),a=i(74743),l=i(93967),o=i.n(l),h=i(4511),c=i(85215),u=i(37039),d=i(15505),m=i.n(d);i(78210);let g={Play:" (Space)",Pause:" (Space)",Mute:" (m)",Unmute:" (m)",Fullscreen:" (f)","Non-Fullscreen":" (f)","Picture-in-Picture":" (i)","Exit Picture-in-Picture":" (i)"},p=e=>{let{options:t,onReady:i}=e,r=s.useRef(null),a=s.useRef(null),{t:l}=(0,u.$G)(),o=(e,t)=>{let i={};Object.keys(g).forEach(e=>{let t=g[e];i[e]=l("".concat(e).concat(t))}),e.addLanguage(t,i)};return s.useEffect(()=>{if(!a.current){let e=r.current;o(c.Z,"en");let n={...t,noUITitleAttributes:!0},s=a.current=(0,c.Z)(e,n,()=>(console.debug("player is ready"),i&&i(s,c.Z)));s.autoplay(t.autoplay),s.src(t.sources)}},[t,r]),s.useEffect(()=>{c.Z.getPlayer(r.current).on("xhr-hooks-ready",()=>{var e;null===(e=c.Z.getPlayer(r.current).tech({IWillNotUseThisInPlugins:!0}))||void 0===e||e.vhs.xhr.onRequest(e=>{let{uri:t}=e,i=t;if(e.uri.match("m3u8")){let e=t.startsWith("http")?new URL(t):new URL(t,window.location.protocol+window.location.host),n=Math.random().toString(16).slice(2,8);e.searchParams.append("cachebust",n),i=e.toString()}return{...e,uri:i}})})},[]),(0,n.jsx)("div",{"data-vjs-player":!0,children:(0,n.jsx)("video",{ref:r,className:"video-js vjs-big-play-centered vjs-show-big-play-button-on-pause ".concat(m().player," vjs-owncast")})})};class f{start(){this.stop(),this.timer=setInterval(()=>{!function(){try{fetch("/api/ping")}catch(e){console.error(e)}}()},4e3)}stop(){clearInterval(this.timer)}}let y={position:"absolute",width:"100%",height:"100%"},b=e=>{let{src:t="",width:i,height:r,objectFit:a="fill",duration:l="3s",className:o}=e,h=(0,s.useMemo)(()=>({display:"inline-block",position:"relative",width:i,height:r}),[i,r]),c=(0,s.useMemo)(()=>[{...y,objectFit:a,opacity:0,transition:"opacity ".concat(l)},{...y,objectFit:a,opacity:1,transition:"opacity ".concat(l)},{...y,objectFit:a,opacity:0}],[a,l]),[u,d]=(0,s.useState)(0),[m,g]=(0,s.useState)(["",""]),p=t!==m[1]?t:"",f=()=>{d((u+1)%3),g([m[1],p])};return(0,n.jsx)("span",{style:h,className:o,children:[...m,p].map((e,t)=>""!==e&&(0,n.jsx)("img",{src:e,alt:"",style:c[t],onLoad:2===t?f:void 0},e))})};var T=i(73593),v=i.n(T);let k=e=>{let t,{online:i,initialSrc:r,src:a}=e,[l,o]=(0,s.useState)(r),[h,c]=(0,s.useState)("0s");return(0,s.useEffect)(()=>{clearInterval(t),t=setInterval(()=>{"0s"===h&&c("3s"),o("".concat(a,"?").concat(Date.now()))},2e4)},[]),(0,n.jsxs)("div",{className:v().poster,children:[!i&&(0,n.jsx)("img",{src:r,alt:"logo"}),i&&(0,n.jsx)(b,{src:l,duration:h,objectFit:"contain",height:"auto",width:"100%",className:v().image})]})};var w=i(46445),C=i(28049);class P{stop(){clearInterval(this.sendMetricsTimer),this.player.off()}setClockSkew(e){this.clockSkewMs=e}videoJSReady(){let e=this.player.tech({IWillNotUseThisInPlugins:!0});this.supportsDetailedMetrics=!!e,null==e||e.on("usage",e=>{"vhs-unknown-waiting"===e.name&&this.setIsBuffering(!0),"vhs-rendition-change-abr"===e.name&&this.incrementQualityVariantChanges()}),this.player.textTracks().addEventListener("cuechange",()=>{this.incrementQualityVariantChanges()})}handlePlaying(){clearInterval(this.collectPlaybackMetricsTimer),this.collectPlaybackMetricsTimer=setInterval(()=>{this.collectPlaybackMetrics()},5e3)}handleEnded(){clearInterval(this.collectPlaybackMetricsTimer)}handleBuffering(){this.incrementErrorCount(1),this.setIsBuffering(!0)}handleNoLongerBuffering(){this.setIsBuffering(!1)}handleError(){this.incrementErrorCount(1)}incrementErrorCount(e){this.errors+=e}incrementQualityVariantChanges(){if(!this.hasPerformedInitialVariantChange){this.hasPerformedInitialVariantChange=!0;return}this.qualityVariantChanges++}setIsBuffering(e){if(this.isBuffering=e,!e){clearTimeout(this.bufferingDurationTimer);return}this.bufferingDurationTimer=setTimeout(()=>{this.incrementErrorCount(1)},500)}trackSegmentDownloadTime(e){this.segmentDownloadTime.push(e)}trackBandwidth(e){this.bandwidthTracking.push(e)}trackLatency(e){this.latencyTracking.push(e)}collectPlaybackMetrics(){let e=this.player.tech({IWillNotUseThisInPlugins:!0});if(!e||!e.vhs||this.player.paused()||2!==this.player.networkState())return;let t=e.vhs.systemBandwidth;this.trackBandwidth(t);try{let t=function(e){let t;let i=e.vhs.playlists.media(),n=e.currentTime();for(let e=0,s=i.segments.length;e<s;e++)if(n<i.segments[e].end){t=i.segments[e];break}return t||([t]=i.segments),t}(e);if(!t||!t.dateTimeObject)return;let i=t.dateTimeObject.getTime(),n=new Date().getTime()+this.clockSkewMs-i;if(n<0||n/1e3>=100)return;this.trackLatency(n)}catch(e){console.warn(e)}}async send(){let e;if(0===this.segmentDownloadTime.length||!this.player||this.player.paused())return;let t=this.errors;if(this.supportsDetailedMetrics){let i=e=>e.reduce((e,t)=>e+t,0)/e.length,n=i(this.segmentDownloadTime)/1e3;e={bandwidth:Math.round(i(this.bandwidthTracking)/1e3*1e3)/1e3,latency:Math.round(i(this.latencyTracking)/1e3*1e3)/1e3,downloadDuration:Math.round(1e3*n)/1e3,errors:t+(this.isBuffering?1:0),qualityVariantChanges:this.qualityVariantChanges}}else e={errors:t+(this.isBuffering?1:0)};this.errors=0,this.qualityVariantChanges=0,this.segmentDownloadTime=[],this.bandwidthTracking=[],this.latencyTracking=[];let i={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)};try{await fetch("/api/metrics/playback",i)}catch(e){console.error(e)}}constructor(e,t){var i=this;this.player=e,this.supportsDetailedMetrics=!1,this.hasPerformedInitialVariantChange=!1,this.clockSkewMs=0,this.segmentDownloadTime=[],this.bandwidthTracking=[],this.latencyTracking=[],this.errors=0,this.qualityVariantChanges=0,this.isBuffering=!1,this.bufferingDurationTimer=0,this.collectPlaybackMetricsTimer=0,this.videoJSReady=this.videoJSReady.bind(this),this.handlePlaying=this.handlePlaying.bind(this),this.handleBuffering=this.handleBuffering.bind(this),this.handleEnded=this.handleEnded.bind(this),this.handleError=this.handleError.bind(this),this.send=this.send.bind(this),this.collectPlaybackMetrics=this.collectPlaybackMetrics.bind(this),this.handleNoLongerBuffering=this.handleNoLongerBuffering.bind(this),this.sendMetricsTimer=0,this.player.on("canplaythrough",this.handleNoLongerBuffering),this.player.on("error",this.handleError),this.player.on("stalled",this.handleBuffering),this.player.on("waiting",this.handleBuffering),this.player.on("playing",this.handlePlaying),this.player.on("ended",this.handleEnded);let n=t.xhr;t.Vhs.xhr=function(){for(var e=arguments.length,t=Array(e),s=0;s<e;s++)t[s]=arguments[s];if(t[0].uri.match(".ts")){let e=new Date,n=t[1];t[1]=(t,s,r)=>{let a=new Date().getTime()-e.getTime();i.trackSegmentDownloadTime(a),n(t,s,r)}}return n(...t)},this.videoJSReady(),this.sendMetricsTimer=setInterval(()=>{this.send()},1e4)}}class I{setClockSkew(e){this.clockSkewMs=e}check(){if(new Date().getTime()-this.startupTime.getTime()<1e4||this.player.paused()||this.player.seeking()||this.inTimeout||!this.enabled)return;let e=this.player.tech({IWillNotUseThisInPlugins:!0});if(!e||!e.vhs||2!==this.player.networkState())return;let t=0;try{if(0===e.vhs.stats.buffered.length){this.timeout();return}e.vhs.stats.buffered.forEach(e=>{t+=e.end-e.start})}catch(e){console.error(e)}let i=e.vhs.playlists.media().attributes.BANDWIDTH,n=e.vhs.systemBandwidth/i;try{let i=function(e){let t;let i=e.vhs.playlists.media(),n=e.currentTime();for(let e=0,s=i.segments.length;e<s;e++)if(n<i.segments[e].end){t=i.segments[e];break}return t||([t]=i.segments),t}(e);if(!i)return;if(n<1.8&&t<6*i.duration){this.timeout();return}let s=Math.max(4e3,1e3*i.duration*1.8),r=this.bufferedAtLatency.concat([s]),a=r.reduce((e,t)=>e+t,0)/r.length,l=Math.max(1.4*a,Math.min(1e3*i.duration*2.6,15e3));a>=l&&(l=a+3e3);let o=i.dateTimeObject.getTime(),h=new Date().getTime()+this.clockSkewMs-o;if(this.currentLatency=h,Math.abs(h)>8e4){this.timeout();return}if(h>l){if(this.shouldJumpToLive()&&h>l+5e3){let t=h/1e3-3*i.duration,n=this.player.currentTime()+t;console.info("latency",h/1e3,"jumping",t,"to live from ",this.player.currentTime()," to ",n);let s=e.vhs.stats.buffered[0].end,r=e.vhs.stats.buffered[0].start;if(n>r<s){this.jump(n);return}}let t=.33*n;(t=Math.max(Math.min(t,1.08),1))>this.playbackRate+.02&&(t=this.playbackRate+.02),t=Math.round(1e3*t)/1e3,this.start(t)}else h<=a&&this.stop();console.info("latency",h/1e3,"min",a/1e3,"max",l/1e3,"playback rate",this.playbackRate,"enabled:",this.enabled,"running: ",this.running,"skew: ",this.clockSkewMs,"rebuffer events: ",this.bufferingCounter)}catch(e){}}shouldJumpToLive(){return!(this.bufferingCounter>1)&&new Date().getTime()-this.lastJumpOccurred>2e4}jump(e){this.jumpingToLiveIgnoreBuffer=!0,this.performedInitialLiveJump=!0,this.lastJumpOccurred=new Date,console.info("current time",this.player.currentTime(),"seeking to",e),this.player.currentTime(e),setTimeout(()=>{this.jumpingToLiveIgnoreBuffer=!1},5e3)}setPlaybackRate(e){this.playbackRate=e,this.player.playbackRate(e)}start(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;!this.inTimeout&&this.enabled&&e!==this.playbackRate&&(this.running=!0,this.setPlaybackRate(e))}stop(){this.running&&console.log("stopping latency compensator..."),this.running=!1,this.setPlaybackRate(1)}enable(){this.enabled=!0,clearInterval(this.checkTimer),clearTimeout(this.bufferingTimer),this.checkTimer=setInterval(()=>{this.check()},3e3)}disable(){clearInterval(this.checkTimer),clearTimeout(this.timeoutTimer),this.stop(),this.enabled=!1}timeout(){this.jumpingToLiveIgnoreBuffer||(this.inTimeout=!0,this.stop(),clearTimeout(this.timeoutTimer),this.timeoutTimer=setTimeout(()=>{this.endTimeout()},3e4))}endTimeout(){clearTimeout(this.timeoutTimer),this.inTimeout=!1}handlePlaying(){let e=this.playing;this.playing=!0,clearTimeout(this.bufferingTimer),this.enabled&&this.shouldJumpToLive()&&(e||(this.jumpingToLiveIgnoreBuffer=!0,this.player.liveTracker.seekToLiveEdge(),this.lastJumpOccurred=new Date))}handlePause(){this.playing=!1}handleEnded(){this.enabled&&this.disable()}handleError(){this.enabled&&this.timeout()}countBufferingEvent(){if(this.bufferingCounter+=1,this.bufferingCounter>4){this.disable();return}this.bufferedAtLatency.push(this.currentLatency),console.log("latency compensation timeout due to buffering:",this.bufferingCounter,"buffering events of",4),setTimeout(()=>{this.bufferingCounter>0&&(this.bufferingCounter-=1)},18e4)}handleBuffering(){if(this.enabled&&!this.inTimeout){if(this.jumpingToLiveIgnoreBuffer){this.jumpingToLiveIgnoreBuffer=!1;return}this.timeout(),clearTimeout(this.bufferingTimer),this.bufferingTimer=setTimeout(()=>{this.countBufferingEvent()},200)}}constructor(e){this.player=e,this.playing=!1,this.enabled=!1,this.running=!1,this.inTimeout=!1,this.jumpingToLiveIgnoreBuffer=!1,this.timeoutTimer=0,this.checkTimer=0,this.bufferingCounter=0,this.bufferingTimer=0,this.playbackRate=1,this.lastJumpOccurred=null,this.startupTime=new Date,this.clockSkewMs=0,this.currentLatency=null,this.bufferedAtLatency=[],this.player.on("playing",this.handlePlaying.bind(this)),this.player.on("pause",this.handlePause.bind(this)),this.player.on("error",this.handleError.bind(this)),this.player.on("waiting",this.handleBuffering.bind(this)),this.player.on("stalled",this.handleBuffering.bind(this)),this.player.on("ended",this.handleEnded.bind(this)),this.player.on("canplaythrough",this.handlePlaying.bind(this)),this.player.on("canplay",this.handlePlaying.bind(this)),this.check=this.check.bind(this),this.start=this.start.bind(this),this.enable=this.enable.bind(this),this.countBufferingEvent=this.countBufferingEvent.bind(this)}}var B=i(52020),E=i.n(B);class j{static async getVideoQualities(){let e=[];try{let t=await fetch(j.VIDEO_CONFIG_URL);e=await t.json()}catch(e){console.error(e)}return e}}j.VIDEO_CONFIG_URL="/api/video/variants";let x=(0,s.createContext)(j);var M=i(69583);let L="owncast_volume",S="latencyCompensatorEnabled",D=new f,R=null,_=null,N=!1,O=e=>{let{source:t,online:i,initiallyMuted:l=!1,title:c,className:u}=e,d=(0,s.useContext)(x),m=s.useRef(null),[g,f]=(0,r.FV)(C.We),y=(0,r.sJ)(C.g8),b=()=>{try{m.current.volume((0,w.$o)(L)||1)}catch(e){console.warn(e)}},T=()=>{(0,w.qQ)(L,m.current.muted()?0:m.current.volume())},v=()=>{m.current.paused()?m.current.play():m.current.pause()},B=()=>{_&&_.stop(),N=!0,(_=new I(m.current)).setClockSkew(y),_.enable(),(0,w.qQ)(S,!0)},j=()=>{_&&_.disable(),_=null,N=!1,(0,w.qQ)(S,!1)},O=()=>(N?j():B(),N),V=e=>{let t=e.tech({IWillNotUseThisInPlugins:!0});t&&t.vhs&&("true"===(0,w.$o)(S)&&t&&t.vhs?B():j())},J=async(e,t)=>{let i=function(e,t,i,n){let s=t.getComponent("MenuItem"),r=t.getComponent("MenuItem"),a=t.getComponent("MenuButton");class l extends s{createEl(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"button",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=super.createEl(e,t,i);return n.innerHTML='<hr style="opacity: 0.3; margin-left: 10px; margin-right: 10px;" />',n}constructor(e,t){super(e,t)}}let o=new r(e,{selectable:!0,label:"minimize latency (experimental)"});o.on("click",()=>{let e=n();o.selected(e)}),new l(e,{selectable:!1});class h extends a{createItems(){let t;let n=e.tech({IWillNotUseThisInPlugins:!0}),s=new r(e,{selectable:!0,selected:!0,label:"Auto"}),a=Array(i.length);i.forEach(t=>{a[t.index]=new r(e,{selectable:!0,label:t.name})}),t="ontouchstart"in window?"touchend":"click";for(let e=0;e<a.length;e+=1)a[e].on(t,()=>{if(!n){console.warn("Invalid attempt to access null player tech");return}n.vhs.representations().forEach((t,i)=>{let n=i===e;t.enabled(n),a[i].selected(n)}),s.selected(!1)});return s.on(t,()=>{n.vhs.representations().forEach(e=>{e.enabled(!0)}),a.forEach(e=>e.selected(!1)),s.selected(!0)}),i.length,i.length,1===i.length?[]:[s,...a]}constructor(){super(e)}}let c=new h;return c.el().setAttribute("aria-label","Settings"),c.addClass("vjs-quality-selector"),t.registerComponent("MenuButton",h),c}(e,t,await d.getVideoQualities(),O);e.controlBar.addChild(i,{},e.controlBar.children_.length-2),V(e)},A=(e,t)=>{if(window.hasOwnProperty("WebKitPlaybackTargetAvailabilityEvent")){let i=t.getComponent("Button");class n extends i{handleClick(){try{document.getElementsByTagName("video")[0].webkitShowPlaybackTargetPicker()}catch(e){console.error(e)}}constructor(){super(e)}}let s=new n;e.controlBar.addChild(s).addClass("vjs-airplay")}};return(0,a.y1)("space",e=>{e.preventDefault(),v()}),(0,a.y1)("f",()=>{m.current.isFullscreen()?m.current.exitFullscreen():m.current.requestFullscreen()},{enableOnContentEditable:!1}),(0,a.y1)("m",()=>{m.current.muted()||0===m.current.volume()?m.current.volume(.7):m.current.volume(0)},{enableOnContentEditable:!1}),(0,a.y1)("0",()=>m.current.volume(m.current.volume()+.1),{enableOnContentEditable:!1}),(0,a.y1)("9",()=>m.current.volume(m.current.volume()-.1),{enableOnContentEditable:!1}),(0,s.useEffect)(()=>{R&&R.setClockSkew(y)},[y]),(0,s.useEffect)(()=>()=>{j(),null==R||R.stop()},[]),(0,n.jsx)(h.SV,{fallbackRender:e=>{let{error:t,resetErrorBoundary:i}=e;return(0,n.jsx)(M.A,{componentName:"OwncastPlayer",message:t.message,retryFunction:i})},children:(0,n.jsxs)("div",{className:o()(E().container,u),id:"player",children:[i&&(0,n.jsx)("div",{className:E().player,children:(0,n.jsx)(p,{options:{autoplay:!1,controls:!0,responsive:!0,fluid:!1,fill:!0,playsinline:!0,liveui:!0,preload:"auto",muted:l,controlBar:{progressControl:{seekBar:!1}},html5:{vhs:{enableLowInitialPlaylist:!0,experimentalBufferBasedABR:!0,useNetworkInformationApi:!0,maxPlaylistRetries:30}},liveTracker:{trackingThreshold:0,liveTolerance:15},sources:[{src:t,type:"application/x-mpegURL"}]},onReady:(e,t)=>{m.current=e,b(),A(e,t),e.on("waiting",()=>{console.debug("player is waiting")}),e.on("dispose",()=>{console.debug("player will dispose"),D.stop()}),e.on("playing",()=>{console.debug("player is playing"),D.start(),f(!0)}),e.on("pause",()=>{console.debug("player is paused"),D.stop(),f(!1)}),e.on("ended",()=>{console.debug("player is ended"),D.stop(),f(!1)}),t.hookOnce(),e.on("volumechange",T),(R=new P(e,t)).setClockSkew(y),J(e,t)},"aria-label":c})}),(0,n.jsx)("div",{className:E().poster,children:!g&&(0,n.jsx)(k,{online:i,initialSrc:"/thumbnail.jpg",src:"/thumbnail.jpg"})})]})})}},52020:function(e){e.exports={container:"OwncastPlayer_container__CR5Ry",player:"OwncastPlayer_player__dCDjy",poster:"OwncastPlayer_poster__tbpwE"}},15505:function(e){e.exports={player:"VideoJS_player__GD36e"}},73593:function(e){e.exports={poster:"VideoPoster_poster__6rnLj",image:"VideoPoster_image__8kRcw"}},25893:function(){}}]); |