← back to Allnewsdaily
scripts/short/verify-variation.cjs
49 lines
"use strict";
const fs = require('fs');
const path = require('path');
const { execFileSync, spawnSync } = require('child_process');
const assert = require('node:assert/strict');
const { buildScript } = require('./build-script');
const root = path.resolve(__dirname, '../..');
const evidence = process.argv[2];
assert.ok(evidence, 'Pass a fresh evidence directory');
const data = path.join(root, 'data/short');
fs.mkdirSync(evidence, {recursive:true}); fs.mkdirSync(data, {recursive:true});
const headlines = [
'Fixture: The museum opened a new exhibition on Monday.',
'Fixture: The library added evening hours for visitors.',
'Fixture: The city published its annual transport report.',
'Fixture: The university announced three public science lectures.',
'Fixture: The park reopened its walking path on Tuesday.',
];
const results = [];
for (const date of ['2026-09-10','2026-09-11','2026-09-12']) {
const stories = {date, stories: (date === '2026-09-10' ? headlines : headlines.slice(0,1)).map((headline,i) => ({n:i+1,headline,outlet:'Fixture Civic Record '+(i+1)}))};
fs.writeFileSync(path.join(data,'stories.json'),JSON.stringify(stories,null,2));
const buildLog = execFileSync(process.execPath,[path.join(__dirname,'build-script.js')],{encoding:'utf8'});
const script = JSON.parse(fs.readFileSync(path.join(data,'script.json')));
const dir = path.join(evidence,script.format); fs.mkdirSync(dir,{recursive:true});
const reuse = process.argv.includes('--resume') && fs.existsSync(path.join(dir,'out.mp4'));
if (reuse) assert.deepEqual(JSON.parse(fs.readFileSync(path.join(dir,'script.json'))),script, 'Refuse stale media from a different script');
fs.copyFileSync(path.join(data,'stories.json'),path.join(dir,'stories.json'));
fs.copyFileSync(path.join(data,'script.json'),path.join(dir,'script.json'));
const log = reuse ? fs.readFileSync(path.join(dir,'render.log'),'utf8') : execFileSync(process.execPath,[path.join(__dirname,'render-short.js')],{encoding:'utf8',maxBuffer:20*1024*1024});
fs.writeFileSync(path.join(dir,'render.log'),buildLog+'\n'+log);
if (!reuse) for (const file of ['out.mp4','thumb.jpg']) fs.copyFileSync(path.join(data,file),path.join(dir,file));
const probe=JSON.parse(execFileSync('ffprobe',['-v','error','-show_streams','-show_format','-of','json',path.join(dir,'out.mp4')],{encoding:'utf8'}));
fs.writeFileSync(path.join(dir,'ffprobe.json'),JSON.stringify(probe,null,2));
const v=probe.streams.find(s=>s.codec_type==='video'),a=probe.streams.find(s=>s.codec_type==='audio');
assert.equal(v.width,1080); assert.equal(v.height,1920); assert.equal(v.codec_name,'h264'); assert.equal(v.pix_fmt,'yuv420p'); assert.equal(v.avg_frame_rate,'30/1'); assert.equal(a.codec_name,'aac');
assert.ok(+probe.format.duration < 60 && Math.abs(+probe.format.duration - script.totalSec) < 0.5);
const scratch = log.match(/retained scratch=(.+)/)[1];
fs.copyFileSync(path.join(scratch,'card1.png'),path.join(dir,'lead-card.png'));
results.push({format:script.format,duration:+probe.format.duration,dir,scratch,verdict:'PASS'});
console.log(JSON.stringify(results.at(-1)));
}
const script=buildScript({date:'2026-09-10',stories:[{headline:'Fixture fact.',outlet:'Fixture Record'}]});
script.totalSec=61;fs.writeFileSync(path.join(data,'script.json'),JSON.stringify(script));
const bad=spawnSync(process.execPath,[path.join(__dirname,'render-short.js')],{encoding:'utf8'});
assert.notEqual(bad.status,0); assert.match(bad.stderr,/58 seconds/);
fs.writeFileSync(path.join(evidence,'negative-render.log'),bad.stdout+bad.stderr);
fs.writeFileSync(path.join(evidence,'results.json'),JSON.stringify(results,null,2));