// Quick audit script to inspect all lesson packages const fs = require("fs"); const path = require("path"); // Generated packages const genDir = path.join(__dirname, "../../data/teaching/social-science/generated"); const histDir = path.join(__dirname, "../../data/teaching/history"); function auditPackage(filePath) { const d = JSON.parse(fs.readFileSync(filePath, "utf8")); const visualKinds = {}; d.scenes.forEach(s => { visualKinds[s.visual.kind] = (visualKinds[s.visual.kind] || 0) + 1; }); const sections = [...new Set(d.scenes.map(s => s.section))]; const hasImages = d.scenes.filter(s => s.visual.image).length; const totalWords = d.scenes.reduce((sum, s) => sum + s.narration.split(/\s+/).length, 0); return { file: path.basename(filePath), chapterId: d.chapterId, subject: d.subject, discipline: d.discipline || "unknown", chapterTitle: d.chapterTitle, chapterNumber: d.chapterNumber, bookPart: d.bookPart, targetDuration: d.targetDurationMinutes, teachingMode: d.teachingMode, sceneCount: d.scenes.length, totalWords, sections, visualKinds, scenesWithImages: hasImages, sourceEdition: d.sourceEdition, }; } console.log("=== GENERATED PACKAGES ==="); const genFiles = fs.readdirSync(genDir).filter(f => f.endsWith(".json")).sort(); genFiles.forEach(f => { const info = auditPackage(path.join(genDir, f)); console.log(`\n--- ${info.chapterId} ---`); console.log(` Title: ${info.chapterTitle}`); console.log(` Discipline: ${info.discipline} | Book: ${info.bookPart} | Ch#: ${info.chapterNumber}`); console.log(` Scenes: ${info.sceneCount} | Words: ${info.totalWords} | Images: ${info.scenesWithImages}`); console.log(` Target: ${info.targetDuration}min | Mode: ${info.teachingMode}`); console.log(` Visual kinds:`, JSON.stringify(info.visualKinds)); console.log(` Sections: [${info.sections.join(", ")}]`); }); console.log("\n\n=== HISTORY PACKAGES ==="); const histFiles = fs.readdirSync(histDir).filter(f => f.endsWith(".json")).sort(); histFiles.forEach(f => { const info = auditPackage(path.join(histDir, f)); console.log(`\n--- ${info.chapterId} ---`); console.log(` Title: ${info.chapterTitle}`); console.log(` Discipline: ${info.discipline} | Book: ${info.bookPart} | Ch#: ${info.chapterNumber}`); console.log(` Scenes: ${info.sceneCount} | Words: ${info.totalWords} | Images: ${info.scenesWithImages}`); console.log(` Target: ${info.targetDuration}min | Mode: ${info.teachingMode}`); console.log(` Visual kinds:`, JSON.stringify(info.visualKinds)); console.log(` Sections: [${info.sections.join(", ")}]`); }); // Check existing 1080p outputs console.log("\n\n=== EXISTING 1080p MP4 OUTPUTS ==="); const outputRoot = path.join(__dirname, "../../outputs/video/social-science"); function findMp4s(dir) { if (!fs.existsSync(dir)) return []; const results = []; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const full = path.join(dir, entry.name); if (entry.isDirectory()) results.push(...findMp4s(full)); else if (entry.name.endsWith("-1080p.mp4")) results.push(full); } return results; } const mp4s = findMp4s(outputRoot); mp4s.forEach(f => { const stat = fs.statSync(f); console.log(` ${path.relative(outputRoot, f)} (${(stat.size / 1024 / 1024).toFixed(1)} MB)`); }); console.log(`\nTotal 1080p MP4s found: ${mp4s.length}`); // Check existing audio manifests console.log("\n\n=== EXISTING AUDIO MANIFESTS ==="); function findManifests(dir) { if (!fs.existsSync(dir)) return []; const results = []; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const full = path.join(dir, entry.name); if (entry.isDirectory()) results.push(...findManifests(full)); else if (entry.name === "manifest.json" && full.includes("kokoro")) results.push(full); } return results; } const manifests = findManifests(outputRoot); manifests.forEach(f => { try { const m = JSON.parse(fs.readFileSync(f, "utf8")); console.log(` ${path.relative(outputRoot, f)} (${m.sceneCount} scenes, ${(m.totalDurationSeconds / 60).toFixed(1)}min, voice: ${m.voice})`); } catch { console.log(` ${path.relative(outputRoot, f)} (parse error)`); } }); console.log(`\nTotal audio manifests: ${manifests.length}`);