返回项目集
edumotion

Project

edumotion

输入一个知识点,即可自动生成一段带解说字幕和可选配音的教学动画视频(HTML/MP4),将抽象概念转化为直观的动态演示。
平台 GitHub
类型 开源项目
状态 PUBLISHED
更新 2026-07-18 17:13:48
project dossier slug: edumotion owner: bike13 repo: edumotion

EduMotion · 教学动画生成器

输入一个知识点(如「勾股定理」「Dijkstra 算法」),自动生成一段自包含的 HTML5 教学动画,可选叠加 TTS 配音,并导出为 MP4。

项目简介

EduMotion 用大模型把「知识点 → 讲解字幕 → 配音 → 动画 HTML → 录制视频」这条链路自动化。后端 FastAPI + LangGraph 编排,前端 Vue3 单页,浏览器端用 Playwright 录屏、FFmpeg 转码出片。

逻辑简要

生成流程是一条 LangGraph 状态图,含两个人工确认断点(字幕、预览),前端可介入编辑:

生成字幕 → [字幕确认断点] → ┬ 勾选 TTS → 合成配音 → 生成动画(按音频时长计时) → 嵌入音频 ┐
                            └ 未勾选   → 生成动画(单次)                              ┘
                                                    → [HTML 预览断点] → 勾选自动录制 → 录制 → 落库

关键契约与设计:

  • 字幕先行:先由模型产出讲解字幕,再据字幕逐条合成 TTS,测得每条音频真实时长后,才生成与时长匹配的动画 HTML,保证音画同步。
  • 生成 HTML 的 JS 钩子:模型被要求始终输出 showSubtitle(text)(字幕)、await wait(ms)(计时)、markAnimationFinished()(派发 recording:finished 事件,录制端据此停录)。改钩子名需同步改提示词与录制/抽取逻辑。
  • 音画对齐:视觉等待轴(embed_audio_in_html)与合成音轨轴(_build_merged_audio)共用同一间隔公式;导出时按「录屏时长 − 音轨时长」裁掉动画启动前的静止片头,令音画从第 0 帧对齐。
  • 多引擎:OpenAI / Claude / 火山方舟(ark) / Gemini,经预设(preset)配置,可按阶段(字幕/HTML)绑定不同模型。

目录结构

edumotion/            后端主包
├── api/              FastAPI 路由(health / generate / presets / config / history)
├── graph/            LangGraph 状态图:nodes(节点) / pipeline(装配) / state(状态)
├── engines/          多 LLM 引擎适配(openai/claude/ark/gemini + factory)
├── services/         业务服务:字幕匹配、音频嵌入、录制合成、TTS、提示词
├── db/               SQLAlchemy 模型 / 仓储 / 连接
├── config/           设置与日志
└── schemas.py        API 请求/响应模型(Pydantic v2)
frontend/             Vue3 + Vite 单页前端(设置 / 生成 / 进度 / 预览)
scripts/              record_media.py(Playwright 录制+FFmpeg)、e2e_dry/e2e_real
utils/                火山 v3 双向 WebSocket TTS 客户端与二进制协议
app.py                入口:装配 FastAPI、路由、静态、启动建表

技术栈

  • 后端:Python 3.11、FastAPI、Uvicorn、LangGraph、SQLAlchemy 2、Pydantic v2
  • 前端:Vue 3、Pinia、Vite
  • 模型:OpenAI SDK / Anthropic(httpx) / 火山方舟 / google-genai,任意 OpenAI 兼容端点
  • 配音:火山引擎 TTS(豆包 HTTP v1 / v3 双向 WebSocket)
  • 出片:Playwright(Chromium) 录屏 → FFmpeg 转码 MP4/GIF
  • 存储:默认本地 SQLite(可切 MySQL)

启动方式

手动启动

python -m venv .venv && .venv\Scripts\activate     # Windows(或 source .venv/bin/activate)
pip install -r requirements.txt
playwright install chromium                          # 录制所需
playwright install-deps chromium                     # 仅 Linux

cp .env.example .env                                 # 填入 LLM/TTS 凭据

# 前端构建(可选,构建后由后端静态托管;开发时也可 cd frontend && npm run dev 单跑)
cd frontend 
npm install 
npm run build 
npm run dev 

python app.py                                        # 服务于 http://127.0.0.1:8005

Docker

docker-compose up -d                                 # host 端口默认 8005,可用 HOST_PORT 覆盖

镜像内含 FFmpeg、中文字体、Chromium 及依赖;前端在构建阶段一并打包。

配置

复制 .env.example.env。解析优先级:环境变量 → .env

| 变量 | 说明 | |------|------| | DATABASE_URL | 数据库连接串,默认 sqlite:///edumotion.db;切 MySQL 填 mysql+pymysql://... | | DOUBAO_VOICE_APP_ID / DOUBAO_VOICE_API_KEY / DOUBAO_VOICE_TYPE | 豆包 HTTP TTS 凭据与音色 | | TTS_APP_ID / TTS_ACCESS_TOKEN / TTS_VOICE_TYPE / TTS_ENDPOINT | 火山 v3 WebSocket TTS(可选兜底) | | PORT | 服务端口,默认 8001 |

LLM 预设(引擎/base_url/api_key/model)在运行时经 /api/presets 接口管理并持久化,不走 .env

核心接口

所有接口以 /api 为前缀。前端静态页挂在 /,产物目录挂 /output/recordings

| 方法 | 路径 | 功能 | 关键参数 | |------|------|------|----------| | GET | /api/health | 健康检查 | — | | POST | /api/generate | 启动生成(SSE 流),到字幕断点中断 | topic 知识点、target_audience 受众、enable_tts 是否配音、auto_record 是否自动录制 | | POST | /api/generate/{id}/subtitles | 提交编辑后的字幕、继续流程 | subtitles 台词列表、enable_tts | | POST | /api/generate/{id}/revise | 依反馈重生成字幕 | feedback 修改意见 | | POST | /api/generate/{id}/resume | 预览断点后继续 | action = record(录制) | skip(跳过) | | GET | /api/history / /api/history/{id} | 历史列表 / 详情 | — | | GET | /api/history/{id}/download | 下载产物 | — | | DELETE | /api/history/{id} | 删除历史(级联清产物) | — | | GET/PUT | /api/config | 读取 / 更新 TTS 与阶段绑定配置 | tts_*stage_preset_subtitlestage_preset_html | | GET/POST/PUT/DELETE | /api/presets | 模型预设增删改查 | nameengine_type(openai/claude/ark/gemini)、base_urlapi_keymodeltemperaturemax_tokens | | POST | /api/presets/{id}/activate | 启用某预设 | — | | POST | /api/presets/{id}/test | 连通性测试 | 可空字段则沿用已存预设值 |

运行时产物目录

output/(最终 MP4/音频/中间 HTML 与录屏) 均已 gitignore。

API_KEY

API_KEY=sk-PviHWHby3225LjxXY0nzYYLiFSQpuhREG0TgNHktu7eagAfz BASE_URL=https://www.dmxapi.cn

评论