Files
ki-fwi/tools/data/check-audio.mjs
T

87 lines
3.0 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* check-audio.mjs — liste les enregistrements kréyòl manquants.
*
* Le brief §6 le demande explicitement : « prévois le contrat (audio.gcf, format .opus,
* repli silencieux si le fichier manque) et un script de vérification listant les
* enregistrements manquants. »
*
* Pas de synthèse vocale : ce script n'en fabrique aucune. Il produit une liste de courses
* pour la séance d'enregistrement — une après-midi de terrain vaut dix heures de code.
*
* Ce script n'échoue jamais : un enregistrement manquant est un travail à faire,
* pas un défaut de build. Le jeu doit se replier en silence.
*/
import { readFile, readdir, writeFile, access } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
const DATA = join(ROOT, 'src', 'lib', 'data', 'fruits');
const STATIC = join(ROOT, 'static');
async function existe(p) {
try {
await access(p);
return true;
} catch {
return false;
}
}
async function main() {
const fichiers = (await readdir(DATA)).filter((f) => f.endsWith('.json')).sort();
const manquants = [];
const absents = [];
const presents = [];
for (const f of fichiers) {
const e = JSON.parse(await readFile(join(DATA, f), 'utf8'));
if (!e.audio.gcf) {
manquants.push(e);
continue;
}
// Le chemin est absolu depuis la racine du site : /audio/<id>.opus → static/audio/<id>.opus
if (await existe(join(STATIC, e.audio.gcf))) presents.push(e);
else absents.push(e);
}
const l = [
'# Enregistrements kréyòl à réaliser',
'',
'> Généré par `npm run check:audio`. Aucune synthèse vocale : ces noms doivent être',
'> prononcés par une voix humaine locale (brief §6).',
'',
"Format attendu : `.opus` — un fichier par entrée, déposé dans `static/audio/<id>.opus`.",
'',
`## À enregistrer (${manquants.length})`,
''
];
for (const e of manquants) l.push(`- [ ] **${e.noms.gcf}** — \`static/audio/${e.id}.opus\` _(${e.noms.fr ?? ''})_`);
l.push('');
if (absents.length) {
l.push(`## Déclarés mais fichier introuvable (${absents.length})`, '');
for (const e of absents) l.push(`- ⚠ \`${e.id}\` → \`${e.audio.gcf}\` absent de \`static/\``);
l.push('');
}
if (presents.length) {
l.push(`## En place (${presents.length})`, '');
for (const e of presents) l.push(`- ✔ \`${e.id}\` — ${e.audio.locuteur ?? 'locuteur non renseigné'}`);
l.push('');
}
await writeFile(join(ROOT, 'docs', 'audio-a-enregistrer.md'), l.join('\n'));
console.log(`À enregistrer : ${manquants.length}`);
console.log(`Introuvables : ${absents.length}`);
console.log(`En place : ${presents.length}`);
console.log('\n docs/audio-a-enregistrer.md');
if (absents.length) console.log("\n⚠ Des chemins audio sont déclarés sans fichier : le jeu se repliera en silence.");
}
main().catch((e) => {
console.error('✘', e.stack ?? e.message);
process.exit(1);
});