铸渊 ICE-GL-ZY001 LL-172-20260707 冰朔委托: 新建第 5 子仓, 给苍耳(人类主控) + 鉴影(人格体) 专用 原 guanghulab/video-ai-system/ 东西太多(225 文件) · 找不到 · 乱 迁移: ⊢ 16 个核心 .hdlp (VA-GATE / VA-LIGHTHOUSE / VA-BROADCAST / VA-SYSTEM-STATUS 等) ⊢ 17 个子目录 (agents/engines/protocols/tasks/tools/assets/knowledge/memory/docs/config/brain/director-brain/experience/feedback/issues/plans/reference-analysis) 排除: ⊢ outputs/ (视频产物) ⊢ test-input/ test-output/ (测试) ⊢ data/ (临时数据) ⊢ preview-001/002 (旧产片) ⊢ 旧分镜/旧提示词/旧导演编码 后续: ⊢ 老仓 guanghulab/video-ai-system/ 改写为已迁出占位 ⊢ 苍耳+鉴影 写新东西进本仓 ⊢ GLOBAL-SEARCH 加 cang-ying 仓库 铸渊 ICE-GL-ZY001 · 2026-07-07 D167 冰朔 ICE-GL∞ 主权
126 lines
4.6 KiB
JavaScript
126 lines
4.6 KiB
JavaScript
/**
|
|
* D136+ · 视频批量生成 · 导演编码 → Seedance API
|
|
* 用法: node generate-shots.js
|
|
*/
|
|
const { generateVideo } = require('./video-api-adapter');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const ENCODING_FILE = path.resolve(__dirname, '../outputs/付费修仙-ep01-director-encoding.json');
|
|
|
|
// D136+ 输出优先JZAO外置硬盘 · 本地fallback
|
|
const JZAO_SHOTS = '/Volumes/JZAO/铸渊-ICE-GL-ZY001/OUT-输出/视频/zai-fu-fei-xiu-xian/ep01';
|
|
const LOCAL_SHOTS = path.resolve(__dirname, '../outputs/shots');
|
|
const OUT_DIR = fs.existsSync(JZAO_SHOTS) ? JZAO_SHOTS : LOCAL_SHOTS;
|
|
|
|
async function main() {
|
|
const encoding = JSON.parse(fs.readFileSync(ENCODING_FILE, 'utf8'));
|
|
fs.mkdirSync(OUT_DIR, { recursive: true });
|
|
|
|
console.log(`[Generate] ${encoding.project} · ep${encoding.episode} · ${encoding.shots.length}镜`);
|
|
console.log(`[Generate] 输出: ${OUT_DIR}\n`);
|
|
|
|
const results = [];
|
|
for (let i = 0; i < encoding.shots.length; i++) {
|
|
const s = encoding.shots[i];
|
|
const prompt = buildPrompt(s, encoding);
|
|
|
|
console.log(`━━━ 镜${i + 1}/${encoding.shots.length}: ${s.id} ━━━`);
|
|
console.log(` 景别: ${s.framing} | 情绪: ${s.emotion?.type}(${s.emotion?.intensity}) | ${s.duration}s`);
|
|
console.log(` spatial_anchor: ${s.spatial_anchor}`);
|
|
console.log(` text_elements: ${s.text_elements}`);
|
|
console.log(` prompt: ${prompt.substring(0, 100)}...`);
|
|
|
|
const outputPath = path.join(OUT_DIR, `${encoding.project}-${encoding.episode}-${s.id}.mp4`);
|
|
if (fs.existsSync(outputPath)) {
|
|
console.log(` ✅ 已存在,跳过\n`);
|
|
results.push({ ...s, file: outputPath });
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
const result = await generateVideo({
|
|
prompt,
|
|
duration: s.duration || 5,
|
|
shotId: `${encoding.project}-${encoding.episode}-${s.id}`,
|
|
projectKey: `付费修仙/ep01`,
|
|
outputPath,
|
|
});
|
|
console.log(` ✅ ${path.basename(result.videoPath)}\n`);
|
|
results.push({ ...s, file: result.videoPath, taskId: result.taskId });
|
|
} catch (e) {
|
|
console.error(` ❌ ${e.message}\n`);
|
|
results.push({ ...s, file: null, error: e.message });
|
|
// 继续下一个
|
|
}
|
|
}
|
|
|
|
const resultFile = path.join(OUT_DIR, `${encoding.project}-${encoding.episode}-results.json`);
|
|
fs.writeFileSync(resultFile, JSON.stringify(results, null, 2));
|
|
const success = results.filter(r => r.file).length;
|
|
console.log(`\n═══ 完成: ${success}/${results.length} ═══`);
|
|
console.log(`结果: ${resultFile}`);
|
|
}
|
|
|
|
function buildPrompt(shot, encoding) {
|
|
const locks = encoding.continuity_locks;
|
|
|
|
// ═══ 上下文+编码+自然语言 三层协议 ═══
|
|
//
|
|
// [Context] 英文编码 · 告诉AI前面发生了什么 + 这个故事是什么
|
|
// 50词以内 → AI理解上下文 → 不自盲抽
|
|
//
|
|
// ⊢ 编码层: CHAR+PROP+ENV锁定
|
|
//
|
|
// ⊢ 场景层: 中文自然语言 → AI推理情节+原因
|
|
|
|
let prompt = '';
|
|
|
|
// ─── 上下文层: 英文编码 → 告诉AI前面发生了什么 ───
|
|
// 每镜都带:剧集摘要 + 前一个镜头的框架
|
|
if (encoding.episode_summary) {
|
|
prompt += `[Ep${encoding.episode} Summary] ${encoding.episode_summary}\n`;
|
|
}
|
|
if (encoding.prev_shots?.[shot.id]) {
|
|
prompt += `[Previous Shot] ${encoding.prev_shots[shot.id]}\n`;
|
|
}
|
|
if (prompt.length > 0) prompt += '\n';
|
|
|
|
// ─── 编码层: CHAR+PROP+ENV ───
|
|
if (shot.char_ref && locks?.characters?.[shot.char_ref]) {
|
|
prompt += `⊢ CHAR-003 Su Bai: 18yr male, white robe, black hair half-up, 175cm\n`;
|
|
}
|
|
|
|
if (shot.prop_ref && locks?.props?.[shot.prop_ref]) {
|
|
prompt += `⊢ PROP: vertical hanging wood sign, worn edges, 【天道宗】\n`;
|
|
}
|
|
if (shot.prop_ref_2 && locks?.props?.[shot.prop_ref_2]) {
|
|
prompt += `⊢ PROP: horizontal floor board, recruitment ad\n`;
|
|
}
|
|
|
|
if (shot.env && locks?.environments?.[shot.env]) {
|
|
prompt += `⊢ ENV: cultivation square, edge corner, golden sunlight\n`;
|
|
}
|
|
|
|
// ─── 场景层: 情节+原因 → AI推理 ───
|
|
if (encoding.scene) {
|
|
prompt += `\n⊢ Scene:\n ${encoding.scene}\n`;
|
|
}
|
|
|
|
// ─── 动作: 当前镜头 ───
|
|
prompt += `\n→ Shot: ${shot.framing}`;
|
|
if (shot.emotion?.type) prompt += ` | ${shot.emotion.type}`;
|
|
prompt += `\n`;
|
|
|
|
if (shot.action) {
|
|
prompt += `→ ${shot.action}\n`;
|
|
}
|
|
|
|
prompt += `⊢ Style: 3D animation, Chinese cultivation, cinematic lighting\n`;
|
|
prompt += `⊢ No: photorealism, cartoon, modern elements, watermark`;
|
|
|
|
return prompt;
|
|
}
|
|
|
|
main().catch(e => { console.error(e); process.exit(1); });
|