61 lines
2.7 KiB
HTML
61 lines
2.7 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>直播 SFU 分流 Demo</title>
|
||
<link rel="stylesheet" href="/static/styles.css" />
|
||
</head>
|
||
<body>
|
||
<div class="topbar">
|
||
<div class="brand">直播 SFU 分流 Demo <small>Cloudflare Realtime · SRS</small></div>
|
||
<nav>
|
||
<a href="/publish">开始直播</a>
|
||
<a href="/watch">观看直播</a>
|
||
<a href="/login">登录</a>
|
||
<span id="navAuth" class="muted" style="margin-left:12px;"></span>
|
||
</nav>
|
||
</div>
|
||
<div class="band">
|
||
<div class="hero">
|
||
<h1>一路推流,多路扇出</h1>
|
||
<p>基于 GOSpeak 技术栈的直播 SFU 分流演示。控制面用 protobuf/gRPC 定义,主 SFU 为
|
||
<b>Cloudflare Realtime</b>,<b>SRS</b> 作为本地对照后端。同一路发布可同时落到多条分发链路,观众任选后端拉流。</p>
|
||
</div>
|
||
<div class="grid">
|
||
<div class="card">
|
||
<h3>进入房间</h3>
|
||
<div class="row">
|
||
<input type="text" id="room" placeholder="房间名,例如 demo" />
|
||
<button onclick="goPublish()">开始直播</button>
|
||
<button class="secondary" onclick="goWatch()">观看直播</button>
|
||
</div>
|
||
<div class="muted" style="margin-top:10px">提示:推流与观看使用同一房间名即可配对。需先登录(默认 admin/Admin123! / publisher/Publisher123! / viewer/Viewer123!)。</div>
|
||
</div>
|
||
<div class="card">
|
||
<h3>后端能力</h3>
|
||
<div id="backends" class="targets"><span class="muted">加载中…</span></div>
|
||
<div class="muted" style="margin-top:10px">Cloudflare Realtime 需在 <code>.env</code> 配置 <code>CF_APP_ID</code> / <code>CF_APP_SECRET</code>;
|
||
SRS 由本地 <code>docker compose up -d srs</code> 提供。</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script src="/static/app.js"></script>
|
||
<script>
|
||
LiveSFU.loadConfig(document.getElementById('backends'));
|
||
LiveSFU.authCheck().then(chk=>{
|
||
const el=document.getElementById('navAuth');
|
||
if(chk.authenticated){ el.textContent='已登录:'+chk.username+'/'+chk.role; const a=document.createElement('a'); a.href='#'; a.textContent=' 退出'; a.onclick=()=>{LiveSFU.clearToken(); location.reload();}; el.appendChild(a); } else { el.innerHTML='<a href="/login">未登录,点击登录</a>'; }
|
||
});
|
||
function goPublish() {
|
||
const r = document.getElementById('room').value.trim() || 'demo';
|
||
location.href = '/publish?room=' + encodeURIComponent(r);
|
||
}
|
||
function goWatch() {
|
||
const r = document.getElementById('room').value.trim() || 'demo';
|
||
location.href = '/watch?room=' + encodeURIComponent(r);
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|