cang-ying/video-ai-system/tools/run_storyboard.js
Guanghu Domestic Migration a2fa7d57d8 chore: import sanitized domestic snapshot for REPO-005
Source snapshot: 23037fa3a2e9b0597162735755e92fc763bf4d94
2026-07-17 15:55:48 +08:00

72 lines
2.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 步骤⑦ storyboard: doubao lite 模型拆解剧本
const https = require('https');
const fs = require('fs');
const path = require('path');
const ENV_PATH = path.join(__dirname, '..', '..', '.env');
const ARK_KEY = fs.readFileSync(ENV_PATH, 'utf-8').match(/ARK_API_KEY=(.+)/)[1].trim();
const SCRIPT_PATH = path.join(__dirname, '..', 'projects', 'deep-sea-voyage', 'EP01-SCRIPT-LOCK.hdlp');
const script = fs.readFileSync(SCRIPT_PATH, 'utf-8');
const prompt = `请将以下短剧剧本第1集拆解为结构化分镜严格输出JSON格式。
要求:
- 按镜头拆分,每个镜头对应一个动作/反应/信息增量
- 每镜包含shot_number(S01-SXX), description(中文50字内), camera(特写/近景/中景/全景/POV), duration(秒), type(establishing/action/reaction/closeup/transition), characters(角色列表), scenes(场景列表), props(道具列表)
输出示例:
{"episode":1,"shots":[{"shot_number":"S01","description":"画面漆黑,警报声滴滴","camera":"POV","duration":3,"type":"establishing","characters":[],"scenes":["船员宿舍"],"props":[],"dialogue":"滴滴滴滴..."}]}
剧本:
${script}`;
const payload = JSON.stringify({
model: 'doubao-seed-2-0-lite-260215',
messages: [
{ role: 'user', content: prompt }
],
temperature: 0.2,
max_tokens: 4096
});
const options = {
hostname: 'ark.cn-beijing.volces.com',
path: '/api/v3/chat/completions',
method: 'POST',
headers: {
'Authorization': 'Bearer ' + ARK_KEY,
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload, 'utf-8')
}
};
console.log('豆包 lite 拆解剧本...');
const t0 = Date.now();
const req = https.request(options, (res) => {
let body = '';
res.on('data', (chunk) => { body += chunk; });
res.on('end', () => {
var elapsed = ((Date.now() - t0) / 1000).toFixed(1);
console.log('elapsed: ' + elapsed + 's');
try {
const data = JSON.parse(body);
if (data.error) { console.error('ERROR:', data.error); process.exit(1); }
const content = data.choices?.[0]?.message?.content || '';
console.log('tokens:', JSON.stringify(data.usage));
let json = content;
const m = json.match(/```(?:json)?\s*([\s\S]*?)```/);
if (m) json = m[1].trim();
const outPath = path.join(__dirname, '..', 'projects', 'deep-sea-voyage', 'STORYBOARD-AI.json');
fs.writeFileSync(outPath, json, 'utf-8');
console.log('SAVED:', outPath);
console.log('---\n' + json);
} catch(e) { console.error(e.message); }
});
});
req.on('error', (e) => console.error(e.message));
req.write(payload);
req.end();