70 lines
2.8 KiB
JavaScript
70 lines
2.8 KiB
JavaScript
// 步骤⑦ storyboard: doubao PRO 模型拆解剧本
|
||
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-1-pro-260628',
|
||
messages: [{ role: 'system', content: '你是一个顶级影视分镜师,专精科幻恐怖短剧。' }, { 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('豆包 PRO 拆解剧本...');
|
||
var t0 = Date.now();
|
||
var req = https.request(options, function(res) {
|
||
var body = '';
|
||
res.on('data', function(chunk) { body += chunk; });
|
||
res.on('end', function() {
|
||
var elapsed = ((Date.now() - t0) / 1000).toFixed(1);
|
||
console.log('elapsed: ' + elapsed + 's');
|
||
try {
|
||
var data = JSON.parse(body);
|
||
if (data.error) { console.error('ERROR:', JSON.stringify(data.error)); process.exit(1); }
|
||
var content = data.choices[0].message.content;
|
||
console.log('tokens:', JSON.stringify(data.usage));
|
||
|
||
var json = content;
|
||
var m = json.match(/```(?:json)?\s*([\s\S]*?)```/);
|
||
if (m) json = m[1].trim();
|
||
|
||
var outPath = path.join(__dirname, '..', 'projects', 'deep-sea-voyage', 'STORYBOARD-AI-PRO.json');
|
||
fs.writeFileSync(outPath, json, 'utf-8');
|
||
console.log('SAVED:', outPath);
|
||
console.log('---\n' + json);
|
||
} catch(e) { console.error(e.message); }
|
||
});
|
||
});
|
||
req.on('error', function(e) { console.error(e.message); });
|
||
req.setTimeout(300000, function() { req.destroy(); console.error('TIMEOUT 300s'); });
|
||
req.write(payload);
|
||
req.end();
|