铸渊 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∞ 主权
131 lines
4.2 KiB
JavaScript
131 lines
4.2 KiB
JavaScript
/**
|
||
* 光湖视频AI系统 · 导演编码适配器
|
||
* D136+ · 铸渊 ICE-GL-ZY001
|
||
*
|
||
* 输入:Agent_06 导演编码(JSON)
|
||
* 输出:video-editor.js 的 edit() 参数
|
||
*
|
||
* 使用:
|
||
* const { adapt } = require('./hldp-director-adapter');
|
||
* const editorInput = adapt(directorEncoding, { shotsDir: './outputs/shots/' });
|
||
* await edit(editorInput);
|
||
*/
|
||
|
||
// ==================== 景别 → zoom ====================
|
||
const FRAMING_ZOOM = {
|
||
'远景': { from: 1.0, to: 1.0 },
|
||
'全景': { from: 1.0, to: 1.05 },
|
||
'中景': { from: 1.0, to: 1.10 },
|
||
'近景': { from: 1.0, to: 1.15 },
|
||
'特写': { from: 1.0, to: 1.25 },
|
||
'大特写': { from: 1.0, to: 1.5 },
|
||
};
|
||
|
||
// ==================== 情绪类型 → 调色 ====================
|
||
const EMOTION_COLOR = {
|
||
'悬': { contrast: 1.2, saturation: 0.9, brightness: -0.05 },
|
||
'恐': { contrast: 1.2, saturation: 0.9, brightness: -0.05 },
|
||
'怒': { contrast: 1.15, saturation: 1.1, brightness: 0 },
|
||
'燃': { contrast: 1.15, saturation: 1.1, brightness: 0 },
|
||
'甜': { contrast: 1.0, saturation: 1.15, brightness: 0.05 },
|
||
'暖': { contrast: 1.0, saturation: 1.15, brightness: 0.05 },
|
||
'冷': { contrast: 0.95, saturation: 0.85, brightness: -0.08 },
|
||
'哀': { contrast: 0.95, saturation: 0.85, brightness: -0.08 },
|
||
'爽': { contrast: 1.1, saturation: 1.1, brightness: 0.02 },
|
||
'震': { contrast: 1.1, saturation: 1.1, brightness: 0.02 },
|
||
};
|
||
|
||
// ==================== 强度 → trim时长 ====================
|
||
function intensityToTrim(intensity) {
|
||
if (intensity <= 3) return 2.0;
|
||
if (intensity <= 6) return 3.0;
|
||
if (intensity <= 8) return 3.5;
|
||
return 4.5; // 9-10: 定格感
|
||
}
|
||
|
||
// ==================== 节奏 → 过渡类型 ====================
|
||
function rhythmToTransition(rhythm) {
|
||
switch (rhythm) {
|
||
case '铺垫': case '建立': case '余波': case '余韵':
|
||
return 'fade';
|
||
case '爬升': case '高潮': case '反转': case '转折':
|
||
return 'cut';
|
||
default: return 'fade';
|
||
}
|
||
}
|
||
|
||
// ==================== 主适配函数 ====================
|
||
|
||
/**
|
||
* @param {object} dc - 导演编码 (Agent_06 输出)
|
||
* @param {object} opts
|
||
* @param {string} [opts.shotsDir] - 分镜视频文件目录
|
||
* @param {string} [opts.voiceFile] - 配音文件
|
||
* @param {string} [opts.bgmFile] - BGM文件
|
||
* @param {string} [opts.srtFile] - 字幕文件
|
||
* @param {object} [opts.resolution] - { w, h }
|
||
* @param {number} [opts.fps]
|
||
* @param {string} [opts.output] - 输出路径
|
||
* @returns {object} video-editor.js edit() 参数
|
||
*/
|
||
function adapt(dc, opts = {}) {
|
||
const shotsDir = opts.shotsDir || './outputs/shots/';
|
||
const timeline = [];
|
||
|
||
for (const s of dc.shots) {
|
||
const framing = FRAMING_ZOOM[s.framing] || FRAMING_ZOOM['中景'];
|
||
const trim = s.duration || intensityToTrim(s.emotion?.intensity || 5);
|
||
|
||
const shotEntry = {
|
||
shot: `${shotsDir}${dc.project}-${dc.episode}-${s.id}.mp4`,
|
||
trim,
|
||
transition: s.transition || rhythmToTransition(s.rhythm),
|
||
keyframes: s.keyframes || {},
|
||
};
|
||
|
||
// 景别映射到 keyframes.zoom(如果导演没有显式指定)
|
||
if (!shotEntry.keyframes.zoom && framing.from !== framing.to) {
|
||
shotEntry.keyframes.zoom = framing;
|
||
}
|
||
|
||
timeline.push(shotEntry);
|
||
}
|
||
|
||
// 取主导情绪的调色参数
|
||
const mainEmotion = dc.emotion_main || '悬';
|
||
const colorGrade = EMOTION_COLOR[mainEmotion] || EMOTION_COLOR['悬'];
|
||
|
||
const result = {
|
||
timeline,
|
||
colorGrade,
|
||
resolution: opts.resolution || { w: 1920, h: 1080 },
|
||
fps: opts.fps || 24,
|
||
output: opts.output || `./outputs/${dc.project}-${dc.episode}-final.mp4`,
|
||
};
|
||
|
||
if (opts.voiceFile) {
|
||
result.audio = { ...(result.audio || {}), voice: opts.voiceFile };
|
||
}
|
||
if (opts.bgmFile) {
|
||
result.audio = { ...(result.audio || {}), bgm: opts.bgmFile, bgmVolume: 0.3 };
|
||
}
|
||
if (opts.srtFile) {
|
||
result.subtitle = opts.srtFile;
|
||
}
|
||
|
||
// 附加元信息
|
||
result._meta = {
|
||
project: dc.project,
|
||
episode: dc.episode,
|
||
tempo: dc.tempo,
|
||
emotion_main: mainEmotion,
|
||
hooks: dc.hooks,
|
||
shotCount: timeline.length,
|
||
totalDuration: timeline.reduce((sum, t) => sum + t.trim, 0),
|
||
};
|
||
|
||
return result;
|
||
}
|
||
|
||
module.exports = { adapt, FRAMING_ZOOM, EMOTION_COLOR, intensityToTrim, rhythmToTransition };
|