146 lines
4.7 KiB
TypeScript
146 lines
4.7 KiB
TypeScript
/**
|
||
* 云手机课程章节详情配置(克隆自 nomadlms)
|
||
*/
|
||
|
||
const SAMPLE_VIDEO = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
|
||
|
||
const SAMPLE_MARKDOWN = `# 课程概述
|
||
|
||
本小节将带你理解云手机的核心概念,掌握低成本工作室搭建技能。
|
||
|
||
## 学习目标
|
||
|
||
- 理解云手机的本质与自建方案
|
||
- 掌握 Redroid、AOSP 等虚拟化技术
|
||
- 完成无人直播推流配置
|
||
|
||
## 核心要点
|
||
|
||
1. **定义**:云手机 = 虚拟化安卓 + 远程控制 + 自动化推流
|
||
2. **技术**:Docker Redroid、ARM 开发板、ffmpeg、SRS
|
||
3. **成本**:自建单台成本可控制在千元以内
|
||
|
||
## 行动清单
|
||
|
||
- [ ] 评估自己的硬件与网络环境
|
||
- [ ] 列出想实现的直播平台(TikTok/Youtube 等)
|
||
- [ ] 设定 1 个月内的搭建目标
|
||
|
||
### 代码示例
|
||
|
||
\`\`\`bash
|
||
# 启动 Redroid 容器
|
||
docker run -itd --privileged \\
|
||
-v ~/data:/data \\
|
||
redroid/redroid:13.0.0-latest
|
||
\`\`\`
|
||
|
||
行内代码示例:\`ffmpeg -re -i input.mp4 -c copy -f flv rtmp://server/live\` 可推流到 RTMP 服务器。
|
||
|
||
## 注意事项
|
||
|
||
> 云手机自建需要一定技术基础,建议先完成前 2 节试看再决定是否购买。
|
||
|
||
| 项目 | 说明 |
|
||
|------|------|
|
||
| 硬件 | 建议 ARM 开发板或 x86 主机 |
|
||
| 网络 | 需科学上网与静态 IP |
|
||
| 时间 | 完整搭建约 1-2 天 |
|
||
`;
|
||
|
||
export type LessonDetail = {
|
||
name: string;
|
||
duration: string;
|
||
videoUrl: string;
|
||
markdown: string;
|
||
};
|
||
|
||
export const LESSONS_MAP: Record<string, LessonDetail> = {
|
||
"0-0": {
|
||
name: "01 什么是云手机?自建 vs 商业平台",
|
||
duration: "08:32",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "云手机定义与自建 vs 商业平台对比"),
|
||
},
|
||
"0-1": {
|
||
name: "02 低成本工作室硬件选型",
|
||
duration: "12:15",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "开发板、采集卡、配件选型"),
|
||
},
|
||
"1-0": {
|
||
name: "03 Docker 虚拟化安卓 - Redroid",
|
||
duration: "15:20",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "Redroid 安装与配置"),
|
||
},
|
||
"1-1": {
|
||
name: "04 ARM 开发板 AOSP 系统",
|
||
duration: "18:00",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "AOSP 刷机与系统定制"),
|
||
},
|
||
"1-2": {
|
||
name: "05 相机与推流配置",
|
||
duration: "14:30",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "虚拟相机与 RTMP 推流"),
|
||
},
|
||
"2-0": {
|
||
name: "06 ffmpeg 拉流转推",
|
||
duration: "16:00",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "ffmpeg 拉流与转推"),
|
||
},
|
||
"2-1": {
|
||
name: "07 SRS 直播服务器",
|
||
duration: "12:45",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "SRS 部署与推拉流"),
|
||
},
|
||
"2-2": {
|
||
name: "08 油猴脚本自动化",
|
||
duration: "11:20",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "油猴脚本实现自动化操作"),
|
||
},
|
||
"2-3": {
|
||
name: "09 TikTok/Youtube 实战",
|
||
duration: "20:00",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "TikTok/Youtube 无人直播实战"),
|
||
},
|
||
"3-0": {
|
||
name: "10 软路由与科学上网",
|
||
duration: "13:00",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "软路由配置与科学上网"),
|
||
},
|
||
"3-1": {
|
||
name: "11 静态住宅 IP 配置",
|
||
duration: "10:30",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "静态住宅 IP 与代理配置"),
|
||
},
|
||
"4-0": {
|
||
name: "12 HDMI 辅助板方案",
|
||
duration: "15:00",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "HDMI 采集与辅助板"),
|
||
},
|
||
"4-1": {
|
||
name: "13 多设备群控与远控",
|
||
duration: "12:00",
|
||
videoUrl: SAMPLE_VIDEO,
|
||
markdown: SAMPLE_MARKDOWN.replace("本小节", "本节").replace("核心概念", "群控与远程控制方案"),
|
||
},
|
||
};
|
||
|
||
export function getLessonKey(moduleIndex: number, lessonIndex: number): string {
|
||
return `${moduleIndex}-${lessonIndex}`;
|
||
}
|
||
|
||
export function getLesson(moduleIndex: number, lessonIndex: number): LessonDetail | null {
|
||
return LESSONS_MAP[getLessonKey(moduleIndex, lessonIndex)] ?? null;
|
||
}
|