网络科技公司网站源码,四川省建设三类职称网站,顺德网站建设包括哪些,营销软件站主要的功能就是将文本转为语音#xff0c;可以播放。
看了看官方提供的demo#xff0c;嗯....没看懂。最后还是去网上找的。
网上提供的案例#xff0c;很多都是有局限性的#xff0c;我找的那个他只能读取第一段数据#xff0c;剩下的不读取。
科大讯飞的接口#xf…主要的功能就是将文本转为语音可以播放。
看了看官方提供的demo嗯....没看懂。最后还是去网上找的。
网上提供的案例很多都是有局限性的我找的那个他只能读取第一段数据剩下的不读取。
科大讯飞的接口返回的是一个数组因为需要合成的文本多所以将数据切割成多份然后返回的。
例子 封装了个方法直接调用方法就可以了。
import CryptoJS from crypto-js;
import { Base64 } from js-base64;
import { message } from ant-design-vue;let APPID ;
let API_SECRET ;
let API_KEY ;// 正确的URL
function getWebSocketUrl(apiKey, apiSecret) {let url wss://tts-api.xfyun.cn/v2/tts;const host tts-api.xfyun.cn;const date new Date().toGMTString();const algorithm hmac-sha256;const headers host date request-line;const signatureOrigin host: ${host}\ndate: ${date}\nGET /v2/tts HTTP/1.1;const signatureSha CryptoJS.HmacSHA256(signatureOrigin, apiSecret);const signature CryptoJS.enc.Base64.stringify(signatureSha);const authorizationOrigin api_key${apiKey}, algorithm${algorithm}, headers${headers}, signature${signature};const authorization btoa(authorizationOrigin);url ${url}?authorization${authorization}date${date}host${host};return url;
}// 文本编码
function encodeText(text, encoding) {switch (encoding) {case utf16le: {const buf new ArrayBuffer(text.length * 4);const bufView new Uint16Array(buf);// eslint-disable-next-line no-plusplusfor (let i 0, strlen text.length; i strlen; i) {bufView[i] text.charCodeAt(i);}return buf;}case buffer2Base64: {let binary ;const bytes new Uint8Array(text);const len bytes.byteLength;// eslint-disable-next-line no-plusplusfor (let i 0; i len; i) {binary String.fromCharCode(bytes[i]);}return window.btoa(binary);}case base64utf16le: {return this.encodeText(this.encodeText(text, utf16le), buffer2Base64);}default: {return Base64.encode(text);}}
}// eslint-disable-next-line no-shadow
function TextToSpeechConfig(APPID, vcn, speed, volume, pitch, tte, text) {// 私有方法生成参数对象function generateParams() {return {common: {app_id: APPID,},business: {aue: lame,auf: audio/L16;rate16000,sfl: 1,vcn,speed,volume,pitch,bgs: 1,tte,},data: {status: 2,text: encodeText(text, tte unicode ? base64utf16le : ), // 假设 encodeText 是一个已定义的函数},};}// 公共方法暴露给外部调用以获取参数对象return generateParams();
}export default class TTSWSS {static _instance; // 使用下划线表示这是一个内部使用的属性text ;vcn ;speed ;volume ;pitch ;tte UTF8;ttsWS null;static getInstance(text, vcn, speed, volume, pitch) { // 单例模式// if (!TTSWSS._instance) {// TTSWSS._instance new TTSWSS(text, vcn, speed, volume, pitch);// }TTSWSS._instance new TTSWSS(text, vcn, speed, volume, pitch);return TTSWSS._instance;}constructor(text, vcn, speed, volume, pitch) {this.text text;this.vcn vcn;this.speed speed;this.volume volume;this.pitch pitch;const url getWebSocketUrl(API_KEY, API_SECRET);if (WebSocket in window) { // 构造函数时就创建websocket对象this.ttsWS new WebSocket(url);} else if (MozWebSocket in window) {this.ttsWS new WebSocket(url);} else {// alert(浏览器不支持WebSocket);message.error(浏览器不支持WebSocket);}}setText(text) {this.text text;}setTextVCN(vcn) {this.vcn vcn;}setSpeed(speed) {this.speed speed;}setVolume(volume) {this.volume volume;}// setTte(isttefalse){// this.tte isttetrue ? unicode : UTF8// }connectWebSocket() {this.ttsWS.onopen () {// console.log(TextToSpeechConfig(APPID, this.vcn, this.speed, this.volume, this.pitch, this.tte, this.text), 请求参数);this.ttsWS.send(JSON.stringify(TextToSpeechConfig(APPID, this.vcn, this.speed, this.volume, this.pitch, this.tte, this.text)));};this.ttsWS.onerror () {// console.error(e);};this.ttsWS.onclose () {// console.log(e);};}disconnectWebSocket() {TTSWSS._instance null;this.ttsWS.close(); // 关闭 WebSocket 连接this.ttsWS null; // 清空 WebSocket 对象// console.log(WebSocket disconnected);}send_newMessage text {const params {common: {app_id: APPID,},business: {aue: lame,sfl: 1,auf: audio/L16;rate16000,vcn: this.vcn,speed: this.speed,volume: this.volume,pitch: this.pitch,bgs: 1,tte: UTF8,},data: {status: 2,text: encodeText(text, this.tte unicode ? base64utf16le : ),},};this.ttsWS.send(JSON.stringify(params));};getMessage() {const that this.ttsWS;const messages []; // 用于存储所有消息return new Promise((resolve, reject) {that.onmessage e {const jsonData JSON.parse(e.data);// 合成失败if (jsonData.code ! 0) {// eslint-disable-next-line prefer-promise-reject-errorsreject({ message: 失败, data: jsonData });return; // 退出当前处理}// 存储成功的消息messages.push({message: 成功,type: base64,data: jsonData.data.audio,isLastData: jsonData.data.status 2,});// 如果接收到最后一条数据解析所有消息并关闭连接if (jsonData.data.status 2) {that.close();resolve(messages); // 返回所有消息}};});}TTS_close_reset() {this.ttsWS?.close();// audioPlayer.reset();}static resetInstance() {TTSWSS._instance null; // 清空实例// console.log(TTSWSS instance has been reset.);}
}
export function setConfig(params) {APPID params?.APPID;API_SECRET params?.APISecret;API_KEY params?.APIKey;
}使用
import TTWss from /utils/voice/index.js;const audio_url ref();
const ttsinstance ref(null); // 初始化为 null
const voiceLoading ref(false); // 加载音频中function playVoice() {voiceLoading.value true;ttsinstance?.value?.disconnectWebSocket();ttsinstance.value null;audio_url.value null; // 清空音频 URLconst { text } props; // 这里是要转成语音的文字我这个是写在组件里面的用props接收的所以要这样写到时候替换成自己要合成的文字就行// 创建 TTS 实例ttsinstance.value TTWss.getInstance(text, xiaoyan, 50, 50, 50);// 连接 WebSocketttsinstance.value.connectWebSocket();// 获取消息ttsinstance.value.getMessage().then(result {// 这里需要特殊处理因为返回的数据是数组所以要先将数组中的数据拿出来放在每项里面的data中然将不要先拼接而是要先解码然后将解码后的数据在拼接起来这样就是一整段完整的录音文件了。const allData result.map(it atob(it.data));const binaryString allData.join();const len binaryString.length;const bytes new Uint8Array(len);for (let i 0; i len; i) {bytes[i] binaryString.charCodeAt(i);}const blob new Blob([bytes], { type: audio/mp3 }); // 根据音频格式修改MIME类型const url URL.createObjectURL(blob);audio_url.value url; // 将生成的 URL 赋值给 audio_url// 这里展开后可以直接下载// const aTag document.createElement(a);// aTag.href url;// aTag.download audio_file_name.mp3; // 设置文件名// aTag.style.display none;// document.body.appendChild(aTag);// aTag.click();// document.body.removeChild(aTag);// 播放音频playItem(url);voiceLoading.value false;}).catch(err {// console.log(失败, err);message.error(err);voiceLoading.value false;});
}let currentAudio null;
function playItem(url) {// 如果当前有音频在播放则停止它if (currentAudio) {currentAudio.pause();currentAudio.currentTime 0; // 可选重置播放时间}currentAudio new Audio(url);currentAudio.play().then(() {// console.log(音频播放开始);}).catch(error {// console.error(音频播放失败, error);message.error(error);});// 释放对象URL可选currentAudio.addEventListener(ended, () {URL.revokeObjectURL(url);currentAudio null; // 音频结束后清空实例});
}
HTML
img:srcPlayVoicealtclassicon-imgclick.stopplayVoice/