--- marp: true theme: default size: 16:9 paginate: true header: "Hightube 开源跨平台个人直播平台" footer: "Highground-Soft | 中期汇报 (v1.0.0-Beta4.7) | 2026.05.05" 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); } ---
已实现从推流鉴权、多码率转码到多端互动观看的全链路闭环。
目标:打造一个开箱即用、性能优异、生态开放的私有化个人直播基座。
--- # 中期成果概览:五大功能域RBAC 权限控制
Bcrypt 密码哈希
JWT 令牌鉴权
会话管理
RTMP 推拉流
FFmpeg 多码率转码
定时缩略图抓取
流状态监控
WebSocket Hub
弹幕遮罩渲染
消息历史持久化
心跳断线重连
系统监控指标
SSE 实时日志流
用户 CRUD 管理
直播间状态面板
Flutter 3.x 跨平台
Windows / Android / iOS / Web
多清晰度无缝切换
累计交付 23 个功能模块,覆盖从注册到直播观看的完整业务生命周期。
--- # 研发数据统计| 模块 | 语言 | 源文件 | 行数 |
|---|---|---|---|
| 后端业务逻辑 | Go | 12 | 1,128 |
| 流媒体服务 | Go | 6 | 613 |
| Flutter 跨平台 | Dart | 15 | 2,761 |
| 管理后台 Web | HTML/JS | 5 | 789 |
| 总计 | - | 38 | 5,291 |
OBS / 移动端推流 → RTMP Server → FFmpeg 转码管线 → Go 业务后端 → Flutter / Web 播放端
| 推流协议 | RTMP (端口 1935) |
| 转码引擎 | FFmpeg 子进程管线 |
| 输出档位 | 1080p 源码 + 720p 转码 |
| Web 分发 | HTTP-FLV (flv.js 播放) |
| 缩略图 | 每 12s 自动截取一帧 |
| HTTP 框架 | Gin — 路由、中间件、CORS |
| 数据库 | SQLite + GORM ORM 抽象 |
| 认证体系 | JWT 签发 + Bcrypt 哈希 |
| 实时通信 | Gorilla WebSocket Hub 模式 |
| 日志推送 | SSE 单向流至管理后台 |
部署方式:Go 编译为单一静态二进制,内嵌 RTMP 模块与前端静态资源,单文件、零依赖即可启动完整服务。
exec.CommandContext 启动子进程。context.Context 树状派生,推流断开时自动 cancel() 级联终止,杜绝僵尸进程。flv.js 解码播放。stream_key,在 URL 路径级 进行实时校验。StreamKey 有效性与归属,推流路径与播放路径分离。IgnorePointer,不拦截底层视频控制栏触摸事件。管理工具:自研嵌入式 Web 控制台,通过 SSE 实时推送系统日志与运行指标,无需额外依赖。
直播间列表采用自适应网格布局,不同屏幕尺寸自动调整列数,保持视觉一致性。
后端每 12s 自动截取一帧封面,前端定时轮询,用户无需进入即可看到实时画面。
"直播中" 角标实时同步房间活跃状态,观众一目了然。
基于 Flutter 3.x 自绘引擎,Windows / Android / iOS / Web 四端共用一套 UI 代码,平台间视觉偏差 < 5%。
支持横竖屏自动切换、双击暂停、进度条拖拽、亮度/音量手势调节(移动端),清晰度菜单一键切换。
gofmt 格式化;前端配置严格 analysis_options.yaml — 拒绝未使用的 import / 变量。| 程景愉 | 后端核心开发、流媒体架构设计与 FFmpeg 转码管线 |
| 舒钰权 | RESTful API 开发、数据库建模、管理后台 |
| 李俊友 | Flutter 播放器核心、WebSocket 实时互动模块 |
| 张钊源 | 跨平台 UI 适配、Android 端推流联调、项目文档 |
经过 30+ 次审查与合并,形成稳定的迭代节奏。
--- # 遇到的挑战与解决方案 | 挑战 | 问题描述 | 解决方案 | 结果 | | :--- | :--- | :--- | :---: | | **RTMP 鉴权** | 默认 RTMP 无认证,任何人可推流 | 路径解析 `stream_key` + 数据库实时验证 | ✅ | | **FFmpeg 僵尸进程** | 推流断开后子进程未回收,内存泄漏 | `context.Context` 树状管理 + `defer cancel()` | ✅ | | **Web 端无法播放** | 浏览器不支持 RTMP 直连 | 增加 HTTP-FLV 封装层,前端接入 `flv.js` | ✅ | | **弹幕拦截触控** | 弹幕层遮挡视频控制栏 | `IgnorePointer` 穿透弹幕层,保留交互 | ✅ | | **跨平台 UI 偏差** | 不同平台渲染效果不一致 | 统一 Material Design 3 规范 + 响应式断点 | ✅ | | **SSE 连接泄漏** | 管理后台长时间挂机导致连接堆积 | 引入心跳超时机制 + 客户端自动重连 | ✅ | --- # 后续计划:迈向 AI 时代| 里程碑 | 时间 | 交付物 |
|---|---|---|
| Beta 4.7 | 2026.05 ✅ | 核心功能 100%,中期汇报 |
| AI 模块初版 | 2026.05 底 | LLM 接口联调 + TTS 集成 |
| v2.0 正式版 | 2026.06 初 | i18n、Docker、AI VTuber、单元测试 |
Thank You
Hightube — 私有化直播基座建设阶段性完成
欢迎老师指正,Q & A
开源地址:https://git.nudt.space/Highground-Soft/Hightube