/* Load and speak with every Chinese bundle the picker offers, plus a Piper voice to prove the espeak path did not regress. */ const path=require('path'), os=require('os'); const voices=require('./voices.js'); const sherpa=require('sherpa-onnx-node'); const DIR=path.join(os.homedir(),'Library/Application Support/Church Translate Voices'); const C=require('./voice-catalog.js'); const TEXT='耶稣说,我就是道路、真理、生命。'; const cases=C.forLanguage('zho_Hans').filter(v=>v.engine==='builtin') .map(v=>({bundle:v.bundle,model:v.model,text:TEXT})); cases.push({bundle:'vits-piper-de_DE-thorsten-medium',model:'de_DE-thorsten-medium.onnx', text:'Jesus sprach: Ich bin der Weg.'}); let ok=0,bad=0; for (const c of cases) { const dir=path.join(DIR,c.bundle); try { const cfg=voices.ttsConfig(dir,{model:c.model}); const which=cfg.model.vits.lexicon?'lexicon':'espeak'; const t=new sherpa.OfflineTts(cfg); const a=t.generate({text:c.text,sid:0,speed:1.0}); const secs=a.samples.length/a.sampleRate; /* Silence means it "worked" but produced nothing — that is still a failure. */ let peak=0; for(let i=0;ipeak)peak=v;} const dead=peak<0.01; console.log((dead?' SILENT ':' OK ')+c.bundle.padEnd(38)+which.padEnd(9)+ secs.toFixed(1)+'s peak '+peak.toFixed(3)+' @'+a.sampleRate); dead?bad++:ok++; } catch(e) { console.log(' FAIL '+c.bundle.padEnd(38)+String(e.message).split('\n')[0].slice(0,70)); bad++; } } console.log('\n'+ok+' usable, '+bad+' not');