xfyun-client-sdk
Version:
xunfei voice sdk
2 lines (1 loc) • 3.26 kB
JavaScript
;function t(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var e=t(require("crypto-js"));module.exports=class{constructor(t){var e;this.ttsWS=null,this.audioChunks=[],this.audioContext=null,this.audioSource=null,this.isPlaying=!1,this.appid=t.appid,this.apiKey=t.apiKey,this.apiSecret=t.apiSecret,this.content=null!==(e=t.content)&&void 0!==e?e:"",this.validateConfig(t)}validateConfig(t){if(!t.appid||!t.apiKey||!t.apiSecret)throw new Error("Missing required authenication parameters")}generateSignature(){const t=location.host,o=(new Date).toUTCString(),i=`host: ${t}\ndate: ${o}\nGET /v2/tts HTTP/1.1`,s=e.default.HmacSHA256(i,this.apiSecret),a=e.default.enc.Base64.stringify(s),n=`api_key="${this.apiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${a}"`;return`wss://tts-api.xfyun.cn/v2/tts?authorization=${btoa(n)}&date=${o}&host=${t}`}async playAudio(){if(0!==this.audioChunks.length)try{const t=this.audioChunks.reduce(((t,e)=>t+e.byteLength),0),e=new Uint8Array(t);let o=0;for(const t of this.audioChunks)e.set(new Uint8Array(t),o),o+=t.byteLength;this.audioContext=new(window.AudioContext||window.webkitAudioContext);const i=await this.audioContext.decodeAudioData(e.buffer);this.audioSource=this.audioContext.createBufferSource(),this.audioSource.buffer=i,this.audioSource.connect(this.audioContext.destination),this.audioSource.onended=()=>{this.isPlaying=!1,console.log("Play finished")},this.audioSource.start(0),this.isPlaying=!0,console.log("Audio play started")}catch(t){console.log("Failed to play audio",t)}else console.warn("No audio data to play")}stopPlayAudio(){this.isPlaying&&this.audioSource&&(this.audioSource.stop(),this.isPlaying=!1,console.log("play stopped"))}async synthesize(t={}){return new Promise(((e,o)=>{const i=this.generateSignature();if(!("WebSocket"in window))return o(new Error("WebSocket is not supported in this environment"));this.ttsWS=new WebSocket(i),this.ttsWS.onopen=()=>{var e,o,i,s,a,n;const r={common:{app_id:this.appid},business:{aue:null!==(e=t.audioFormat)&&void 0!==e?e:"lame",auf:`audio/L16;rate=${t.sampleRate||16e3}`,vcn:null!==(o=t.voice)&&void 0!==o?o:"xiaoyan",speed:null!==(i=t.speed)&&void 0!==i?i:50,volume:null!==(s=t.volume)&&void 0!==s?s:50,pitch:null!==(a=t.pitch)&&void 0!==a?a:50,tte:"UTF8"},data:{status:2,text:btoa(String.fromCharCode(...(new TextEncoder).encode(this.content)))}};null===(n=this.ttsWS)||void 0===n||n.send(JSON.stringify(r))},this.ttsWS.onmessage=t=>{var i,s;const a=JSON.parse(t.data);if(0===a.code){const t=Uint8Array.from(atob(a.data.audio),(t=>t.charCodeAt(0)));this.audioChunks.push(t.buffer),2===a.data.status&&(console.log("Received all audio data"),null===(i=this.ttsWS)||void 0===i||i.close(),this.playAudio().then(e).catch(o))}else null===(s=this.ttsWS)||void 0===s||s.close(),o(new Error(`TTS error:${a.message} (code ${a.code})`))},this.ttsWS.onerror=t=>{var e;console.log("websocket error:",t),null===(e=this.ttsWS)||void 0===e||e.close(),o(new Error("webscoket connection error"))},this.ttsWS.onclose=()=>{this.ttsWS=null}}))}destory(){this.stopPlayAudio(),this.ttsWS&&(this.ttsWS.close(),this.ttsWS=null),this.audioContext&&(this.audioContext.close(),this.audioContext=null),this.audioChunks=[]}};