승인된 Blender 컷의 실제 합성과 최종 검수 근거 추가
This commit is contained in:
@@ -1,26 +1,46 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import path from 'node:path';
|
||||
import {artifact, prepareData, projectDir, read, validateInputs} from './data.mjs';
|
||||
import {loadInputs, prepareData, validateInputs, measured, absolute} from './data.mjs';
|
||||
|
||||
const project = read(path.join(projectDir, 'project.json'));
|
||||
const cuts = artifact('07-cuts').payload.cuts;
|
||||
const images = artifact('11-images').payload.result.frames;
|
||||
const scenes = artifact('08-scenes').payload;
|
||||
validateInputs(project, cuts, images, scenes);
|
||||
const data = prepareData();
|
||||
const inputs = loadInputs();
|
||||
validateInputs(inputs.project, inputs.context, inputs.anchors);
|
||||
const data = prepareData(inputs);
|
||||
assert.equal(data.visual_engine, 'Blender');
|
||||
assert.equal(data.clips.filter((c) => c.video_path && c.anchors).length, 31);
|
||||
assert.equal(data.clips.reduce((n, c) => n + c.frames, 0), 5528);
|
||||
for (const c of data.clips.filter((c) => c.boxes)) for (const box of c.boxes) {
|
||||
assert(box[1] >= 660 && box[2] < 430, `${c.id}: guide pixels confused with droplet body`);
|
||||
const cases = [
|
||||
['scenes 미승인', (p) => {p.reviews.find((r) => r.review_id === 'scenes').decision = 'pending';}],
|
||||
['옛 승인', (p) => {p.reviews.find((r) => r.review_id === 'scenes').artifact_refs[1].revision = 2;}],
|
||||
['stale 결과', (p) => {p.stages.find((s) => s.stage_id === '12-motion').status = 'stale';}],
|
||||
['다른 현재 경로', (p) => {p.stages.find((s) => s.stage_id === '12-motion').artifact_path = 'foreign.json';}],
|
||||
['다른 선행 버전', (p, c) => {c['12-motion'].inputs[2].revision = 1;}],
|
||||
['옛 엔진', (p) => {p.settings.visual_engine = 'Image';}],
|
||||
['누락 컷', (p, c) => {c['12-motion'].payload.result.clips.pop();}],
|
||||
['미검증 컷', (p, c) => {c['12-motion'].payload.result.clips[0].media.verified = false;}],
|
||||
['다른 시각 버전', (p, c) => {c['12-motion'].payload.result.clips[0].media.path = 'projects/water-hydrogen-bond-surface-tension/stages/12-motion/r1/clip.mp4';}],
|
||||
['누락 끝점', (p, c) => {c['11-images'].payload.result.frames.pop();}],
|
||||
['프로필 혼입', (p, c) => {c['12-motion'].payload.request.render_profile.samples = 32;}],
|
||||
['원본 혼입', (p, c, a) => {a.source_sha256 = '0'.repeat(64);}],
|
||||
['시간 격자 오류', (p, c) => {c['07-cuts'].payload.cuts[1].start_ms += 1;}],
|
||||
['연속 경계 불일치', (p, c) => {c['11-images'].payload.result.frames.find((f) => f.frame_id === 'c02-start').media.path = c['11-images'].payload.result.frames[2].media.path + 'wrong.png';}],
|
||||
['다른 Scene 앵커', (p, c, a) => {a.cuts[0].scene_name = 'WrongScene';}],
|
||||
['움직임 키 누락', (p, c, a) => {a.cuts.find((a) => a.motion.some((m) => m.animated)).motion.find((m) => m.animated).keys.pop();}],
|
||||
['옛 대표 원본', (p, c) => {c['08-scenes'].payload.preview.scene_file.path = 'projects/water-hydrogen-bond-surface-tension/stages/08-scenes/r1/old.blend';}],
|
||||
['미검증 대표 화면', (p, c) => {c['08-scenes'].payload.preview.samples[0].media.verified = false;}],
|
||||
];
|
||||
for (const [name, mutate] of cases) {
|
||||
const {project, context, anchors} = structuredClone(inputs);
|
||||
mutate(project, context, anchors);
|
||||
assert.throws(() => validateInputs(project, context, anchors), undefined, name);
|
||||
}
|
||||
for (const mutate of [
|
||||
(p, c, i) => {p.reviews.find((r) => r.review_id === 'scenes').decision = 'pending';},
|
||||
(p, c, i) => {i.pop();},
|
||||
(p, c, i) => {i[0].media.verified = false;},
|
||||
(p, c, i) => {c[1].start_ms += 20;},
|
||||
(p, c, i) => {i.find((f) => f.frame_id === 'c02-start').media.path = 'wrong.png';},
|
||||
assert.throws(() => measured(absolute(data.clips[1].video_path), data.clips[0].end_ms), /실제 시간 불일치/);
|
||||
assert.throws(() => measured(absolute('projects/water-hydrogen-bond-surface-tension/missing.mp4'), 20));
|
||||
for (const [name, mutate] of [
|
||||
['없는 통합 WAV', (i) => {i.context['06-tts'].payload.result.narration.path = 'projects/water-hydrogen-bond-surface-tension/media/06-tts/r1/missing.wav';}],
|
||||
['미검증 단위 WAV', (i) => {i.context['06-tts'].payload.result.files[0].media.verified = false;}],
|
||||
['실측 WAV 시간 오류', (i) => {i.context['06-tts'].payload.result.files[0].media.duration_ms += 20;}],
|
||||
['실제 원본 SHA 오류', (i) => {i.context['11-images'].payload.result.scene_file.sha256 = '0'.repeat(64); i.anchors.source_sha256 = '0'.repeat(64);}],
|
||||
]) {
|
||||
const [p, c, i] = structuredClone([project, cuts, images]);
|
||||
mutate(p, c, i);
|
||||
assert.throws(() => validateInputs(p, c, i, scenes));
|
||||
const changed = structuredClone(inputs); mutate(changed);
|
||||
assert.throws(() => prepareData(changed), undefined, name);
|
||||
}
|
||||
console.log('Actual inputs and failure checks passed: missing approval/frame, unverified media, timing gap and discontinuity.');
|
||||
console.log(`실제 Blender 입력과 ${cases.length + 6}개 거부 사례 통과: 31컷·62끝점·38자막·5528프레임`);
|
||||
|
||||
Reference in New Issue
Block a user