| 123456789101112131415161718192021222324 |
- #!/usr/bin/env node
- // Explicit, small real-provider smoke test. Never changes production vocabulary.
- import {readFileSync,mkdirSync,writeFileSync,existsSync,statSync} from 'node:fs';
- import {homedir} from 'node:os';
- import {resolve} from 'node:path';
- import {createHash,webcrypto} from 'node:crypto';
- import vm from 'node:vm';
- const file=resolve(process.argv.find(x=>x.startsWith('--file='))?.slice(7)||homedir()+'/.config/xiaoshu/xfyun-word-audio.json');
- if(statSync(file).mode&0o077)throw Error('请将配置文件权限设置为600');
- const settings=JSON.parse(readFileSync(file,'utf8'));
- const ctx=vm.createContext({crypto:webcrypto,WebSocket,TextEncoder,URL,URLSearchParams,Uint8Array,btoa,atob,AbortSignal,setTimeout,clearTimeout,fetch,Parse:{Config:{get:async()=>({get:key=>settings[key]})}},fail:(_code,message)=>{throw Error(message);}});
- vm.runInContext(readFileSync(new URL('./cloud/word-audio.js',import.meta.url),'utf8'),ctx);
- const config=await ctx.wordAudioConfig();
- if(!config.appId||!config.apiKey||!config.apiSecret||!config.voice)throw Error('讯飞配置不完整');
- if(!process.argv.includes('--generate')){console.log(JSON.stringify({configured:true,voice:config.voice,generated:false,message:'--generate 生成 apple 样音;--extended 追加四个代表性词句。'}));process.exit(0);}
- const output=resolve('tmp/word-audio-qa');mkdirSync(output,{recursive:true});
- const words=process.argv.includes('--extended')?['apple','comfortable','read','NASA','Good morning']:['apple'];
- for(const word of words){
- const key=createHash('sha256').update(JSON.stringify([word,config.voice,config.speed])).digest('hex').slice(0,16),path=output+'/'+key+'.mp3';
- let cached=existsSync(path);
- if(!cached){const audio=await ctx.wordAudioSynthesize(word,config);writeFileSync(path,Buffer.from(audio,'base64'),{mode:0o600});}
- const bytes=readFileSync(path);
- console.log(JSON.stringify({word,voice:config.voice,path,bytes:bytes.length,cached,sha256:createHash('sha256').update(bytes).digest('hex')}));
- }
|