1 line
9.7 KiB
JavaScript
1 line
9.7 KiB
JavaScript
import{A as e,C as t,E as n,H as r,J as i,K as a,M as o,P as s,R as c,W as l,Y as u,_ as d,a as ee,c as f,i as p,k as m,l as h,m as g,n as _,o as v,r as y,t as b,v as x,w as S,x as te}from"./ui-CzB-gjVP.js";import{t as C}from"./cloud-DZf51awA.js";import{a as ne,c as re,d as w,l as ie,o as ae,r as T,s as oe,t as se,u as ce}from"./webrtc-CWAdwVhe.js";import{t as E}from"./message-square-1ZGuav88.js";import{t as D}from"./server-eXVtBH0Y.js";import{t as O}from"./video-C1co3G53.js";import{a as le}from"./index-D9mHcT7c.js";var k=[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`rect`,{x:`9`,y:`9`,width:`6`,height:`6`,rx:`1`,key:`1ssd4o`}]],ue=e=>c(x,a(e,{iconNode:k,name:`circle-stop`})),de=m(`<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">选择分发后端,一路推流将扇出到所选 SFU。</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=m(`<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`),pe=m(`<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</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">`),me=m(`<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">routing</span></div></div><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">推流凭证仅在服务端会话中生效,浏览器端不会出现 SFU 密钥。`),he=m(`<div class="mt-4 grid gap-3 md:grid-cols-2">`),A=m(`<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">fan-out status`),j=m(`<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">`),M=m(`<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)]">`),N=m(`<p class="text-sm text-muted-foreground">正在读取后端配置…`),P=m(`<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="micro-label mt-1.5 text-muted-foreground"> · `),F=m(`<div class="mt-4 border border-dashed border-line px-5 py-8 text-center text-sm text-muted-foreground">尚未开始推流`),I=m(`<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`),L=m(`<p class="mt-2 truncate font-mono text-[10px] text-muted-foreground">session · `),R=m(`<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">`);function z(e){return e===`BACKEND_KIND_CLOUDFLARE`?`Cloudflare Realtime`:e===`BACKEND_KIND_SRS`?`SRS`:e}function ge(e){return e===`BACKEND_KIND_CLOUDFLARE`?C:D}var B=()=>{let a=le({from:`/publish`}),m=()=>a().room,[x,C]=l([]),[k,B]=l({BACKEND_KIND_CLOUDFLARE:!0,BACKEND_KIND_SRS:!0}),[V,H]=l(null),[U,W]=l(!1),[G,K]=l([]),[q,J]=l(``),[Y,_e]=l([]),[X,ve]=l(!0),Z,Q={};u(()=>{d.getConfig().then(e=>C(e.backends||[])).catch(()=>{});let e=re(m(),e=>K(e.targets||[])),t=oe(m(),e=>_e(t=>[...t,e].slice(-100)));i(()=>{e(),t()})});let ye=(e,t)=>{ae(m(),e,t).catch(()=>{})},be=e=>B(t=>({...t,[e]:!t[e]})),xe=async()=>{if(!g.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=x().filter(e=>k()[e.kind]);for(let n of t){let t=await d.publish(m(),n.kind,``);n.kind===`BACKEND_KIND_SRS`?Q.srs=await ne({stream:t.stream,token:t.publish_token,local:e,iceServers:(t.ice_servers||[]).map(T)}):n.kind===`BACKEND_KIND_CLOUDFLARE`&&(Q.cloudflare=await se({sessionId:t.session_id,local:e,iceServers:(t.ice_servers||[]).map(T)}))}}catch(e){J(String(e?.message||e)),W(!1)}},$=async()=>{for(let e of Object.keys(Q)){try{Q[e].close()}catch{}delete Q[e]}for(let e of G())try{await d.stop(m(),e.backend)}catch{}V()&&(V().getTracks().forEach(e=>e.stop()),H(null)),K([]),W(!1)};return i($),(()=>{var i=M(),a=i.firstChild;return t(i,c(h,{get children(){var e=de(),n=e.firstChild,r=n.firstChild;r.firstChild;var i=n.nextSibling,a=i.firstChild;return t(r,m,null),t(i,c(v,{get active(){return U()}}),a),t(a,()=>U()?`推流中 / live`:`待机 / standby`),t(i,c(f,{get active(){return U()}}),null),e}}),a),t(i,c(s,{get when(){return!g.can(`room:publish`)},get children(){return c(b,{tone:`warning`,get children(){return[`当前角色(`,S(()=>g.role()),`)无权发布,仅 admin / publisher 可推流。可切换到「观看」进入房间发弹幕。`]}})}}),a),t(i,c(s,{get when(){return q()},get children(){return c(b,{tone:`error`,get children(){return q()}})}}),a),t(a,c(h,{delay:1,class:`min-w-0`,get children(){var n=pe(),r=n.firstChild,i=r.firstChild,a=i.firstChild,o=i.nextSibling,l=o.firstChild,u=r.nextSibling,d=u.firstChild,f=d.nextSibling,p=u.nextSibling;return t(n,c(ee,{}),r),t(i,c(O,{class:`size-4 text-acid-lime`}),a),t(l,(()=>{var e=S(()=>!!V());return()=>e()?`${V().getVideoTracks().length} 视频 · ${V().getAudioTracks().length} 音频`:`tracks · off`})()),t(o,c(y,{variant:`ghost`,size:`sm`,onClick:()=>ve(e=>!e),get children(){return X()?`隐藏弹幕`:`显示弹幕`}}),null),e(e=>Z=e,d),t(u,c(s,{get when(){return X()},get children(){return c(ce,{messages:Y})}}),f),t(f,c(_,{get variant(){return U()?`success`:`outline`},class:`bg-black/50 shadow-sm backdrop-blur-sm`,get children(){return[c(v,{get active(){return U()}}),S(()=>U()?`LIVE`:`STANDBY`)]}})),t(u,c(s,{get when(){return!V()},get children(){var e=fe(),n=e.firstChild;return t(n,c(O,{class:`size-5`})),e}}),null),t(p,c(y,{class:`h-10`,onClick:xe,get disabled(){return U()||!g.can(`room:publish`)},get children(){return[c(O,{class:`size-4`}),`开始推流`]}}),null),t(p,c(y,{variant:`danger`,class:`h-10`,onClick:$,get disabled(){return!U()},get children(){return[c(ue,{class:`size-4`}),`停止推流`]}}),null),n}}),null),t(a,c(h,{delay:2,class:`min-w-0 self-start`,get children(){var e=me(),n=e.firstChild,i=n.firstChild,a=i.firstChild,l=n.nextSibling;return t(i,c(D,{class:`size-4 text-acid-lime`}),a),t(n,c(_,{variant:`muted`,get children(){return[S(()=>x().length),` 路`]}}),null),t(l,c(s,{get when(){return x().length>0},get fallback(){return N()},get children(){return c(o,{get each(){return x()},children:e=>{let n=ge(e.kind);return(()=>{var i=P(),a=i.firstChild.firstChild,o=a.nextSibling,s=o.firstChild,l=s.firstChild;return t(a,c(n,{class:`size-4`})),t(o,c(p,{get label(){return e.name},get checked(){return!!k()[e.kind]},onChange:()=>be(e.kind),get disabled(){return U()}}),s),t(s,()=>z(e.kind),l),t(s,()=>e.primary?`主 SFU`:`对照后端`,null),t(i,c(_,{get variant(){return e.configured?`success`:`muted`},get children(){return e.configured?`在线`:`未配置`}}),null),r(()=>te(i,`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`}`)),i})()}})}})),e}}),null),t(i,c(h,{delay:1,get children(){var e=A(),i=e.firstChild,a=i.firstChild;return t(i,c(w,{class:`size-4 text-acid-lime`}),a),t(e,c(s,{get when(){return G().length>0},get fallback(){return F()},get children(){var e=he();return t(e,c(o,{get each(){return G()},children:e=>(()=>{var i=R(),a=i.firstChild.nextSibling,o=a.firstChild;return t(o,()=>z(e.backend)),t(a,c(_,{variant:`success`,get children(){return[c(v,{active:!0}),`直播中`]}}),null),t(i,c(s,{get when(){return e.stream},get children(){var i=I(),a=i.firstChild,o=a.firstChild,s=a.nextSibling,l=s.firstChild;return t(a,c(w,{class:`size-3`}),o),t(s,c(w,{class:`size-3`}),l),r(t=>{var r=`/live/${e.stream}.m3u8`,i=`/live/${e.stream}.flv`;return r!==t.e&&n(a,`href`,t.e=r),i!==t.t&&n(s,`href`,t.t=i),t},{e:void 0,t:void 0}),i}}),null),t(i,c(s,{get when(){return e.session_id},get children(){var n=L();return n.firstChild,t(n,()=>e.session_id,null),n}}),null),i})()})),e}}),null),e}}),null),t(i,c(h,{delay:2,get children(){var e=j(),n=e.firstChild,r=n.firstChild,i=r.firstChild,a=n.nextSibling;return t(r,c(E,{class:`size-4 text-acid-lime`}),i),t(n,c(_,{variant:`muted`,get children(){return Y().length}}),null),t(a,c(ie,{messages:Y,get canChat(){return g.can(`room:chat`)},onSend:ye})),e}}),null),i})()};export{B as Publish}; |