diff --git a/Dockerfile b/Dockerfile
index 6154e4f..63cd7a4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,9 @@
-FROM nvidia/cuda:12.1.1-runtime-ubuntu22.04 AS builder
+ARG NODE_BASE_IMAGE=docker.m.daocloud.io/library/node:20-bookworm-slim
+ARG CUDA_BASE_IMAGE=docker.m.daocloud.io/nvidia/cuda:12.1.1-runtime-ubuntu22.04
+
+FROM ${NODE_BASE_IMAGE} AS node20
+
+FROM ${CUDA_BASE_IMAGE} AS builder
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 \
@@ -11,18 +16,18 @@ ENV DEBIAN_FRONTEND=noninteractive \
WORKDIR /app
-# Base deps + Python 3.10 + Node.js 20.x
+# Base deps + Python 3.10
RUN sed -i 's|http://archive.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu.cn/ubuntu|g; s|http://security.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu.cn/ubuntu|g' /etc/apt/sources.list \
&& apt-get -o Acquire::Retries=5 update \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends --fix-missing \
ca-certificates curl gnupg \
python3.10 python3.10-distutils python3-pip \
ffmpeg fonts-dejavu-core \
- && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
- && apt-get -o Acquire::Retries=5 install -y --no-install-recommends --fix-missing nodejs \
&& ln -sf /usr/bin/python3.10 /usr/local/bin/python \
&& rm -rf /var/lib/apt/lists/*
+COPY --from=node20 /usr/local /usr/local
+
COPY requirements.txt /app/requirements.txt
RUN python3.10 -m pip install -r /app/requirements.txt
@@ -31,7 +36,7 @@ RUN cd /app/server && npm ci --omit=dev
COPY . /app
-FROM nvidia/cuda:12.1.1-runtime-ubuntu22.04 AS runtime
+FROM ${CUDA_BASE_IMAGE} AS runtime
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 \
@@ -50,11 +55,11 @@ RUN sed -i 's|http://archive.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu
ca-certificates \
python3.10 python3.10-distutils python3-pip \
ffmpeg fonts-dejavu-core \
- && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
- && apt-get -o Acquire::Retries=5 install -y --no-install-recommends --fix-missing nodejs \
&& ln -sf /usr/bin/python3.10 /usr/local/bin/python \
&& rm -rf /var/lib/apt/lists/*
+COPY --from=node20 /usr/local /usr/local
+
COPY --from=builder /usr/local/lib/python3.10 /usr/local/lib/python3.10
COPY --from=builder /usr/local/bin /usr/local/bin
COPY --from=builder /app /app
diff --git a/README.md b/README.md
index e293042..53de734 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
- Output: a 3-scene narrated video `final_poc.mp4` (mock mode supported)
## Quick start (Docker)
-`docker compose up` includes a **ComfyUI** service (default image `jamesbrink/comfyui:latest` from Docker Hub). If you use another registry image, set `COMFYUI_IMAGE` in the environment.
+`docker compose up` includes a **ComfyUI** service (default through domestic mirror: `docker.1ms.run/ardenius/comfyui-cpu:latest`). If you use another registry image, set `COMFYUI_IMAGE` in the environment.
Build:
@@ -49,3 +49,4 @@ Open `http://127.0.0.1:3000` and click “运行” to see `main.py --script-onl
- **apt**: TUNA Debian mirrors (baked into `Dockerfile`)
- **pip**: `PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple`
- **npm**: `NPM_CONFIG_REGISTRY=https://registry.npmmirror.com`
+- **docker images**: default base images now pull via `docker.m.daocloud.io` mirror
diff --git a/clone.html b/clone.html
new file mode 100644
index 0000000..703911a
--- /dev/null
+++ b/clone.html
@@ -0,0 +1,52 @@
+
Untitled video - Google VidsUpgrade to unlock higher video generation limits and premium AI capabilities.
Close banner
Turn on screen reader supportBanner hidden
Google Account
zhao jiang
josephine900710@gmail.com
To enable screen reader support, press ⌘+Option+Z To learn about keyboard shortcuts, press ⌘slash
Generate an AI video clip
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index 3060a5f..0a8da07 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -10,15 +10,17 @@ services:
- PORT=3000
volumes:
- ./:/app
+ # Keep dependencies inside container volume to avoid host FS read issues on macOS.
+ - /app/server/node_modules
ports:
- "3000:3000"
- # Default: Docker Hub (anonymous pull). GHCR comfyanonymous image often returns "denied" without login.
- # Override: COMFYUI_IMAGE=ghcr.io/... after `docker login ghcr.io`
+ # Default: use domestic mirror to speed up pulls in CN networks.
+ # Override with COMFYUI_IMAGE to use another registry/image.
comfyui:
# CPU-friendly default image for non-NVIDIA development machines.
# Override with COMFYUI_IMAGE to switch back to a GPU image.
- image: ${COMFYUI_IMAGE:-ardenius/comfyui-cpu:latest}
+ image: ${COMFYUI_IMAGE:-docker.1ms.run/ardenius/comfyui-cpu:latest}
# Force bind to all interfaces so other containers (and `check_comfy`) can reach it.
# Works with the default ardenius/comfyui-cpu image layout (/ComfyUI-cpu/main.py).
command: ${COMFYUI_COMMAND:-python3 /ComfyUI-cpu/main.py --cpu --cpu-vae --listen 0.0.0.0 --port 8188}
diff --git a/docs/studio_rearchitecture.md b/docs/studio_rearchitecture.md
new file mode 100644
index 0000000..27f0c25
--- /dev/null
+++ b/docs/studio_rearchitecture.md
@@ -0,0 +1,61 @@
+# AiVideo Studio 重构方案(V2)
+
+## 目标
+- 实现与参考编辑器页面一致的工作台布局:顶部导航、中央预览舞台、底部时间线、右侧参数与日志面板。
+- 保留并强化现有能力:自动分镜、单镜头润色、渲染、阶段日志、任务跟踪。
+- 将前端代码从“流程散落”改造为“分层架构”,减少重复逻辑与状态不一致风险。
+
+## 新架构
+
+### 1. UI Shell 层
+- `TopNav`:品牌、快捷操作、Play/Render 入口。
+- `ToolBar`:上下文状态(task/mock)与工具位。
+- `PreviewStage`:展示当前 Scene 预览或 final video。
+- `TimelineStrip`:镜头缩略图时间线与进度条。
+- `SceneEditor`:单镜头编辑与润色入口。
+
+### 2. 状态层(StudioState)
+- 统一使用 `useReducer` 管理工作台状态。
+- 核心状态:
+ - `scenes`
+ - `selectedSceneIndex`
+ - `stageState`
+ - `stageLogs`
+ - `renderProgress`
+ - `taskId`
+ - `finalVideoUrl`
+ - `toast`
+- 所有修改均通过 `dispatch(action)` 进入 reducer,避免多处 `useState` 导致的竞态和重复。
+
+### 3. API/流处理层(StudioAPI)
+- `startScriptStream()`:EventSource 流式接收 Script 阶段事件。
+- `postStream()`:统一处理 Refine/Render 的 fetch + SSE 流。
+- `consumeFetchSSE()`:抽象 SSE 分块解析,消除重复解析代码。
+
+### 4. 事件编排层
+- `onStageEvent(sourceStage, event, data)` 统一路由:
+ - `task`
+ - `stage_update`
+ - `line`
+ - `error`
+ - `done`
+- `applyStageUpdate()` 负责阶段状态、进度、scene upsert 的单点更新。
+
+## 数据流
+1. 用户修改 Prompt / Provider 参数。
+2. 自动防抖触发 `startScript()`,进入 Script SSE。
+3. `stage_update.scene_json` 持续更新 `scenes`,时间线和右侧编辑器同步刷新。
+4. 用户可对当前 Scene 进行编辑与 `refine`。
+5. 用户触发 `render`,进度与日志实时反馈,完成后挂载 final video URL。
+
+## 兼容性说明
+- 继续使用 `babel-standalone@6`,所以 JSX 不使用 `<>...>`,统一为 `React.Fragment`。
+- 保持现有后端接口契约不变:
+ - `GET /api/script`
+ - `POST /api/refine`
+ - `POST /api/render`
+
+## 后续建议
+- 将当前单文件页面拆分为真正多文件前端工程(Vite + React),引入 TypeScript 与单元测试。
+- 增加 Timeline 的拖拽排序与片段时长编辑。
+- 增加右侧“资产库”与“模板库”,进一步贴近参考产品完整体验。
diff --git a/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/scenes.json b/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/scenes.json
new file mode 100644
index 0000000..75b4740
--- /dev/null
+++ b/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/scenes.json
@@ -0,0 +1,19 @@
+{
+ "scenes": [
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,城市夜景,霓虹灯,电影感",
+ "video_motion": "缓慢推进镜头,轻微摇镜",
+ "narration": "夜色温柔落在街灯上"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,咖啡店窗边,暖光,细雨",
+ "video_motion": "侧向平移,人物轻轻抬头",
+ "narration": "雨声里藏着一段回忆"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,桥上远景,车流光轨,温暖",
+ "video_motion": "拉远全景,光轨流动",
+ "narration": "我们在光里学会告别"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_786948454fcb42f09bdff72cdbcf3381.png b/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_786948454fcb42f09bdff72cdbcf3381.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_786948454fcb42f09bdff72cdbcf3381.png differ
diff --git a/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_9c07077ad485421e8f8258473aa2ec51.png b/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_9c07077ad485421e8f8258473aa2ec51.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_9c07077ad485421e8f8258473aa2ec51.png differ
diff --git a/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_e0328915d14746038ab25515ece4e25c.png b/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_e0328915d14746038ab25515ece4e25c.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/0c7eca55-8d10-4808-a5da-bd0b1247b4ed/shot_e0328915d14746038ab25515ece4e25c.png differ
diff --git a/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/scenes.json b/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/scenes.json
new file mode 100644
index 0000000..75b4740
--- /dev/null
+++ b/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/scenes.json
@@ -0,0 +1,19 @@
+{
+ "scenes": [
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,城市夜景,霓虹灯,电影感",
+ "video_motion": "缓慢推进镜头,轻微摇镜",
+ "narration": "夜色温柔落在街灯上"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,咖啡店窗边,暖光,细雨",
+ "video_motion": "侧向平移,人物轻轻抬头",
+ "narration": "雨声里藏着一段回忆"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,桥上远景,车流光轨,温暖",
+ "video_motion": "拉远全景,光轨流动",
+ "narration": "我们在光里学会告别"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_0b4321ff54414687878ec98869c581e4.png b/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_0b4321ff54414687878ec98869c581e4.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_0b4321ff54414687878ec98869c581e4.png differ
diff --git a/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_41044d8abc9346ff83b7963ff9e678c4.png b/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_41044d8abc9346ff83b7963ff9e678c4.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_41044d8abc9346ff83b7963ff9e678c4.png differ
diff --git a/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_fd9046e98697457ab46cd1dd66bdb649.png b/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_fd9046e98697457ab46cd1dd66bdb649.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/2be794b9-5b7b-4769-b25b-b8f9539f786d/shot_fd9046e98697457ab46cd1dd66bdb649.png differ
diff --git a/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/scenes.json b/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/scenes.json
new file mode 100644
index 0000000..75b4740
--- /dev/null
+++ b/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/scenes.json
@@ -0,0 +1,19 @@
+{
+ "scenes": [
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,城市夜景,霓虹灯,电影感",
+ "video_motion": "缓慢推进镜头,轻微摇镜",
+ "narration": "夜色温柔落在街灯上"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,咖啡店窗边,暖光,细雨",
+ "video_motion": "侧向平移,人物轻轻抬头",
+ "narration": "雨声里藏着一段回忆"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,桥上远景,车流光轨,温暖",
+ "video_motion": "拉远全景,光轨流动",
+ "narration": "我们在光里学会告别"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_5ad5a57722aa40aca1388cbc4d89adf1.png b/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_5ad5a57722aa40aca1388cbc4d89adf1.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_5ad5a57722aa40aca1388cbc4d89adf1.png differ
diff --git a/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_5cb19a1d2bb94bdd9d7d8ac45c91c2bc.png b/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_5cb19a1d2bb94bdd9d7d8ac45c91c2bc.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_5cb19a1d2bb94bdd9d7d8ac45c91c2bc.png differ
diff --git a/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_67ce07e6abae44d8b780aa38d6551a3a.png b/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_67ce07e6abae44d8b780aa38d6551a3a.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/4f7d41b0-e28a-430a-9d86-dbde570388c3/shot_67ce07e6abae44d8b780aa38d6551a3a.png differ
diff --git a/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/scenes.json b/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/scenes.json
new file mode 100644
index 0000000..75b4740
--- /dev/null
+++ b/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/scenes.json
@@ -0,0 +1,19 @@
+{
+ "scenes": [
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,城市夜景,霓虹灯,电影感",
+ "video_motion": "缓慢推进镜头,轻微摇镜",
+ "narration": "夜色温柔落在街灯上"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,咖啡店窗边,暖光,细雨",
+ "video_motion": "侧向平移,人物轻轻抬头",
+ "narration": "雨声里藏着一段回忆"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,桥上远景,车流光轨,温暖",
+ "video_motion": "拉远全景,光轨流动",
+ "narration": "我们在光里学会告别"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_66c444bceb0f468490ed8cc6676bd530.png b/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_66c444bceb0f468490ed8cc6676bd530.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_66c444bceb0f468490ed8cc6676bd530.png differ
diff --git a/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_acd715860ded449bb24186292665c31e.png b/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_acd715860ded449bb24186292665c31e.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_acd715860ded449bb24186292665c31e.png differ
diff --git a/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_d08ccecfca114abcb62c9e730bc5e11d.png b/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_d08ccecfca114abcb62c9e730bc5e11d.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/617c1a3f-1c19-42d9-86c6-d121ae08f708/shot_d08ccecfca114abcb62c9e730bc5e11d.png differ
diff --git a/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/scenes.json b/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/scenes.json
new file mode 100644
index 0000000..75b4740
--- /dev/null
+++ b/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/scenes.json
@@ -0,0 +1,19 @@
+{
+ "scenes": [
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,城市夜景,霓虹灯,电影感",
+ "video_motion": "缓慢推进镜头,轻微摇镜",
+ "narration": "夜色温柔落在街灯上"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,咖啡店窗边,暖光,细雨",
+ "video_motion": "侧向平移,人物轻轻抬头",
+ "narration": "雨声里藏着一段回忆"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,桥上远景,车流光轨,温暖",
+ "video_motion": "拉远全景,光轨流动",
+ "narration": "我们在光里学会告别"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_04ce1be706b14f32a00debdb3a44949e.png b/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_04ce1be706b14f32a00debdb3a44949e.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_04ce1be706b14f32a00debdb3a44949e.png differ
diff --git a/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_453d3f399a534b92bdebff1e881bc6ec.png b/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_453d3f399a534b92bdebff1e881bc6ec.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_453d3f399a534b92bdebff1e881bc6ec.png differ
diff --git a/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_b69ff3ff6c674ab59194fe6a34b3e043.png b/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_b69ff3ff6c674ab59194fe6a34b3e043.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/8853ac45-7c00-4ef8-a83c-603c4e14ddd8/shot_b69ff3ff6c674ab59194fe6a34b3e043.png differ
diff --git a/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/scenes.json b/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/scenes.json
new file mode 100644
index 0000000..75b4740
--- /dev/null
+++ b/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/scenes.json
@@ -0,0 +1,19 @@
+{
+ "scenes": [
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,城市夜景,霓虹灯,电影感",
+ "video_motion": "缓慢推进镜头,轻微摇镜",
+ "narration": "夜色温柔落在街灯上"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,咖啡店窗边,暖光,细雨",
+ "video_motion": "侧向平移,人物轻轻抬头",
+ "narration": "雨声里藏着一段回忆"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,桥上远景,车流光轨,温暖",
+ "video_motion": "拉远全景,光轨流动",
+ "narration": "我们在光里学会告别"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_9ec0ea4571fd474ca5418468e46891cf.png b/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_9ec0ea4571fd474ca5418468e46891cf.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_9ec0ea4571fd474ca5418468e46891cf.png differ
diff --git a/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_c297344ae7a240d8b03fbe591272a559.png b/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_c297344ae7a240d8b03fbe591272a559.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_c297344ae7a240d8b03fbe591272a559.png differ
diff --git a/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_d895c7f1baad41bfb5214d44e3ec262c.png b/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_d895c7f1baad41bfb5214d44e3ec262c.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/a3396ccd-b7ec-48ad-b976-6991b45e4ebd/shot_d895c7f1baad41bfb5214d44e3ec262c.png differ
diff --git a/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/scenes.json b/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/scenes.json
new file mode 100644
index 0000000..75b4740
--- /dev/null
+++ b/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/scenes.json
@@ -0,0 +1,19 @@
+{
+ "scenes": [
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,城市夜景,霓虹灯,电影感",
+ "video_motion": "缓慢推进镜头,轻微摇镜",
+ "narration": "夜色温柔落在街灯上"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,咖啡店窗边,暖光,细雨",
+ "video_motion": "侧向平移,人物轻轻抬头",
+ "narration": "雨声里藏着一段回忆"
+ },
+ {
+ "image_prompt": "写一个温暖的城市夜景故事\n\n\n[Global Constraints]\n- Global Style: 电影感\n请严格遵守上述全局信息,并保持三分镜主角一致。,桥上远景,车流光轨,温暖",
+ "video_motion": "拉远全景,光轨流动",
+ "narration": "我们在光里学会告别"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_0b964ea11e0748fb844413b2f4d2e705.png b/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_0b964ea11e0748fb844413b2f4d2e705.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_0b964ea11e0748fb844413b2f4d2e705.png differ
diff --git a/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_a560a67aee7f4943857bfc8c48d332e2.png b/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_a560a67aee7f4943857bfc8c48d332e2.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_a560a67aee7f4943857bfc8c48d332e2.png differ
diff --git a/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_ed01a3da6b4f47008ba74843ca77639f.png b/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_ed01a3da6b4f47008ba74843ca77639f.png
new file mode 100644
index 0000000..4c86bf9
Binary files /dev/null and b/outputs/df867ed0-8d50-40e3-b839-f61cfb7439bd/shot_ed01a3da6b4f47008ba74843ca77639f.png differ
diff --git a/prompt/v1.md b/prompt/v1.md
new file mode 100644
index 0000000..e3c0571
--- /dev/null
+++ b/prompt/v1.md
@@ -0,0 +1,373 @@
+# 3分钟短片分镜脚本(5秒/镜头)
+
+## 基础设定
+- 总时长:180秒
+- 分镜数量:36个(每个5秒)
+- 叙事风格:军事写实 + 高压营救
+- 画幅建议:2.39:1,24fps
+- 色调建议:
+ - 战前与巡航:冷蓝灰
+ - 被击落与搜捕:黄沙+火光高反差
+ - 夜间营救:深蓝+红色告警光
+
+## 角色映射(拟人化动物代号)
+- 美国:鹰酱
+- 伊朗:波猫
+- 以色列:乌贼(本片仅作为电台背景提及,不正面出场)
+- 中国:熊猫(新闻墙背景信息)
+- 俄罗斯:棕熊(新闻墙背景信息)
+- 印度:白象(新闻墙背景信息)
+- 法国:高卢鸡(新闻墙背景信息)
+- 英国:约翰牛(新闻墙背景信息)
+
+## 身份与语言锁定(必须严格保持)
+- 人物国籍/身份:
+ - `Falcon-1`、`Falcon-2`、Rescue机组、鹰酱指挥链:美国人(American)。
+ - 波猫地面部队、波猫指挥员、波猫电台:波斯人(Persian / Iranian)。
+- 语种使用:
+ - 鹰酱侧人物对白与无线电:英语(English)。
+ - 波猫侧人物对白与无线电:波斯语(Persian / Farsi)。
+ - 旁白可保留中文版本用于成片叙事;若做国际版,旁白统一英语。
+- 字幕与播报规范:
+ - 对白保持原语种发声,不要“角色直接说中文”。
+ - 成片字幕建议双语:中文主字幕 + 英文副字幕;波斯语台词保留音译或意译其一并全片统一。
+ - 无线电口令优先使用军事短句,避免口语化长句。
+
+## 连续性规则(后续生成必须严格保持)
+- 飞行员共2名:
+ - 1号飞行员“Falcon-1”:橙色应急信标、右臂擦伤。
+ - 2号飞行员“Falcon-2”:绿色应急信标、左腿轻伤。
+- 被击落战机:鹰酱双机编队,共2架,均在山地荒漠区坠毁。
+- 营救空中力量:
+ - 黑鹰直升机2架(代号 Rescue-1、Rescue-2)
+ - 加油机1架(代号 Shell-6)
+ - 护航战机若干(不固定数量,远景表现)
+- 结局战损必须出现:
+ - 1架运输机被炸毁
+ - 2架直升机被炸毁(对应 Rescue-1 与 Rescue-2)
+- 主结局必须保留:两名飞行员均被成功救出。
+
+## 人物形象一致性圣经(必须锁定)
+- `Falcon-1`(橙标):
+ - 识别锚点:头盔左侧白色短划痕、右臂外侧止血贴、橙色频闪信标固定在胸挂左下。
+ - 动作特征:右臂发力受限,举枪与攀爬时明显护臂动作。
+ - 台词状态:语速偏稳、短句下达信息。
+- `Falcon-2`(绿标):
+ - 识别锚点:头盔后缘绿色反光贴、左腿膝下弹性绷带、绿色频闪信标固定在腰后。
+ - 动作特征:落地后全程轻度跛行,冲刺时左腿拖步。
+ - 台词状态:呼吸更急,句尾常有停顿。
+- 拟人化呈现边界:
+ - 仅保留“代号化动物身份”语义,不使用夸张兽化比例。
+ - 面部与体型遵循真人军事题材比例,装备佩戴方式符合实战逻辑。
+ - 不出现卡通眼神、夸张毛发、Q版肢体。
+- 全员装备佩戴统一:
+ - 同一角色的头盔编号、护目镜款式、战术背心挂载位置在全片不改变。
+ - 血迹、划伤、灰尘只增不减,不能在后续镜头“突然变干净”。
+
+## 武器与装备真实性基线(建议锁定)
+- 鹰酱舰载打击机:`F/A-18E/F` 双机编队(对应镜头02-07)。
+- 营救直升机:`UH-60` 级别中型通用直升机(Rescue-1 / Rescue-2),侧门机枪位清晰可见。
+- 空中加油机:`KC-46/KC-135` 级别(Shell-6),受油阶段以软管锥套或硬管受油呈现,不出现“接驳火花”。
+- 运输机:`C-130` 级别战术运输机(镜头25、28、29)。
+- 波猫地面防空:
+ - 中程防空系统(雷达车 + 发射车)负责初次击落。
+ - 末段近程威胁以重机枪 + 便携防空导弹(MANPADS)为主。
+- 弹药与火力效果写实化:
+ - 曳光弹比例控制在“数发可见”,避免整条激光束观感。
+ - 近炸与破片效果优先,减少夸张球形大火团。
+ - 爆炸后要有二次碎片与烟尘延迟,不要“一炸即净空”。
+
+## 分镜脚本(36镜头)
+
+### 镜头01(00:00-00:05)
+- 画面:高空俯瞰,波猫领地城市边缘被连续轰炸,冲击波掀起尘墙。
+- 机位/运动:无人机式广角,缓慢前推。
+- 关键元素:夜色未尽,地表火点连成线,防空探照灯扫空。
+- 音效:低沉爆炸滚雷,远处防空警报。
+- 台词/旁白:旁白「战争进入第七夜,鹰酱的空袭仍在继续。」
+
+### 镜头02(00:05-00:10)
+- 画面:鹰酱航母甲板,2架F/A-18E/F挂弹弹射起飞,蒸汽与尾焰交叠。
+- 机位/运动:低机位仰拍,快速摇镜跟随起飞。
+- 关键元素:甲板人员手势指挥、夜航灯闪烁。
+- 音效:喷气轰鸣、甲板指令哨音。
+- 台词/旁白:无线电「Viper编队,进入打击航线。」
+
+### 镜头03(00:10-00:15)
+- 画面:双机编队穿过云层,HUD叠加锁定地面目标。
+- 机位/运动:座舱第一视角与外景切换。
+- 关键元素:导弹挂架细节、雷达波纹扫描。
+- 音效:电子告警“滴滴”,呼吸声。
+- 台词/旁白:Falcon-1「目标区在前,保持队形。」
+
+### 镜头04(00:15-00:20)
+- 画面:波猫山地防空阵地启动,雷达车转入跟踪,导弹发射车舱盖弹开。
+- 机位/运动:地面中景,手持震动感。
+- 关键元素:士兵奔跑装填,红外追踪镜头特写。
+- 音效:机械液压声、点火咆哮。
+- 台词/旁白:波猫指挥员「锁定高空双目标,发射!」
+
+### 镜头05(00:20-00:25)
+- 画面:一枚防空导弹破云而出,拖着白色尾迹直扑编队。
+- 机位/运动:导弹追踪镜头,高速推进。
+- 关键元素:云层被撕开,导弹尾焰占满画面。
+- 音效:尖啸上扬,心跳加重。
+- 台词/旁白:Falcon-2「警报!导弹来袭!」
+
+### 镜头06(00:25-00:30)
+- 画面:第一架战机被命中,机翼断裂起火,飞行员弹射。
+- 机位/运动:慢动作+快速拉远。
+- 关键元素:火球碎片雨、橙色降落伞打开、Falcon-1头盔左侧白色划痕可辨。
+- 音效:爆裂巨响后瞬间闷音。
+- 台词/旁白:Falcon-1「我中弹了,弹射!」
+
+### 镜头07(00:30-00:35)
+- 画面:第二架战机规避失败,在山脊后方爆炸,第二名飞行员跳伞。
+- 机位/运动:远景长焦,爆炸后切近景。
+- 关键元素:绿色信标闪烁,黑烟柱升空,Falcon-2左腿落地姿态明显受伤。
+- 音效:山谷回响爆炸、碎片落地声。
+- 台词/旁白:Falcon-2「我也跳伞了,落点偏东!」
+
+### 镜头08(00:35-00:40)
+- 画面:两名飞行员分别落入荒漠沟壑,迅速解伞隐蔽。
+- 机位/运动:俯拍切地面跟拍。
+- 关键元素:Falcon-1右臂流血并贴止血贴,Falcon-2左腿跛行前进,信标颜色不可互换。
+- 音效:风沙呼啸,急促喘息。
+- 台词/旁白:旁白「两人坠入波猫腹地,距离最近友军超过百公里。」
+
+### 镜头09(00:40-00:45)
+- 画面:Falcon-1开启橙色应急信标,贴地发报。
+- 机位/运动:特写手部操作,微距切换。
+- 关键元素:终端屏幕坐标跳动:Grid K-27。
+- 音效:加密电台短促脉冲声。
+- 台词/旁白:Falcon-1「Mayday,坐标K-27,等待回收。」
+
+### 镜头10(00:45-00:50)
+- 画面:Falcon-2在岩缝内发送绿色信标,标记L-31。
+- 机位/运动:肩扛镜头,压迫感近景。
+- 关键元素:夜视模式闪现,腿部绑带止血。
+- 音效:远处履带车轰鸣渐近。
+- 台词/旁白:Falcon-2「L-31,敌巡逻接近,快。」
+
+### 镜头11(00:50-00:55)
+- 画面:鹰酱前线基地作战室,大屏锁定两个信标点。
+- 机位/运动:环绕镜头扫过指挥台。
+- 关键元素:地图上红蓝箭头交错,倒计时启动。
+- 音效:键盘急击,警铃短鸣。
+- 台词/旁白:指挥官「启动CSAR,黑鹰立即起飞。」
+
+### 镜头12(00:55-01:00)
+- 画面:黑鹰Rescue-1与Rescue-2低空起飞,加油机Shell-6升空。
+- 机位/运动:侧向跟拍,旋翼掠过镜头。
+- 关键元素:机腹绞盘、双侧机枪位、夜航识别灯、机身战术编号清晰。
+- 音效:旋翼重拍,地勤呼喊。
+- 台词/旁白:无线电「Rescue编队离场,航线A-9。」
+
+### 镜头13(01:00-01:05)
+- 画面:空中加油,护航机与加油机在云海上方并行。
+- 机位/运动:远景稳定镜头后推进到受油管连接点。
+- 关键元素:受油管锥套轻微摆动后稳定咬合,无异常火花。
+- 音效:稳定低频引擎噪音。
+- 台词/旁白:Shell-6「油量窗口三分钟,动作快。」
+
+### 镜头14(01:05-01:10)
+- 画面:波猫地面部队成网状推进,热成像无人机升空搜捕。
+- 机位/运动:高空俯拍+热成像视角切换。
+- 关键元素:车灯组成搜索弧线,士兵犬队前导。
+- 音效:引擎轰鸣、犬吠、短波口令。
+- 台词/旁白:波猫电台「封锁K-27到L-31,全线搜索。」
+
+### 镜头15(01:10-01:15)
+- 画面:Falcon-1躲在废弃输油管下,抬头望见搜索无人机掠过。
+- 机位/运动:主观视角仰拍,镜头轻颤。
+- 关键元素:尘土落在面罩,橙色信标被紧急关闭。
+- 音效:无人机电机嗡鸣从近到远。
+- 台词/旁白:Falcon-1(低声)「再晚十分钟我就暴露了。」
+
+### 镜头16(01:15-01:20)
+- 画面:Falcon-2在峡谷底打出红外闪码,远处有敌军灯柱扫来。
+- 机位/运动:长焦压缩景深,红外闪码特写。
+- 关键元素:膝盖血迹、沙地拖拽痕。
+- 音效:高频电报码、远处喊话回声。
+- 台词/旁白:Falcon-2「我能听见他们,快点。」
+
+### 镜头17(01:20-01:25)
+- 画面:黑鹰编队贴地穿越山谷,规避雷达,机枪手戒备。
+- 机位/运动:直升机舱门外侧跟拍,快速掠地。
+- 关键元素:旋翼扬沙,地形匹配航迹投影。
+- 音效:旋翼轰鸣压迫感增强。
+- 台词/旁白:机组长「保持无线静默,距目标12公里。」
+
+### 镜头18(01:25-01:30)
+- 画面:鹰酱空中分队反复盘旋搜寻,终于双点位重合确认。
+- 机位/运动:战术地图与夜空外景交叉剪辑。
+- 关键元素:K-27与L-31连线形成回收走廊。
+- 音效:系统提示音“Target Confirmed”。
+- 台词/旁白:指挥官「位置确认,执行双点同步回收。」
+
+### 镜头19(01:30-01:35)
+- 画面:Rescue-1悬停K-27上空,绞盘索下降。
+- 机位/运动:俯冲到近景,绞盘视角向下看。
+- 关键元素:地面火光反射在机腹,Falcon-1挥荧光棒。
+- 音效:钢索摩擦声、机枪上膛声。
+- 台词/旁白:救援员「看到你了,接索!」
+
+### 镜头20(01:35-01:40)
+- 画面:波猫地面火力突然开火,曳光弹扫向黑鹰。
+- 机位/运动:地面对空仰拍,快速抖动。
+- 关键元素:重机枪阵地压制、MANPADS射手完成瞄准准备。
+- 音效:密集枪声、金属击穿声。
+- 台词/旁白:波猫士兵「压住它!别让它降!」
+
+### 镜头21(01:40-01:45)
+- 画面:护航机俯冲压制,投下制导炸弹清除火力点。
+- 机位/运动:高速俯冲镜头切地爆炸全景。
+- 关键元素:先精确命中火力核心点,再出现破片与次生爆炸扩散。
+- 音效:破空尖啸后巨响。
+- 台词/旁白:护航飞行员「地面威胁压制中!」
+
+### 镜头22(01:45-01:50)
+- 画面:Rescue-2靠近L-31,准备接Falcon-2,地面车队逼近。
+- 机位/运动:机舱内向外拍,远处车灯快速放大。
+- 关键元素:Falcon-2拖伤腿冲刺,绿色信标闪烁。
+- 音效:引擎轰鸣、队员喊口令。
+- 台词/旁白:救援员「跑!再十米!」
+
+### 镜头23(01:50-01:55)
+- 画面:一枚肩射导弹命中Rescue-1尾梁,直升机失控。
+- 机位/运动:慢动作表现中弹点,然后急速旋转坠落。
+- 关键元素:尾桨碎裂,液压失效导致偏航失控,火星与碎片洒落。
+- 音效:告警蜂鸣连续拉满。
+- 台词/旁白:机组长「我们中弹,迫降失败!」
+
+### 镜头24(01:55-02:00)
+- 画面:Rescue-1撞上山坡爆炸,火球照亮峡谷。
+- 机位/运动:远景定镜,冲击波推沙而来。
+- 关键元素:残骸燃烧,弹药殉爆二次闪光。
+- 音效:爆炸闷响叠加耳鸣效果。
+- 台词/旁白:旁白「第一架黑鹰坠毁,回收窗口骤然收缩。」
+
+### 镜头25(02:00-02:05)
+- 画面:地面快速反应队由运输机空投到临时降落区。
+- 机位/运动:机腹舱门外拍,队员索降。
+- 关键元素:C-130级运输机低空掠过,红色舱灯明灭,队员按序离机。
+- 音效:风噪剧烈,索降扣具碰撞。
+- 台词/旁白:指挥官「地面队接管,强行打通撤离点。」
+
+### 镜头26(02:05-02:10)
+- 画面:Falcon-1被拉上Rescue-2,救援员给右臂注射止痛剂。
+- 机位/运动:机舱手持近景,节奏急促。
+- 关键元素:橙色信标熄灭,血迹染红手套。
+- 音效:呼喊、弹壳落舱声。
+- 台词/旁白:Falcon-1「还有一个人,别丢下他!」
+
+### 镜头27(02:10-02:15)
+- 画面:Falcon-2与地面队汇合,巷战式近距离交火爆发。
+- 机位/运动:平视跟跑镜头,快速切换掩体点。
+- 关键元素:废墟掩体崩裂、火花四溅、Falcon-2左腿拖步清晰。
+- 音效:突击步枪点射,手雷爆炸。
+- 台词/旁白:队长「烟幕弹!掩护伤员后撤!」
+
+### 镜头28(02:15-02:20)
+- 画面:运输机准备二次接应时被便携防空导弹命中右翼油箱。
+- 机位/运动:中远景追拍,命中瞬间闪白。
+- 关键元素:右侧机翼根部命中起火,燃油泄漏后拖尾燃烧。
+- 音效:巨大爆鸣,电流噼啪。
+- 台词/旁白:无线电「运输机中弹!重复,中弹!」
+
+### 镜头29(02:20-02:25)
+- 画面:运输机坠地爆炸,火焰蘑菇云升起。
+- 机位/运动:超远景静镜,地平线被火光吞没。
+- 关键元素:冲击波掀翻附近车辆。
+- 音效:低频冲击后环境声短暂真空。
+- 台词/旁白:旁白「运输机被摧毁,撤离计划只剩最后通道。」
+
+### 镜头30(02:25-02:30)
+- 画面:Rescue-2超低空穿插,试图带走Falcon-2与地面队。
+- 机位/运动:机头视角穿越电线塔与峡谷拐点。
+- 关键元素:曳光弹擦过机身,机体多处中弹,告警面板出现尾传动异常。
+- 音效:金属撞击、告警语音不断。
+- 台词/旁白:飞行员「坚持住,最后一次进场!」
+
+### 镜头31(02:30-02:35)
+- 画面:第二枚导弹命中Rescue-2腹部,直升机带火硬着陆后爆炸。
+- 机位/运动:侧后方跟拍到撞地翻滚。
+- 关键元素:主旋翼断裂飞散,机舱门被炸飞,机体翻滚后二次殉爆。
+- 音效:连续爆炸、旋翼断裂尖啸。
+- 台词/旁白:旁白「第二架黑鹰也被击毁。」
+
+### 镜头32(02:35-02:40)
+- 画面:幸存救援员与两名飞行员冲入废墟掩体,近距离枪战白热化。
+- 机位/运动:手持近景,跟随冲刺与卧倒。
+- 关键元素:子弹打碎混凝土,火星与粉尘充满画面。
+- 音效:枪声密集、耳麦里杂音尖叫。
+- 台词/旁白:队长「全员向北侧缺口突围!」
+
+### 镜头33(02:40-02:45)
+- 画面:护航战机再度空袭,炸开北侧封锁线,制造撤离窗口。
+- 机位/运动:空地交叉剪,先空中俯冲再地面仰视。
+- 关键元素:封锁阵地连环爆破,烟尘墙形成遮蔽。
+- 音效:炸弹连响、无线电倒计时。
+- 台词/旁白:护航飞行员「北线已开,窗口60秒!」
+
+### 镜头34(02:45-02:50)
+- 画面:备用撤离直升机(无编号)从烟幕中突入,救援员推送两名飞行员登机。
+- 机位/运动:地面仰拍到机舱内反打。
+- 关键元素:Falcon-2被拖上机舱时左腿包扎仍在,Falcon-1右臂受限下短点射掩护。
+- 音效:旋翼压制一切环境声,喊话靠吼。
+- 台词/旁白:救援员「人齐了!起飞!」
+
+### 镜头35(02:50-02:55)
+- 画面:直升机拉升脱离火网,地面仍有零星追击火力。
+- 机位/运动:后向追踪镜头,地面火线逐渐变小。
+- 关键元素:机舱内两名飞行员并排固定担架,医护紧急处理。
+- 音效:呼吸机、心率监测滴答声混合旋翼声。
+- 台词/旁白:Falcon-2(虚弱)「我们……还活着吗?」
+
+### 镜头36(02:55-03:00)
+- 画面:黎明前天际线,撤离机飞向海面方向;地面远处仍燃着三处残骸火点(运输机+两架黑鹰)。
+- 机位/运动:超远景缓慢拉远,最后定格。
+- 关键元素:火光映出战场轮廓,字幕淡入“救援成功,代价惨重”。
+- 音效:音乐转低沉弦乐,枪声远去。
+- 台词/旁白:旁白「两名飞行员获救,但这一夜,没人真正获胜。」
+
+## 统一画面生成约束(给AI视频模型)
+- 风格关键词:`cinematic war realism, high detail, volumetric smoke, dramatic lighting, handheld tension, tactical HUD overlay, desert canyon battlefield`
+- 画质关键词:`4k, ultra-detailed, film grain, motion blur, depth of field`
+- 禁止项:`no cartoon style, no cute style, no exaggerated proportions, no text watermark, no logo`
+- 人物一致性:两名飞行员伤情与信标颜色在全片保持一致,不可互换。
+- 物件一致性:黑鹰涂装、运输机编号风格、波猫地面车辆迷彩在跨镜头保持一致。
+- 时间连续性:夜间到拂晓过渡,光线需逐步变化,不可突变白天。
+- 连续伤痕规则:血迹扩散、灰尘堆积、装备磨损按时间递增,不可“重置”。
+- 镜头语言约束:爆炸不过曝、枪口焰不过度拉长、烟尘保留体积光层次。
+- 语种一致性:鹰酱侧仅英语、波猫侧仅波斯语;不得跨阵营混用口语。
+
+## 音频后期建议
+- BGM三段式:
+ - 00:00-01:00:低频压迫 + 战争环境声主导
+ - 01:00-02:30:节奏加速、打击乐增强
+ - 02:30-03:00:弦乐收束、留白
+- 枪炮声做空间方位:左/右声道随机位变化,增强临场感。
+- 关键对白建议保留无线电失真,提升军事纪实感。
+- 语言音色区分:英语通话保持北美军用电台质感;波斯语通话保持短波压缩感与环境底噪。
+
+## 声音与特效细节刻画清单(执行版)
+- 声音分轨建议(至少8轨):
+ - `DX`:角色对白/无线电(300Hz以下滚降,加入轻微带限失真)。
+ - `FX-GUN`:枪声与抛壳(近景强调机械复进声,远景以混响尾音为主)。
+ - `FX-EXP`:爆炸与破片(分“初爆/碎片/回响”三层,避免单层大轰鸣)。
+ - `FX-AIR`:固定翼与旋翼(区分掠过、悬停、远离三种多普勒曲线)。
+ - `FX-FOLEY`:脚步、布料、挂具碰撞、拖拽声。
+ - `AMB-DAYNIGHT`:风沙/城市远噪/战场底噪,按夜到黎明逐步抬高高频空气感。
+ - `UI`:HUD提示、告警蜂鸣、心率仪。
+ - `MUS`:三段式BGM。
+- 关键时间点声音重心:
+ - `00:20-00:35`(击落段):导弹尖啸由右后声像切入,命中瞬间做0.2-0.4秒闷听觉模拟。
+ - `01:30-02:00`(首轮回收段):旋翼低频与地面曳光弹破空声交替压制,对白仅保留关键词。
+ - `02:15-02:35`(连环战损段):运输机爆炸与Rescue-2坠毁分开设计频段,避免低频互相遮蔽。
+ - `02:45-03:00`(撤离段):枪声快速衰减到远景,心率监测与呼吸机接管听觉焦点。
+- 特效(VFX)颗粒度要求:
+ - 火焰颜色分层:近白芯 + 橙黄主体 + 黑烟边缘,不使用纯色“贴图火”。
+ - 破片运动遵循抛物线与空气阻力,远小近大,禁止匀速直线飞散。
+ - 曳光弹亮度受烟尘遮挡衰减,不可全程同亮。
+ - 夜战镜头保留暗部细节,避免“黑成一片”或“亮如白天”。
diff --git a/server/index.js b/server/index.js
index 4714761..f32a30f 100644
--- a/server/index.js
+++ b/server/index.js
@@ -23,6 +23,7 @@ app.use(
},
})
);
+app.use("/assets", express.static(path.join(repoRoot, "assets")));
app.use(express.static(path.join(__dirname, "public")));
app.get("/api/health", (_req, res) => {
@@ -475,4 +476,3 @@ const port = Number(process.env.PORT || 3000);
process.exit(1);
}
})();
-
diff --git a/server/public/index.html b/server/public/index.html
index c4bb3e4..066a162 100644
--- a/server/public/index.html
+++ b/server/public/index.html
@@ -3,530 +3,2274 @@
- AiVideo POC - Interactive
+ AI Video Workspace
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 00:00.0 / 00:10.0
+
+
+
+
+
+
+
+
Video
+
Audio
+
Caption
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ var MIN_DURATION = 0.4;
+ var SNAP_STEP = 0.1;
-
-
-
-
-