diff --git a/.memory/worklog.json b/.memory/worklog.json
index 11dc02a..2998589 100644
--- a/.memory/worklog.json
+++ b/.memory/worklog.json
@@ -1,19 +1,5 @@
{
"entries": [
- {
- "files_changed": 1,
- "hash": "7665d63",
- "message": "auto-save 2026-05-13 05:22 (~1)",
- "ts": "2026-05-13T05:22:43+08:00",
- "type": "commit"
- },
- {
- "files_changed": 1,
- "hash": "245c104",
- "message": "auto-save 2026-05-13 05:28 (~1)",
- "ts": "2026-05-13T05:28:37+08:00",
- "type": "commit"
- },
{
"files_changed": 1,
"hash": "e56631f",
@@ -3291,6 +3277,19 @@
"type": "session-heartbeat",
"message": "Codex 会话活跃 · 最近命令:codex · 3 项未提交变更 · 最近提交:auto-save 2026-05-14 12:15 (~2)",
"files_changed": 3
+ },
+ {
+ "ts": "2026-05-14T12:20:57+08:00",
+ "type": "commit",
+ "message": "auto-save 2026-05-14 12:20 (~4)",
+ "hash": "df6f0c3",
+ "files_changed": 4
+ },
+ {
+ "ts": "2026-05-14T04:26:11Z",
+ "type": "session-heartbeat",
+ "message": "Codex 会话活跃 · 最近命令:codex · 4 项未提交变更 · 最近提交:auto-save 2026-05-14 12:20 (~4)",
+ "files_changed": 4
}
]
}
diff --git a/RULES.md b/RULES.md
index 4369c39..ac821a0 100644
--- a/RULES.md
+++ b/RULES.md
@@ -37,10 +37,10 @@
- `ASR_FALLBACK_MODEL`:当当前网关没有 `/audio/transcriptions` 时,用 Gemini 多模态 chat 直接识别 wav,默认 `gemini-2.5-flash`
- `TRANSLATE_MODEL`:字幕翻译模型,默认 `gemini-2.5-flash`
- `REWRITE_MODEL`:通用改写/分镜描述模型,默认 `gemini-2.5-pro`
-- `AUDIO_REWRITE_MODEL`:音频口播改写模型,默认跟随 `REWRITE_MODEL`
+- `AUDIO_REWRITE_MODEL`:音频口播改写模型,默认跟随 `REWRITE_MODEL`;当前产物要求输出英文 SKG voice-over
- `AUDIO_PRODUCT_BRIEF`:音频口播改写时注入的 SKG 产品卖点
- `MINIMAX_API_KEY`:MiniMax T2A 配音 Key,只能放本地 `api/.env`,不能入库
-- `MINIMAX_TTS_BASE_URL` / `MINIMAX_TTS_MODEL` / `MINIMAX_TTS_VOICE_ID`:MiniMax 配音端点、模型和音色配置
+- `MINIMAX_TTS_BASE_URL` / `MINIMAX_TTS_MODEL` / `MINIMAX_TTS_VOICE_ID`:MiniMax 配音端点、模型和音色配置;当前默认英文音色 `English_expressive_narrator`
- `POE_API_KEY` / `VIDEO_API_KEY`:视频生成通道 Key,只能放本地环境变量
## 规则
diff --git a/api/README.md b/api/README.md
index b5ac919..b03cc8f 100644
--- a/api/README.md
+++ b/api/README.md
@@ -1,6 +1,6 @@
# SKG TK 二创 API
-FastAPI 后端,跑 yt-dlp + ffmpeg + ASR/翻译/文案改写 + MiniMax 配音管线。
+FastAPI 后端,跑 yt-dlp + ffmpeg + ASR/翻译/英文 SKG 文案改写 + MiniMax 英文配音管线。
## 启动
@@ -19,11 +19,11 @@ uvicorn main:app --host 127.0.0.1 --port 4291
- `GET /health` — 健康检查 + 配置状态
- `POST /jobs` `{url}` — 创建 job,后台下载源视频,视频就绪后可手动解析或提取音频
-- `GET /jobs/{id}` — 当前状态 + 产物
-- `POST /jobs/{id}/transcribe` — 触发音频提取 + ASR + 翻译 + SKG 文案改写;配置 MiniMax 后生成配音。前端 Audio 节点提供“提取音频 / 重新提取音频”按钮,可与抽帧并行,不自动触发
+- `GET /jobs/{id}` — 当前状态 + 产物;若原始音轨已拆出,会返回 `source_audio_url`
+- `POST /jobs/{id}/transcribe` — 触发音频提取 + ASR + 翻译 + SKG 英文文案改写;配置 MiniMax 后生成英文配音。前端 Audio 节点提供“提取音频 / 重新提取音频”按钮,可与抽帧并行,不自动触发
- `GET /jobs/{id}/video.mp4` — 原视频
- `GET /jobs/{id}/audio.wav` — 拆轨后的原始音频,供前端底部音频条生成波形
-- `GET /jobs/{id}/audio-script.mp3` — 改写文案的 MiniMax 配音
+- `GET /jobs/{id}/audio-script.mp3` — 英文改写文案的 MiniMax 配音
- `GET /jobs/{id}/frames/{i}.jpg` — 第 i 张关键帧(0-9)
## Mock 模式
@@ -35,4 +35,4 @@ uvicorn main:app --host 127.0.0.1 --port 4291
- `ffmpeg` 系统二进制(拆轨 / 抽帧)
- `yt-dlp` 系统二进制(也可走 Python 包)
- OpenAI 兼容 LLM 网关(ASR / 翻译 / 文案改写);如果 `/audio/transcriptions` 不可用,会用 `ASR_FALLBACK_MODEL` 走 Gemini 多模态音频识别
-- MiniMax T2A HTTP(改写文案配音,使用 `MINIMAX_API_KEY`)
+- MiniMax T2A HTTP(英文改写文案配音,使用 `MINIMAX_API_KEY`;默认音色 `English_expressive_narrator`)
diff --git a/docs/source-analysis.html b/docs/source-analysis.html
index 76d8b7d..8e55b81 100644
--- a/docs/source-analysis.html
+++ b/docs/source-analysis.html
@@ -558,7 +558,7 @@
5
素材准备
清洗关键帧,把多张关键帧作为同一主体的参考,先重绘六张标准站立主体资产图,再按关键帧生成多个去主体、相似或换风格场景图。
6
分镜改造
把参考主体、场景、动作和 SKG 产品放入分镜结构;产品融合使用纵向 6 行镜头工作表,每行绑定产品图、白底人物图、产品区域、场景图、描述词、秒数和单条生成入口。
7
生成视频
普通分镜可调用 Seedance / Kling / Veo 3;产品融合固定用 GPT Image 2 生成位置引导图,再用 Seedance 按秒数生成视频,结果回写到画面工作台节点。
- 8
声音文案
音频轨独立处理:ASR 提取原始文案、翻译成中文、接 SKG 产品卖点改写成口播稿;配置 MiniMax 后直接生成配音 mp3。
+ 8
声音文案
音频轨独立处理:ASR 提取原始英文文案、翻译成中文对照、接 SKG 产品卖点改写成英文 voice-over;配置 MiniMax 后直接生成英文配音 mp3。底部音频条播放原音频时,指针会按时间走过字幕节点。
9
合成成品
片段、字幕、配音、转场合成最终 mp4。当前未实现。
@@ -572,7 +572,7 @@
web/app/page.tsx | 产品工作台主状态:jobs、activeJobId、按 job 隔离的 selectedFrames/详情面板状态、clipboard、ReactFlow 节点和边;负责打开/找回画布工作面板。 |
web/components/nodes/index.tsx | DAG 节点定义:Input、VisualLab、Audio、Compose,以及画布工作面板 KeyframePanel / VideoFramePanel;旧 Keyframe/Storyboard/VideoGen 组件保留但不再挂主画布。 |
- web/components/audio-strip.tsx | 底部吸附音频条:可拖拽调整高度;按时间段展示英文、中文翻译和音频波形,并在右侧固定显示 SKG 改写稿和 MiniMax 配音。 |
+ web/components/audio-strip.tsx | 底部吸附音频条:可拖拽调整高度;播放原音频时移动指针,逐个高亮英文/中文字幕节点和对应波形,并在右侧固定显示 SKG 英文改写稿和 MiniMax 英文配音。 |
web/components/lightbox.tsx | 关键帧素材准备面板:清洗、统一主体候选、参考帧网格、六张主体重绘图、每帧去主体场景图、纵向 6 行产品融合镜头工作表和审核。 |
web/components/product-library-picker.tsx | SKG 内置白底产品图库选择器:搜索、品类筛选、预览尺寸,并把库内图片复制为当前 job 的 asset。 |
web/components/storyboard-bar.tsx | 顶部分镜编排条:展示选入编排的关键帧,并作为唯一分镜导航。 |
@@ -585,7 +585,7 @@
后端核心
- api/main.py | FastAPI 单文件后端:状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、音频文案改写、MiniMax 配音、文件返回。 |
+ api/main.py | FastAPI 单文件后端:状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、音频文案改写、MiniMax 英文配音、文件返回。 |
api/product_library/skg-products | 内置 SKG 白底产品图库:manifest.json 记录从桌面产品图筛出的 gallery 白底图和桌面 4 张产品角度图,images/ 存 45 张参考图。 |
jobs/<jobId>/state.json | 运行时状态文件,不在源码列表里,但刷新恢复依赖它。 |
jobs/<jobId>/audio.wav | 拆轨得到的原始音频,底部 Audio Strip 会通过只读接口拉取并在浏览器里解码成波形峰值。 |
@@ -601,7 +601,7 @@
web/app/page.tsx
-> ReactFlow 节点:web/components/nodes/index.tsx
-> 主画布:Input → VisualLab / Audio → Compose
- -> 底部音频条:web/components/audio-strip.tsx(英文 / 中文 / 波形 / 改写稿)
+ -> 底部音频条:web/components/audio-strip.tsx(原音频播放 / 指针 / 英文 / 中文 / 波形 / 英文改写稿)
-> 画布内视频抽帧面板:InputNode 单击视频缩略图打开 videoFramePanel
-> 画布内镜头拆解面板:VisualLabNode 打开 keyframePanel,内嵌 web/components/lightbox.tsx
-> 分镜工作台:web/components/storyboard-workbench.tsx(底层保留)
@@ -610,7 +610,7 @@ web/app/page.tsx
后端主链路:
api/main.py
-> Job / KeyFrame / KeyElement / StoryboardScene / AudioScript
- -> 下载 / 上传 / 抽帧 / Vision / 清洗 / 元素提取 / 分镜保存 / 音频文案改写 / MiniMax 配音
+ -> 下载 / 上传 / 抽帧 / Vision / 清洗 / 元素提取 / 分镜保存 / 音频文案改写 / MiniMax 英文配音
-> jobs/<jobId>/state.json + 图片文件落盘
@@ -648,7 +648,7 @@ api/main.py
一个视频任务。前端维护多个 jobs[],当前激活的是 activeJobId。URL 查询参数会持久化多个 job。
Job {
id, url, status, progress, message,
- video_url, duration, width, height,
+ video_url, source_audio_url, duration, width, height,
frames: KeyFrame[],
transcript: TranscriptSegment[],
audio_script: AudioScript,
@@ -701,7 +701,7 @@ api/main.py
AudioScript
-
音频文案轨的结构化产物。pipeline_transcribe 在 ASR 和翻译后写入:先生成 SKG 口播改写稿,再用 MiniMax T2A 生成配音文件。
+
音频文案轨的结构化产物。pipeline_transcribe 在 ASR 和翻译后写入:先生成 SKG 英文 voice-over 改写稿,再用 MiniMax T2A 生成英文配音文件。
AudioScript {
status: idle | rewriting | completed | failed,
source_text,
@@ -791,9 +791,9 @@ SubjectAsset {
| 上传视频 | POST /jobs/upload | uploadJob | 保存 source.mp4,然后同样进入下载完成状态。 |
| 删除输入视频 | DELETE /jobs/{id} | deleteJob | 从任务队列、URL 和磁盘 jobs/<id> 目录移除整个 job,包括源视频、关键帧、元素提取图和生成视频。 |
| 解析视频 | POST /jobs/{id}/analyze?frames=&target=&mode=&quality= | analyzeJob | 拆轨 + 目标化抽关键帧。默认 frames=12;target 支持透明骨架人、综合、清晰主体、转场变化、表情瞬间、动作峰值;当前 UI 默认 transparent_human。透明骨架人目标现在只走本地清晰度、中心主体、对比度、画面变化和 pHash 去重,不在抽帧阶段逐帧调用 Vision;mode=append 追加新关键帧;quality=auto 为展示友好档,最高只自动选择精细,不会自动上极准;极准保留为手动选择。抽帧开始时同步拆出 audio.wav 并启动音频处理线程。多个抽帧请求进入后端队列顺序处理。 |
- | 音频文案轨 | POST /jobs/{id}/transcribe | triggerTranscribe | 若尚未拆轨,先从 source.mp4 提取 audio.wav;随后 ASR 得到英文时间戳段落,再翻译中文,并按 AUDIO_PRODUCT_BRIEF 生成 audio_script.rewritten_text;配置 MINIMAX_API_KEY 后调用 MiniMax T2A 生成 audio_script.voice_url。前端不自动触发,用户在 Audio 节点点击“提取音频 / 重新提取音频”即可启动;抽帧中也允许并行触发,忙碌态由 audio_script.status 管理。 |
- | 原始音频文件 | GET /jobs/{id}/audio.wav | sourceAudioUrl | 返回拆轨得到的 wav;底部 AudioStrip 拉取该文件,用 Web Audio API 解码并计算波形峰值,只读展示,不参与改写。 |
- | 改写配音文件 | GET /jobs/{id}/audio-script.mp3 | apiAssetUrl(job.audio_script.voice_url) | 返回 MiniMax T2A 生成的 mp3。没有配置 MiniMax 或生成失败时该文件不存在,但改写文案仍会保存在 audio_script.rewritten_text。 |
+ | 音频文案轨 | POST /jobs/{id}/transcribe | triggerTranscribe | 若尚未拆轨,先从 source.mp4 提取 audio.wav 并回填 source_audio_url;随后 ASR 得到英文时间戳段落,再翻译中文,并按 AUDIO_PRODUCT_BRIEF 生成英文 audio_script.rewritten_text;配置 MINIMAX_API_KEY 后调用 MiniMax T2A 生成英文 audio_script.voice_url。前端不自动触发,用户在 Audio 节点点击“提取音频 / 重新提取音频”即可启动并立即打开底部音频条;抽帧中也允许并行触发,忙碌态由 audio_script.status 管理。 |
+ | 原始音频文件 | GET /jobs/{id}/audio.wav | sourceAudioUrl | 返回拆轨得到的 wav;底部 AudioStrip 拉取该文件,用 Web Audio API 解码并计算波形峰值。原音频播放器驱动时间轴,播放时全局指针和当前字幕节点内指针同步移动。 |
+ | 改写配音文件 | GET /jobs/{id}/audio-script.mp3 | apiAssetUrl(job.audio_script.voice_url) | 返回 MiniMax T2A 生成的英文 mp3。没有配置 MiniMax 或生成失败时该文件不存在,但英文改写文案仍会保存在 audio_script.rewritten_text。 |
| 手动加帧 | POST /jobs/{id}/frames?t= | addManualFrame | 按视频时间戳抽一帧,index 递增但 frames 按 timestamp 排序。 |
| Vision 识别 | POST /frames/{idx}/describe | describeFrame | 写入 frame.description,后续可从 objects 加候选元素。 |
| 清洗水印 | POST /frames/{idx}/cleanup | cleanupFrame | 支持全图和区域清洗,生成 cleaned 待应用版本;前端批量清洗会顺序调用该接口,不自动覆盖原图。单帧清洗状态按 frame.index 隔离,清洗某一张不会禁用其他关键帧的清洗按钮。 |
@@ -840,7 +840,7 @@ SubjectAsset {
| Audio / ASR / Rewrite |
- 独立声音文案轨:从 source.mp4 直接提取 audio.wav,再提取原始口播、翻译中文、改写成 SKG 产品语境口播;MiniMax T2A 配置后生成配音 mp3。不再等待抽帧完成,用户在主画布 AudioNode 手动点击“提取音频 / 重新提取音频”启动;即使视觉抽帧正在进行,也通过 audio_script.status 并行管理音频忙碌态。AudioNode 用“改前 · 原音频 / 改后 · SKG 口播”摘要展示;底部 AudioStrip 吸附屏幕底端,可拖拽调整高度,按时间段展示英文、中文翻译和波形;侧栏 Rewrite 展开后显示完整审核视图。 |
+ 独立声音文案轨:从 source.mp4 直接提取 audio.wav,再提取原始口播、翻译中文、改写成 SKG 产品语境英文 voice-over;MiniMax T2A 配置后生成英文配音 mp3。不再等待抽帧完成,用户在主画布 AudioNode 点击卡片或“提取音频 / 重新提取音频”即可打开底部音频条并启动;即使视觉抽帧正在进行,也通过 audio_script.status 并行管理音频忙碌态。AudioNode 用“改前 · 原音频 / 改后 · SKG English VO”摘要展示;底部 AudioStrip 吸附屏幕底端,可拖拽调整高度,按时间段展示英文、中文翻译和波形;原音频播放时指针同步穿过字幕节点,右侧显示英文改写稿和 MiniMax 英文配音。 |
不要阻断视觉素材管线。 |
AudioNode、AudioStrip、ASRNode、TranslateNode、RewriteNode、pipeline_transcribe、AudioScript |
@@ -867,7 +867,7 @@ SubjectAsset {
Vision 识别关键帧,输出 scene、objects、style、suggested_prompt,并作为主体候选来源。
主体候选确认、改名、删除和主体资产包生成。
分镜工作台 4 图槽和改造说明自动保存。
-
音频文案轨:ASR/翻译后自动生成 SKG 口播改写稿;配置 MiniMax 后生成配音 mp3。
+
音频文案轨:ASR/翻译后自动生成 SKG 英文口播改写稿;配置 MiniMax 后生成英文配音 mp3。底部音频条可播放原音频并用指针逐段对齐字幕节点。
nano-banana-pro image-to-image 生图。
@@ -875,7 +875,7 @@ SubjectAsset {
阻塞 / 占位
- ASR:优先走当前 OpenAI-compatible 音频转写入口;如果该网关没有
/audio/transcriptions,自动 fallback 到 ASR_FALLBACK_MODEL(默认 gemini-2.5-flash)的多模态音频识别。
- - MiniMax:当前接入的是官方 T2A 配音能力,不是 ASR;API Key 只能放本地环境变量,不能写入仓库。
+ - MiniMax:当前接入的是官方 T2A 英文配音能力,不是 ASR;API Key 只能放本地环境变量,不能写入仓库。
- Audio Product Brief:默认是通用 SKG 放松产品卖点,后续可改成跟已选产品库条目联动。
- Video Gen:模型层按业务保留 Seedance / Kling / Veo/Voe 选择;后端已支持 Poe、火山方舟和 SKG 豆包视频网关。Seedance 可通过
VIDEO_API_BASE_URL=https://ai.skg.com/doubao 走 content JSON 异步任务,提交后写入 Video Gen 节点并轮询到完成。
- Compose:还没做本地 ffmpeg 字幕/TTS 合成。
@@ -975,7 +975,7 @@ SubjectAsset {
问题:等待抽帧完成后自动启动音频,不符合“先把声音文案拿出来审核”的工作流;用户需要在音频卡片上直接触发。
-
改动:移除前端抽帧完成后的自动转写逻辑;AudioNode 保留并固定显示“提取音频 / 重新提取音频”按钮。后端 /transcribe 不再要求 frames_extracted,视频就绪后可直接从 source.mp4 拆出 audio.wav,并继续 ASR、翻译、SKG 改写和 MiniMax 配音;抽帧中触发时不抢主状态,而是用 audio_script.status 表示音频处理中。当当前网关的 whisper-1 audio endpoint 返回 404 时,会 fallback 到 Gemini 多模态音频识别;改写模型解析失败时使用本地 SKG 口播模板兜底,不再把可用文案标成前端错误。
+
改动:移除前端抽帧完成后的自动转写逻辑;AudioNode 保留并固定显示“提取音频 / 重新提取音频”按钮,点击音频卡片也会立即打开底部音频条。后端 /transcribe 不再要求 frames_extracted,视频就绪后可直接从 source.mp4 拆出 audio.wav,并继续 ASR、翻译、SKG 英文改写和 MiniMax 英文配音;抽帧中触发时不抢主状态,而是用 audio_script.status 表示音频处理中。当当前网关的 whisper-1 audio endpoint 返回 404 时,会 fallback 到 Gemini 多模态音频识别;改写模型解析失败时使用本地 SKG 英文口播模板兜底,不再把可用文案标成前端错误。
影响:web/app/page.tsx、web/components/nodes/index.tsx、api/main.py、docs/source-analysis.html。
@@ -987,7 +987,7 @@ SubjectAsset {
问题:音频和文案只在节点或侧栏里展示,审核时缺少“文字和声音时间轴对应”的空间;英文口播和中文翻译也没有上下对齐。
-
改动:新增 web/components/audio-strip.tsx,在主工作台底部吸附显示,可拖拽调整高度、可收起。每个音频段按时间横向排列,上方显示英文,中间显示中文翻译,下方显示对应波形条;右侧显示改写后的 SKG 口播、MiniMax 配音和产品依据。后端新增 GET /jobs/{id}/audio.wav 只读接口,前端用 Web Audio API 解码生成波形峰值。
+
改动:新增 web/components/audio-strip.tsx,在主工作台底部吸附显示,可拖拽调整高度、可收起。每个音频段按时间横向排列,上方显示英文,中间显示中文翻译,下方显示对应波形条;底部原音频播放器驱动时间轴,播放时绿色指针会沿全局波形移动,并在当前字幕节点内同步走过该段。右侧显示改写后的 SKG English VO、MiniMax 英文配音和产品依据。后端新增 source_audio_url 和 GET /jobs/{id}/audio.wav 只读接口,前端用 Web Audio API 解码生成波形峰值。
影响:web/app/page.tsx、web/components/audio-strip.tsx、web/lib/api.ts、api/main.py、docs/source-analysis.html。
@@ -999,7 +999,7 @@ SubjectAsset {
问题:音频识别成功后只显示改写文案,用户看不到它和原音频之间的变化关系,难以判断“是不是把参考视频转成我们自己的话”。
-
改动:AudioNode 增加轻量对照摘要:改前显示原音频识别/翻译预览,改后显示 SKG 口播;侧栏 Rewrite 面板改为完整审核视图,先列原音频逐段 ASR/翻译,再列改写稿、产品卖点依据和 MiniMax 配音播放器。
+
改动:AudioNode 增加轻量对照摘要:改前显示原音频识别/翻译预览,改后显示 SKG 英文口播;侧栏 Rewrite 面板改为完整审核视图,先列原音频逐段 ASR/翻译,再列英文改写稿、产品卖点依据和 MiniMax 英文配音播放器。
影响:web/components/nodes/index.tsx、web/components/dashboard.tsx、docs/source-analysis.html。
@@ -1042,13 +1042,13 @@ SubjectAsset {
- 2026-05-14 · 音频处理接入 SKG 口播改写与 MiniMax 配音
+ 2026-05-14 · 音频处理接入 SKG 英文口播改写与 MiniMax 配音
Audio
MiniMax
-
问题:音频处理节点之前只说明“音轨 → ASR → 翻译 → 改写”,没有真实改写产物,也没有配音输出;用户无法直接拿到符合 SKG 产品语境的口播。
-
改动:Job 新增 audio_script,pipeline_transcribe 在 ASR 和翻译后生成 SKG 改写文案,并在配置 MINIMAX_API_KEY 时调用 MiniMax T2A 输出 /jobs/{id}/audio-script.mp3。前端 AudioNode 和侧栏 Rewrite 区显示模型链路、改写文案和配音播放器。
+
问题:音频处理节点之前只说明“音轨 → ASR → 翻译 → 改写”,没有真实改写产物,也没有配音输出;用户无法直接拿到符合 SKG 产品语境的英文口播。
+
改动:Job 新增 audio_script,pipeline_transcribe 在 ASR 和翻译后生成 SKG 英文改写文案,并在配置 MINIMAX_API_KEY 时调用 MiniMax T2A 输出 /jobs/{id}/audio-script.mp3。前端 AudioNode 和侧栏 Rewrite 区显示模型链路、英文改写文案和配音播放器。
边界:MiniMax 官方 Speech API 当前接入的是 TTS 配音,不替代 ASR;原始音频文案提取仍走现有 OpenAI-compatible audio transcription 入口。
影响:api/main.py、api/.env.example、api/README.md、web/lib/api.ts、web/components/nodes/index.tsx、web/components/dashboard.tsx、web/app/page.tsx、docs/source-analysis.html。