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.tsxDAG 节点定义: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.tsxSKG 内置白底产品图库选择器:搜索、品类筛选、预览尺寸,并把库内图片复制为当前 job 的 assetweb/components/storyboard-bar.tsx顶部分镜编排条:展示选入编排的关键帧,并作为唯一分镜导航。 @@ -585,7 +585,7 @@

后端核心

- + @@ -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 {
             
- - - + + + @@ -840,7 +840,7 @@ SubjectAsset { - + @@ -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 {

    阻塞 / 占位

    api/main.pyFastAPI 单文件后端:状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、音频文案改写、MiniMax 配音、文件返回。
    api/main.pyFastAPI 单文件后端:状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、音频文案改写、MiniMax 英文配音、文件返回。
    api/product_library/skg-products内置 SKG 白底产品图库:manifest.json 记录从桌面产品图筛出的 gallery 白底图和桌面 4 张产品角度图,images/ 存 45 张参考图。
    jobs/<jobId>/state.json运行时状态文件,不在源码列表里,但刷新恢复依赖它。
    jobs/<jobId>/audio.wav拆轨得到的原始音频,底部 Audio Strip 会通过只读接口拉取并在浏览器里解码成波形峰值。
    上传视频POST /jobs/uploaduploadJob保存 source.mp4,然后同样进入下载完成状态。
    删除输入视频DELETE /jobs/{id}deleteJob从任务队列、URL 和磁盘 jobs/<id> 目录移除整个 job,包括源视频、关键帧、元素提取图和生成视频。
    解析视频POST /jobs/{id}/analyze?frames=&target=&mode=&quality=analyzeJob拆轨 + 目标化抽关键帧。默认 frames=12target 支持透明骨架人、综合、清晰主体、转场变化、表情瞬间、动作峰值;当前 UI 默认 transparent_human。透明骨架人目标现在只走本地清晰度、中心主体、对比度、画面变化和 pHash 去重,不在抽帧阶段逐帧调用 Vision;mode=append 追加新关键帧;quality=auto 为展示友好档,最高只自动选择精细,不会自动上极准;极准保留为手动选择。抽帧开始时同步拆出 audio.wav 并启动音频处理线程。多个抽帧请求进入后端队列顺序处理。
    音频文案轨POST /jobs/{id}/transcribetriggerTranscribe若尚未拆轨,先从 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.wavsourceAudioUrl返回拆轨得到的 wav;底部 AudioStrip 拉取该文件,用 Web Audio API 解码并计算波形峰值,只读展示,不参与改写。
    改写配音文件GET /jobs/{id}/audio-script.mp3apiAssetUrl(job.audio_script.voice_url)返回 MiniMax T2A 生成的 mp3。没有配置 MiniMax 或生成失败时该文件不存在,但改写文案仍会保存在 audio_script.rewritten_text
    音频文案轨POST /jobs/{id}/transcribetriggerTranscribe若尚未拆轨,先从 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.wavsourceAudioUrl返回拆轨得到的 wav;底部 AudioStrip 拉取该文件,用 Web Audio API 解码并计算波形峰值。原音频播放器驱动时间轴,播放时全局指针和当前字幕节点内指针同步移动。
    改写配音文件GET /jobs/{id}/audio-script.mp3apiAssetUrl(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}/describedescribeFrame写入 frame.description,后续可从 objects 加候选元素。
    清洗水印POST /frames/{idx}/cleanupcleanupFrame支持全图和区域清洗,生成 cleaned 待应用版本;前端批量清洗会顺序调用该接口,不自动覆盖原图。单帧清洗状态按 frame.index 隔离,清洗某一张不会禁用其他关键帧的清洗按钮。
    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 英文配音。 不要阻断视觉素材管线。 AudioNodeAudioStripASRNodeTranslateNodeRewriteNodepipeline_transcribeAudioScript