55 lines
2.2 KiB
HTML
55 lines
2.2 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>
|
||
</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">提示:推流与观看使用同一房间名即可配对。</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'));
|
||
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>
|