--- marp: true theme: default size: 16:9 paginate: true header: "Hightube 开源跨平台个人直播平台最终汇报" footer: "Highground-Soft | 最终汇报 (v1.0.0-Release) | 2026.06.27" style: | :root { --ink: #0f172a; --muted: #475569; --soft: #64748b; --line: rgba(15, 23, 42, 0.10); --blue: #2563eb; --cyan: #0891b2; --gold: #d97706; --paper: #fffdf8; --paper-blue: #f4f8ff; } section { position: relative; padding: 56px 68px 48px; font-family: 'Noto Sans CJK SC', 'Microsoft YaHei', sans-serif; font-size: 28px; line-height: 1.35; color: var(--ink); background: radial-gradient(circle at top right, rgba(37, 99, 235, 0.16), transparent 28%), radial-gradient(circle at bottom left, rgba(8, 145, 178, 0.12), transparent 24%), linear-gradient(135deg, var(--paper) 0%, #f9fbff 45%, var(--paper-blue) 100%); } section::before { content: ""; position: absolute; inset: 22px; border: 1px solid var(--line); border-radius: 26px; pointer-events: none; } header, footer { color: #64748b; font-size: 13px; letter-spacing: 0.04em; } h1 { margin: 0 0 14px; font-family: 'Noto Serif CJK SC', 'STSong', serif; font-size: 52px; color: var(--ink); } h2 { margin: 0 0 14px; font-size: 30px; color: var(--blue); font-weight: 700; } h3 { margin: 0 0 8px; font-size: 22px; color: var(--ink); font-weight: 700; } p, ul, ol { margin-top: 0; } ul, ol { padding-left: 1.15em; } li { margin: 0 0 6px; } table { border-collapse: collapse; table-layout: fixed; } th, td { padding: 5px 8px; vertical-align: top; word-break: break-word; } strong { color: var(--blue); font-weight: 800; } .accent { color: var(--blue); font-weight: 800; } .gold { color: var(--gold); font-weight: 700; } section.cover { color: #e8eefc; background: linear-gradient(135deg, #07111f 0%, #0f1f3d 42%, #1d4ed8 100%); } section.cover h1, section.cover h2, section.cover strong { color: #ffffff; } section.cover .eyebrow { color: rgba(232, 238, 252, 0.78); font-size: 15px; font-weight: 700; letter-spacing: 0.16em; margin-bottom: 16px; } .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; } .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; } .grid-5 { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; } .card { background: rgba(255, 255, 255, 0.72); border: 1px solid rgba(148, 163, 184, 0.18); border-radius: 20px; padding: 20px 22px; box-shadow: 0 16px 38px rgba(15, 23, 42, 0.06); } .card.dark { background: rgba(15, 23, 42, 0.05); } .metric-box { text-align: center; padding: 15px; border-radius: 15px; background: rgba(37, 99, 235, 0.05); } .metric-value { font-size: 36px; font-weight: 800; color: var(--blue); display: block; } .metric-label { font-size: 14px; color: var(--soft); } .tag { display: inline-block; padding: 4px 10px; border-radius: 8px; font-size: 14px; font-weight: 700; background: rgba(37, 99, 235, 0.1); color: var(--blue); margin-right: 5px; } .eyebrow { color: var(--soft); font-size: 15px; font-weight: 700; letter-spacing: 0.16em; margin-bottom: 8px; } .closing { display: grid; place-items: center; height: 80%; text-align: center; } .closing h1 { font-size: 72px; font-weight: 900; margin-bottom: 8px; color: var(--blue); } .toc-item { display: flex; align-items: baseline; padding: 10px 0; border-bottom: 1px solid var(--line); } .toc-num { font-size: 32px; font-weight: 900; color: var(--blue); min-width: 56px; } .toc-text { font-size: 22px; } .toc-sub { font-size: 15px; color: var(--soft); } section.compact { padding: 46px 58px 40px; font-size: 24px; line-height: 1.25; } section.compact h1 { font-size: 42px; margin-bottom: 10px; } section.compact h3 { font-size: 19px; margin-bottom: 6px; } section.compact .card { padding: 14px 16px; border-radius: 16px; } section.compact .grid-2 { gap: 14px; } section.compact .grid-3 { gap: 12px; } section.compact li { margin-bottom: 4px; } section.compact .tag { font-size: 12px; padding: 3px 8px; } section.compact p[style], section.compact ul[style], section.compact ol[style], section.compact table[style] { font-size: 14px !important; } section.toc-slide h1 { font-size: 46px; margin-bottom: 10px; } section.toc-slide .toc-item { padding: 7px 0; } section.toc-slide .toc-num { font-size: 27px; min-width: 48px; } section.toc-slide .toc-text { font-size: 19px; } section.toc-slide .toc-sub { font-size: 13px; } section.arch-slide table { font-size: 14px !important; } section.arch-slide th, section.arch-slide td { padding: 4px 6px; } section.challenge-slide table { font-size: 16px; line-height: 1.26; } section.challenge-slide th, section.challenge-slide td { padding: 7px 9px; } section.challenge-slide h1 { margin-bottom: 8px; } section.plan-slide table { font-size: 14px !important; } section.plan-slide .card ul { margin-bottom: 0; } section.showcase-slide .card h3 { color: var(--blue); } ---
已实现从高并发流引擎、后端性能优化到多端自适应拉流与公网部署的完整闭环。
目标:打造一个开箱即用、极速轻量、安全可控的跨平台私有化直播基座。
--- # 系统架构总览OBS / 移动端推流 → RTMP Server → FFmpeg 转码管线 → Go 业务后端 → Flutter / Web 播放端
| 推流监听 | RTMP 协议 (端口 1935) |
| 流鉴权 | URL 路径 stream_key 数据库实时匹配 |
| 转码引擎 | FFmpeg 子进程异步管线 (原始/720p/480p) |
| Web 分发 | HTTP-FLV (低延迟 chunked 长连接) |
| 封面捕获 | 定时抓取脚本,每 12s 生成一张房间缩略图 |
| Web 框架 | Gin — 路由控制、CORS 过滤、健康监测 |
| ORM / 数据库 | GORM + SQLite (嵌入式轻量级持久化) |
| 安全体系 | JWT 访问令牌 + Bcrypt 密码单向哈希 |
| 互动接口 | Gorilla WebSocket Hub 模式弹幕服务器 |
| 管理后台 | 自研 Web 后台,基于 SSE 异步日志滚动 |
部署核心:客户端(Flutter)与服务端(Go)完全分离,结合 Docker 容器化一键部署。
--- # 后端性能优化:三驾马车 (重点) 为了解决直播系统高并发读写下 SQLite 数据库锁死、Socket 写入开销高的问题,设计了三大底层优化:_journal_mode=WAL,读写不互斥,大幅提高并发。synchronous=NORMAL 减半磁盘同步,temp_store=MEMORY 加快临时索引。locked 报错。bufio.NewWriterSize (4KB)。Flush(),延迟 < 1.5s。三项调优相辅相成,使单机并发能力在轻量化环境下呈指数级提升。
--- # 后端性能优化:定量测试成果 (重点) 通过并发压测与物理测量,后端调优取得了极其显著的性能定量数据:| 并发客户端数 | 普通模式 | WAL 调优模式 | 提升幅度 |
|---|---|---|---|
| 1 客户端 | 85 tps | 125 tps | + 47.1% |
| 5 并发 | 18 tps | 240 tps | + 1,233.3% |
| 10 并发 | 9 tps (大量超时) | 380 tps | + 4,122.2% |
* WAL 配合同步 NORMAL 与内存 temp_store,彻底消除了写锁定错误。
| 测试链路 | 追帧关闭 | 追帧开启 | 分析结论 |
|---|---|---|---|
| 同网直连 RTMP | 800 ms | 800 ms | 局域网直连物理延迟极低 |
| 公网 FRP RTMP | 1250 ms | 1250 ms | 穿透引入约 450ms 网络延迟 |
| Web HTTP-FLV | 2600 ms | 1650 ms | 追帧开启后降低 1 秒延迟 |
| 网络抖动积压 | 6200 ms | 1700 ms | 15秒内快速收敛至正常水平 |
利用 FRP 内网穿透 与 Caddy 反向代理,实现零公网 IP 本地服务器的公网安全暴露。
--- # 公网部署方案:隧道穿透与反向代理 (重点)frps (监听 7000),本地内网机 (100.115.45.3) 部署 frpc 建立长连接。/api/* 和 /live/* → 转发至本地 8081
- 默认其他访问 → 转发至本地 8080
HtmlElementView 动态注册 iframe 播放页面 flv_player.html。flv.min.js 本地化部署到项目内,摆脱对外部 CDN 网络连通性的依赖。postMessage 通道,实现 Flutter 主框架到 iframe 播放页面的跨域音量/状态控制。video 元素的 timeupdate 事件,实时计算当前缓冲区延迟。video.currentTime = end - 1.0。
图1:Web 浏览器平台主页(活跃房间列表)
图2:OBS 直播推送与 Web 端低延迟拉流及实时弹幕互动
图3:自研后端管理控制台及系统健康指标
图4:Android 手机客户端直播与聊天室界面
gofmt;Flutter 引入 analysis_options.yaml 开启严苛的静态类型检查与垃圾变量扫描。| 成员 | 职责与主要交付成果 |
|---|---|
| 程景愉 | 后端框架搭建、流媒体解封装、FFmpeg 实时转码通道 |
| 舒钰权 | RESTful 业务逻辑编写、JWT Token 中间件与用户系统 |
| 李俊友 | Flutter 原生播放器对接、WebSocket 实时聊天室、弹幕渲染 |
| 张钊源\n(本人) | 流媒体底座与推流鉴权、Web 端嵌入式 flv.js 播放器与自适应追帧、公网 FRP + Caddy 反向隧道部署 |
https://stream.nudt.space 进行公网拉流。Thank You
Hightube — 开源跨平台个人直播系统项目最终汇报
欢迎老师指正,Q & A
公网体验地址:https://stream.nudt.space
开源地址:https://github.com/Highground-Soft/Hightube