live-sfu-demo/internal/server/static/assets/publish-C8_jmbon.js

1 line
9.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import{C as e,G as t,J as n,L as r,N as i,O as a,S as o,T as s,U as c,V as l,_ as u,a as d,b as f,c as p,g as m,i as ee,j as h,k as te,n as g,p as _,q as v,r as y,s as b,t as x}from"./ui-BjxGELcM.js";import{t as S}from"./cloud-CIOLOOjB.js";import{a as ne,c as re,i as ie,l as ae,n as oe,o as se,s as C,u as w}from"./webrtc-C76mftVq.js";import{t as T}from"./globe-Cy3sFr4f.js";import{t as ce}from"./message-square-DGTwCJY8.js";import{t as E}from"./server-nMqD8oSq.js";import{t as D}from"./video-02fL9iqS.js";import{a as le}from"./index-BsK239Bd.js";var O=[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`rect`,{x:`9`,y:`9`,width:`6`,height:`6`,rx:`1`,key:`1ssd4o`}]],ue=e=>r(u,t(e,{iconNode:O,name:`circle-stop`})),de=a(`<div class="flex flex-wrap items-end justify-between gap-4"><div><p class="mono-label text-muted-foreground">publish / </p><h1 class="display mt-2 text-4xl sm:text-5xl">开始直播</h1><p class="mt-3 max-w-lg text-sm text-muted-foreground">推流仅进入 SRS 主干(WHIP),分发由服务端按配置扇出到多路。</p></div><div class="flex items-center gap-3 border border-line bg-card/60 px-4 py-2.5"><span class=mono-label>`),fe=a(`<div class="pointer-events-none absolute inset-0 flex flex-col items-center justify-center gap-2.5 text-white/60"><span class="flex size-12 items-center justify-center border border-white/20 bg-white/5"></span><span class="micro-label text-white/50">camera off`),k=a(`<div class="relative h-full border border-line bg-card/50 p-4 sm:p-5"><div class="flex flex-wrap items-center justify-between gap-2"><div class="flex items-center gap-2"><h3 class=font-semibold>本地预览</h3><span class="micro-label text-muted-foreground">preview · trunk: </span></div><div class="flex items-center gap-3"><span class="font-mono text-[11px] text-muted-foreground"></span></div></div><div class="relative mt-4 aspect-video overflow-hidden border border-line/70 bg-black"><video autoplay playsinline muted class=size-full></video><div class="pointer-events-none absolute top-3 left-3 flex flex-wrap items-center gap-1.5"></div></div><div class="mt-4 flex flex-wrap gap-2">`),A=a(`<div class="relative border border-line bg-card/50 p-4 sm:p-5"><div class="flex items-center justify-between gap-2"><div class="flex items-center gap-2"><h3 class=font-semibold>分发方式</h3><span class="micro-label text-muted-foreground">distributions</span></div></div><p class="mt-2 text-xs leading-relaxed text-muted-foreground">由服务端按 DISTRIBUTORS 配置自动扇出,推流端无需选择后端。</p><div class="mt-4 space-y-2.5"></div><p class="mt-4 border-t border-line/70 pt-4 text-xs leading-relaxed text-muted-foreground">主干为 SRS,推流凭证仅在服务端会话中生效。`),j=a(`<div class="mt-4 grid gap-3 md:grid-cols-2">`),M=a(`<div class="relative border border-line bg-card/50 p-4 sm:p-5"><div class="flex items-center gap-2"><h3 class=font-semibold>主干状态</h3><span class="micro-label text-muted-foreground">trunk status`),N=a(`<div class="relative border border-line bg-card/50 p-4 sm:p-5"><div class="flex items-center justify-between gap-2"><div class="flex items-center gap-2"><h3 class=font-semibold>房间弹幕 / 聊天</h3><span class="micro-label text-muted-foreground">danmaku</span></div></div><div class="mt-4 h-80 min-h-0">`),P=a(`<div class="mx-auto max-w-[1400px] space-y-5 px-4 py-8 sm:px-6 sm:py-10"><div class="grid gap-4 lg:grid-cols-[minmax(0,1.6fr)_minmax(0,1fr)]">`),F=a(`<p class="text-sm text-muted-foreground">正在读取分发配置…`),I=a(`<div><div class="flex min-w-0 items-center gap-3"><span class="flex size-9 shrink-0 items-center justify-center border border-line bg-background text-foreground/80"></span><div class=min-w-0><p class="text-sm font-medium"></p><p class="micro-label mt-1 text-muted-foreground"> · `),L=a(`<div class="mt-4 border border-dashed border-line px-5 py-8 text-center text-sm text-muted-foreground">尚未开始推流`),R=a(`<div class="mt-3 flex flex-wrap gap-2"><a class=mono-chip target=_blank rel=noreferrer>HLS</a><a class=mono-chip target=_blank rel=noreferrer>FLV`),z=a(`<div class="relative border border-line/80 bg-background/40 p-4"><span class="absolute top-0 left-0 h-3 w-3 border-t-2 border-l-2 border-acid-lime"aria-hidden=true></span><div class="flex items-center justify-between gap-2"><span class="truncate text-sm font-medium">SRS 主干`);function B(e){return e===`DISTRIBUTION_KIND_SRS_HLS`?`SRS HLS 直推`:e===`DISTRIBUTION_KIND_CF_SFU`?`Cloudflare SFU`:e===`DISTRIBUTION_KIND_CDN`?`第三方 CDN`:e}function pe(e){return e===`DISTRIBUTION_KIND_SRS_HLS`?E:e===`DISTRIBUTION_KIND_CF_SFU`?S:e===`DISTRIBUTION_KIND_CDN`?T:E}var V=()=>{let t=le({from:`/publish`}),a=()=>t().room,[u,S]=c([]),[T,O]=c(`SRS`),[V,H]=c(null),[U,W]=c(!1),[G,K]=c([]),[q,J]=c(``),[Y,me]=c([]),[X,he]=c(!0),Z,Q;n(()=>{m.getConfig().then(e=>{S(e.distributors||[]),e.trunk&&O(e.trunk.name||`SRS`)}).catch(()=>{});let e=C(a(),e=>{K(e.targets||[])}),t=se(a(),e=>me(t=>[...t,e].slice(-100)));v(()=>{e(),t()})});let ge=(e,t)=>{ne(a(),e,t).catch(()=>{})},_e=async()=>{if(!_.can(`room:publish`)){J(`当前角色无权发布(需要 room:publish)`);return}J(``),W(!0);try{if(!V()){let e=await navigator.mediaDevices.getUserMedia({video:!0,audio:!0});H(e),Z&&(Z.srcObject=e)}let e=V(),t=await m.publish(a(),`BACKEND_KIND_SRS`,``);Q=await ie({stream:t.stream,token:t.publish_token,local:e,iceServers:(t.ice_servers||[]).map(oe)})}catch(e){J(String(e?.message||e)),W(!1)}},$=async()=>{try{Q?.close()}catch{}Q=void 0;for(let e of G())try{await m.stop(a(),e.backend)}catch{}V()&&(V().getTracks().forEach(e=>e.stop()),H(null)),K([]),W(!1)};return v($),(()=>{var t=P(),n=t.firstChild;return o(t,r(p,{get children(){var e=de(),t=e.firstChild,n=t.firstChild;n.firstChild;var i=t.nextSibling,s=i.firstChild;return o(n,a,null),o(i,r(d,{get active(){return U()}}),s),o(s,()=>U()?`推流中 / live`:`待机 / standby`),o(i,r(b,{get active(){return U()}}),null),e}}),n),o(t,r(i,{get when(){return!_.can(`room:publish`)},get children(){return r(x,{tone:`warning`,get children(){return[`当前角色(`,e(()=>_.role()),`)无权发布,仅 admin / publisher 可推流。可切换到「观看」进入房间发弹幕。`]}})}}),n),o(t,r(i,{get when(){return q()},get children(){return r(x,{tone:`error`,get children(){return q()}})}}),n),o(n,r(p,{delay:1,class:`min-w-0`,get children(){var t=k(),n=t.firstChild,a=n.firstChild,s=a.firstChild,c=s.nextSibling;c.firstChild;var l=a.nextSibling,u=l.firstChild,f=n.nextSibling,p=f.firstChild,m=p.nextSibling,h=f.nextSibling;return o(t,r(ee,{}),n),o(a,r(D,{class:`size-4 text-acid-lime`}),s),o(c,T,null),o(u,(()=>{var t=e(()=>!!V());return()=>t()?`${V().getVideoTracks().length} 视频 · ${V().getAudioTracks().length} 音频`:`tracks · off`})()),o(l,r(y,{variant:`ghost`,size:`sm`,onClick:()=>he(e=>!e),get children(){return X()?`隐藏弹幕`:`显示弹幕`}}),null),te(e=>Z=e,p),o(f,r(i,{get when(){return X()},get children(){return r(ae,{messages:Y})}}),m),o(m,r(g,{get variant(){return U()?`success`:`outline`},class:`bg-black/50 shadow-sm backdrop-blur-sm`,get children(){return[r(d,{get active(){return U()}}),e(()=>U()?`LIVE`:`STANDBY`)]}}),null),o(m,r(g,{variant:`secondary`,class:`border-line bg-black/50 text-white/90 shadow-sm backdrop-blur-sm`,children:`SRS WHIP`}),null),o(f,r(i,{get when(){return!V()},get children(){var e=fe(),t=e.firstChild;return o(t,r(D,{class:`size-5`})),e}}),null),o(h,r(y,{class:`h-10`,onClick:_e,get disabled(){return U()||!_.can(`room:publish`)},get children(){return[r(D,{class:`size-4`}),`开始推流`]}}),null),o(h,r(y,{variant:`danger`,class:`h-10`,onClick:$,get disabled(){return!U()},get children(){return[r(ue,{class:`size-4`}),`停止推流`]}}),null),t}}),null),o(n,r(p,{delay:2,class:`min-w-0 self-start`,get children(){var t=A(),n=t.firstChild,a=n.firstChild,s=a.firstChild,c=n.nextSibling.nextSibling;return o(a,r(E,{class:`size-4 text-acid-lime`}),s),o(n,r(g,{variant:`muted`,get children(){return[e(()=>u().length),` 路`]}}),null),o(c,r(i,{get when(){return u().length>0},get fallback(){return F()},get children(){return r(h,{get each(){return u()},children:e=>{let t=pe(e.kind);return(()=>{var n=I(),i=n.firstChild.firstChild,a=i.nextSibling.firstChild,s=a.nextSibling,c=s.firstChild;return o(i,r(t,{class:`size-4`})),o(a,()=>e.name),o(s,()=>B(e.kind),c),o(s,()=>e.enabled?`已启用`:`未启用`,null),o(n,r(g,{get variant(){return e.configured?`success`:`muted`},get children(){return e.configured?`就绪`:`未配置`}}),null),l(()=>f(n,`flex items-center justify-between gap-3 border p-3 transition-colors ${e.configured?`border-line bg-background/50`:`border-line/60 bg-background/20 opacity-70`}`)),n})()}})}})),t}}),null),o(t,r(p,{delay:1,get children(){var e=M(),t=e.firstChild,n=t.firstChild;return o(t,r(w,{class:`size-4 text-acid-lime`}),n),o(e,r(i,{get when(){return G().length>0},get fallback(){return L()},get children(){var e=j();return o(e,r(h,{get each(){return G()},children:e=>(()=>{var t=z(),n=t.firstChild.nextSibling;return n.firstChild,o(n,r(g,{variant:`success`,get children(){return[r(d,{active:!0}),`直播中`]}}),null),o(t,r(i,{get when(){return e.stream},get children(){var t=R(),n=t.firstChild,i=n.firstChild,a=n.nextSibling,c=a.firstChild;return o(n,r(w,{class:`size-3`}),i),o(a,r(w,{class:`size-3`}),c),l(t=>{var r=`/live/${e.stream}.m3u8`,i=`/live/${e.stream}.flv`;return r!==t.e&&s(n,`href`,t.e=r),i!==t.t&&s(a,`href`,t.t=i),t},{e:void 0,t:void 0}),t}}),null),t})()})),e}}),null),e}}),null),o(t,r(p,{delay:2,get children(){var e=N(),t=e.firstChild,n=t.firstChild,i=n.firstChild,a=t.nextSibling;return o(n,r(ce,{class:`size-4 text-acid-lime`}),i),o(t,r(g,{variant:`muted`,get children(){return Y().length}}),null),o(a,r(re,{messages:Y,get canChat(){return _.can(`room:chat`)},onSend:ge})),e}}),null),t})()};export{V as Publish};