// 步骤⑨: 导演编码适配 (storyboard+prompts → director encoding) const fs = require('fs'); const path = require('path'); const PROJ = path.join(__dirname, '..', 'projects', 'deep-sea-voyage'); // 合并镜头数据(从 STORYBOARD + PROMPTS + SCRIPT-LOCK) const SHOTS = [ { shot_id: 'M01', duration: 8, source_text: '画面漆黑→林昊主观视角缓缓睁眼→天花板灯泡忽明忽暗→破旧船员宿舍→舱门布满铁锈', subject: 'CRAMPED CREW DORM · TWO THREE-TIER BUNKS · RUSTED WATERTIGHT HATCH', action: 'Darkness → eyes slowly open → flickering bulb reveals dilapidated dorm → camera POV breathing', camera: 'Static POV, subtle breathing bob, 9:16 vertical', framing: 'POV · 主观视角仰视', subtitle: null, voice_line: null, char_refs: [], env_refs: ['ENV-001'], prop_refs: [], negative: 'No people visible. No round porthole. Window must be rectangular rivet-framed inspection port.' }, { shot_id: 'M02', duration: 10, source_text: '林昊看向双手→布满老茧机油→轰隆巨响船舱震颤→坐起抓床头铁杆→特写铁杆上"秦山号"', subject: 'LIN HAO (CHAR-001) · Hands with calluses · Bed pole with 秦山号 mark', action: 'Lin Hao examines hands → loud BOOM shakes cabin → sits up grabbing bed post → close-up on 秦山号 engraving', camera: 'Close-up hands → medium full body → push-in to close-up bed pole mark. Camera shakes on impact.', framing: 'Close-up → Medium → Close-up', subtitle: '这……这里是什么地方?', voice_line: '秦山号……这……这是船舱?', char_refs: ['CHAR-001'], env_refs: ['ENV-001'], prop_refs: [], negative: 'No other people in dorm. 秦山号 characters must be clearly legible on pole.' }, { shot_id: 'M03', duration: 8, source_text: '舱外极速沉重脚步声→猛转头看舱门→矩形观察窗黑影闪过→震动停→跳下床险些摔倒扶床沿', subject: 'LIN HAO (CHAR-001) · Rusted hatch door with rectangular inspection port · Shadow blur', action: 'Heavy footsteps outside → head whip to door → dark shadow streaks past rectangular window → jumps off bed, stumbles from tilted floor', camera: 'Medium shot → whip pan to door → brief POV through window → medium as he stumbles', framing: 'Medium · Whip pan · POV', subtitle: '谁!?', voice_line: '整个船体都倾斜了?怎么回事?', char_refs: ['CHAR-001'], env_refs: ['ENV-002'], prop_refs: [], negative: 'Shadow must be BLUR, not clearly visible. Window is RECTANGULAR, not round. Ship tilt visually clear.' }, { shot_id: 'M04', duration: 10, source_text: '稳住身形走向舱门→擦拭观察窗内侧玻璃→外侧仍被厚重灰尘糊住→拧动把手吱呀声纹丝不动→看掌心铁锈', subject: 'LIN HAO (CHAR-001) · Rectangular observation window · Rusty door handle', action: 'Walks tilted toward door → wipes inner glass (outer stays dirty) → twists handle with screech → handle stays jammed → examines rust on palm', camera: 'Medium tracking shot → close-up wipes window → close-up hand on handle. Dutch angle for tilt.', framing: 'Medium · Close-up · Close-up', subtitle: '有人吗?!', voice_line: '刚才跑过去的是谁?我……我又是谁?', char_refs: ['CHAR-001'], env_refs: ['ENV-002'], prop_refs: [], negative: 'Inner glass wiped clean, outer glass stays dusty. Four-layer tempered glass visible on window frame.' }, { shot_id: 'M05', duration: 8, source_text: '瞥见门缝下渗出黑色液压油→转身看见下铺旁的黑色工具包→快步走过去拉开拉链', subject: 'LIN HAO (CHAR-001) · Hydraulic oil pool · Black tool bag (PROP-001)', action: 'Notices black hydraulic oil under door gap → turns → sees large worn tool bag on suspended table → walks over and unzips it', camera: 'Close-up oil pool → medium shot turn → close-up unzipping bag', framing: 'Close-up · Medium · Close-up', subtitle: '这是什么破地方。', voice_line: null, char_refs: ['CHAR-001'], env_refs: ['ENV-002'], prop_refs: ['PROP-001'], negative: 'Oil must be visibly pooling on tilted floor. Bag must look large, worn, industrial.' }, { shot_id: 'M06', duration: 6, source_text: '工具包内物品:手电筒、备用电源、绷带、半米管钳、军绿水壶、破旧工牌→工牌特写:编号000768/林昊/岗位模糊/照片人脸被利器划烂', subject: 'Tool bag contents · PROP-002 ID badge · PROP-003 pipe wrench · PROP-004 flashlight', action: 'Slow pan across bag interior items → push to extreme close-up on badge: serial 000768, name 林昊, job illegible, photo scratched out', camera: 'Close-up slow pan → extreme close-up badge', framing: 'Close-up · Extreme close-up', subtitle: '林昊?这是我吗?', voice_line: null, char_refs: [], env_refs: [], prop_refs: ['PROP-001', 'PROP-002', 'PROP-003', 'PROP-004'], negative: 'Badge photo face MUST be visibly scratched out by sharp object. Text 000768 and 林昊 must be legible.' }, { shot_id: 'M07', duration: 9, source_text: '猛抬头→矩形观察窗外黑影再次闪过更近更快→警报变急促→面露惧色自语呼吸急促→背起工具包抄管钳到门前', subject: 'LIN HAO (CHAR-001) · Rectangular observation window · Tool bag · Pipe wrench', action: 'Head snaps up → shadow flashes past window closer → alarm quickens → fear on face → shoulders bag, grabs pipe wrench, strides to door', camera: 'Medium snap up → whip pan to window → back to terrified face → medium arm-up action', framing: 'Medium · Whip pan · Close-up', subtitle: '这到底是什么东西?', voice_line: '不能坐以待毙!', char_refs: ['CHAR-001'], env_refs: ['ENV-002'], prop_refs: ['PROP-001', 'PROP-003'], negative: 'Shadow closer and darker than M03. Pipe wrench visible at half-meter length.' }, { shot_id: 'M08', duration: 10, source_text: '管钳卡住门把手猛用力纹丝不动→铁锈屑飘落→盯液压油渍目光一凛→举管钳冲液压凸起狠狠砸下→金属变形泄压蒸汽喷出→再撬把手缓缓转动', subject: 'Door handle · Pipe wrench (PROP-003) · Hydraulic bulge · ENV-002', action: 'Wrench clamped on handle → pull with full force, handle stays → rust flakes → eyes lock on hydraulic fluid → raises wrench high → smashes hydraulic bulge → metal deforms, white vapor hisses → pries again, handle slowly turns → faint smile', camera: 'Close-up wrench+handle → medium raise → impact shake → hold on hissing vapor → close-up handle turning', framing: 'Close-up · Medium · Impact shake · Close-up', subtitle: '还是不行。', voice_line: '果然……', char_refs: [], env_refs: ['ENV-002'], prop_refs: ['PROP-003'], negative: 'Impact should show vapor/fog, not sparks. Hydraulic fluid does not spark. Handle turns SLOWLY.' }, { shot_id: 'M09', duration: 12, source_text: '砰!黑影砸在矩形观察窗外→一只手指甲全脱指尖白骨血肉模糊滑下留五道暗红血痕→半人半孢子脸贴玻璃:右半边男人脸苍白流泪,左半边皮肤透明隆起颗粒蠕动黑色菌膜孢子孔洞喷孢子雾', subject: 'Rectangular observation window (ENV-002) · Mutilated hand · Halfling spore monster face (CHAR-002)', action: 'BANG → shadow slams window → hand with torn-off nails and exposed bone slides down leaving 5 dark blood streaks → face presses glass: right side pale crying man, left side translucent skin with writhing granules, torn mouth with pulsing spore pits, black spore mist puffing with each breath', camera: 'Medium → impact shake → slow dolly push to window → extreme close-up monster face → push on spore mist', framing: 'Medium · Slow dolly · Extreme close-up', subtitle: null, voice_line: null, char_refs: ['CHAR-002'], env_refs: ['ENV-002'], prop_refs: [], negative: 'Blood appears nearly black under cold blue light. Human half should evoke PITY not anger. Spore mist is BLACK and particulate. Face pressed against glass with slight distortion.' }, { shot_id: 'M10', duration: 5, source_text: '林昊僵在原地瞳孔剧烈收缩管钳发抖→画面骤然全黑警报持续', subject: 'LIN HAO (CHAR-001) · Pipe wrench trembling', action: 'Frozen in place → pupils contracting violently → pipe wrench shaking in grip → slow fade to pitch black', camera: 'Close-up face terror → extreme close-up pupils → dissolve to black', framing: 'Close-up · Extreme close-up · Black', subtitle: null, voice_line: null, char_refs: ['CHAR-001'], env_refs: [], prop_refs: ['PROP-003'], negative: 'Wrench trembling must be visible. Transition to black must feel like camera losing power.' } ]; var lines = []; lines.push('# 深海迷航 · EP01 · DIRECTOR-ENCODING'); lines.push('# 步骤⑨: 导演编码 · 2026-07-10 · 耳耳蛋 ICE-GL-耳耳蛋'); lines.push('# 10镜 · 75s · Seedance 2.0 2.x · 720p'); lines.push(''); for (var i = 0; i < SHOTS.length; i++) { var s = SHOTS[i]; lines.push('---'); lines.push(''); lines.push('## ' + s.shot_id + ' · ' + s.duration + 's · ' + s.framing); lines.push(''); lines.push('| 字段 | 值 |'); lines.push('|------|------|'); lines.push('| shot_id | ' + s.shot_id + ' |'); lines.push('| duration | ' + s.duration + 's |'); lines.push('| source_text | ' + s.source_text + ' |'); lines.push('| framing | ' + s.framing + ' |'); lines.push('| subject | ' + s.subject + ' |'); lines.push('| action | ' + s.action + ' |'); lines.push('| camera | ' + s.camera + ' |'); if (s.subtitle) lines.push('| subtitle | ' + s.subtitle + ' |'); if (s.voice_line) lines.push('| voice_line | ' + s.voice_line + ' |'); lines.push('| char_refs | ' + (s.char_refs.length ? s.char_refs.join(', ') : 'N/A') + ' |'); lines.push('| env_refs | ' + (s.env_refs.length ? s.env_refs.join(', ') : 'N/A') + ' |'); lines.push('| prop_refs | ' + (s.prop_refs.length ? s.prop_refs.join(', ') : 'N/A') + ' |'); lines.push('| negative | ' + s.negative + ' |'); lines.push(''); lines.push('```'); lines.push(s.negative); lines.push('```'); lines.push(''); } lines.push('---'); lines.push(''); lines.push('## 资产引用汇总'); lines.push(''); lines.push('| 资产 | 镜号 |'); lines.push('|------|------|'); var assetMap = {}; for (var j = 0; j < SHOTS.length; j++) { var s2 = SHOTS[j]; var allRefs = [].concat( s2.char_refs.map(function(r) { return 'CHAR: ' + r; }), s2.env_refs.map(function(r) { return 'ENV: ' + r; }), s2.prop_refs.map(function(r) { return 'PROP: ' + r; }) ); allRefs.forEach(function(ref) { if (!assetMap[ref]) assetMap[ref] = []; assetMap[ref].push(s2.shot_id); }); } Object.keys(assetMap).sort().forEach(function(k) { lines.push('| ' + k + ' | ' + assetMap[k].join(', ') + ' |'); }); lines.push(''); lines.push('> ⊢ 耳耳蛋 ICE-GL-耳耳蛋 · D181 · 2026-07-10'); lines.push('> ⊢ 国作登字-2026-A-00037559'); var outPath = path.join(PROJ, 'DIRECTOR-ENCODING-EP01.hdlp'); fs.writeFileSync(outPath, lines.join('\n'), 'utf-8'); console.log('✅ SAVED: ' + outPath); console.log('10镜 · 导演编码完成');