uniapp开发小程序接入阿里云TTS语音合成(RESTful API)

流程
  1. 首先小程序后台配置白名单
    1.1 路径:开发-开发管理-开发设置-服务器域名-request合法域名
    1.2 request合法域名参数:
          https://nls-meta.cn-shanghai.aliyuncs.com
          https://nls-gateway-cn-shanghai.aliyuncs.com
  2. 引入alitts.js
  3. 页面使用
    3.1 只需替换AccessKeyID、AccessKeySecret 、appkey三个参数即可直接使用
AccessKeyID、AccessKeySecret 、appkey获取地址:
  1. 阿里云RESTful API对接文档
  2. 阿里云TTS管理平台创建项目获取appkey
  3. 阿里云获取AccessKeyID和AccessKeySecret
static/js/alitts.js 用于获取阿里云动态token
// 这个东西我都没执行yarn add crypto竟然能用,可能另一个项目安装了全局共享了,如报错找不到,执行一下yarn add crypto
import crypto from 'crypto'

export class AccessToken {
    static encodeText(text) {
        let encodedText = encodeURIComponent(text);
        return encodedText.replace('+', '%20').replace('*', '%2A').replace('~', '%7E');
    }

    static encodeDict(dict) {
        let keys = Object.keys(dict).sort();
        return keys.map(key => `${this.encodeText(key)}=${this.encodeText(dict[key])}`).join('&');
    }

    static async createToken(accessKeyId, accessKeySecret) {
        const parameters = {
            AccessKeyId: accessKeyId,
            Action: 'CreateToken',
            Format: 'JSON',
            RegionId: 'cn-shanghai',
            SignatureMethod: 'HMAC-SHA1',
            SignatureNonce: uuidv4(),
            SignatureVersion: '1.0',
            Timestamp: new Date().toISOString(),
            Version: '2019-02-28'
        };

        const queryString = this.encodeDict(parameters);
        console.log('Normalized request string:', queryString);

        const stringToSign = `GET&${this.encodeText('/')}&${this.encodeText(queryString)}`;
        console.log('String to sign:', stringToSign);

        const hmac = crypto.createHmac('sha1', `${accessKeySecret}&`);
        hmac.update(stringToSign);
        const signature = hmac.digest('base64');
        console.log('Signature:', signature);

        const encodedSignature = this.encodeText(signature);
        console.log('URL-encoded signature:', encodedSignature);

        const fullUrl = `https://nls-meta.cn-shanghai.aliyuncs.com/?Signature=${encodedSignature}&${queryString}`;
        console.log('URL:', fullUrl);

        let resData =  await new Promise((resolve, reject) => {
            uni.request({
                url: fullUrl,
                method: 'GET',
                success: res => {
                    const data = res.data
                    resolve({
                        token: data.Token.Id,
                        expireTime: data.Token.ExpireTime
                    })
                },
                fail: error => {
                    console.log(error)
                    reject(error)
                }
            })
        })
         console.log('res',resData)
         if(resData){
            return resData
         }
        // Using fetch for HTTP request
        // const response = await fetch(fullUrl);
        // if (response.ok) {
        //     const jsonResponse = await response.json();
        //     if (jsonResponse.Token) {
        //         return {
        //             token: jsonResponse.Token.Id,
        //             expireTime: jsonResponse.Token.ExpireTime
        //         };
        //     }
        // }
        // console.error(await response.text());
        return {
            token: null,
            expireTime: null
        };
    }
}

// Sample UUIDv4 function, or you could use a library like `uuid`
function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}
使用
// 阿里云动态token获取函数
import { AccessToken } from "@/static/js/alitts"
// 阿里云动态token
const aliToken = null
// 需要在阿里云管理平台获取
const AccessKeyID = '你的AccessKeyID '
const AccessKeySecret = '你的AccessKeySecret '
// 需要在阿里云tts管理平台创建项目
const appkey = '你的阿里云后台创建项目的key'

export default {
    name: "tts",
    data() {
        return {
        	isPlay:false,
        	// tts播放实例
            ttsAudio: null,
        }
    },
    onUnload() {
        if(this.ttsAudio){
            this.ttsAudio.stop()
            this.ttsAudio.destroy()
        }
    },
    async onLoad(val) {
		// 获取阿里云动态token,tts需要此参数
		AccessToken.createToken(AccessKeyID, AccessKeySecret).then(({ token, expireTime }) => {
		   console.log('阿里云token:', token, 'Expire Time:', expireTime);
		   aliToken = token
		});

		// 模拟调用
		setTimeout(() => {
			this.tts('刘斩仙明天要去江苏,晚上回来又约了朋友撸串,忙死了')
		},5000)
	},
	methods: {
		/**
		* 文字转语音
		* @param {string} text 
		*/
		tts(text) {
			uni.request({
			      url:'https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts',
			      method:'POST',
			      // header:{
			      //     "Content-Type": "application/json"
			      // },
			      data:{
			          appkey: appkey,
			          token: aliToken,
			          text: text,
			          format: 'mp3',
			          sample_rate: 16000,
			          volume: 100
			      },
			      // dataType:'tts',
			      responseType:'arraybuffer',
			      success:ttsRes => {
			           console.log('阿里云:')
			          // 语音
			          const audio = uni.createInnerAudioContext();
			          // 设置不遵循静音开关播放,否则ios无法外音播放
			          audio.obeyMuteSwitch = false
			          uni.setInnerAudioOption({
			              obeyMuteSwitch: false
			          })
			          // 临时路径-此处必须加时间戳或者随机数,否则同样临时路径无法覆盖,小程序bug
			          const ttsPath = `${wx.env.USER_DATA_PATH}/tts${new Date().getTime()}.mp3`
			          if(this.ttsAudio){
			              this.ttsAudio.stop()
			              this.ttsAudio.destroy()
			          }
			          this.ttsAudio = audio
			          // 将 arrayBuffer 写入临时文件
			          const fs = uni.getFileSystemManager()
			          try {
			              const writeRes = fs.writeFileSync(ttsPath, ttsRes.data, "binary")
			              console.log('writeRes',writeRes)
			          } catch(e) {
			              console.error(e)
			          }
			          
			          audio.src = ttsPath
			          audio.autoplay = false;
			          audio.onError((res) => {
			              console.error('音频播放出错', res);
			          });
			          // 监听播放完成
			          audio.onEnded(() => {
			              console.log('音频播放结束');
			              this.isPlay = false
			              // 播放完成后删除临时文件,此处虽然设置同步删除即使执行成功,文件也不会立即删除,还是能访问到,实际删除为异步操作
			              try {
			                  const unlinkRes = fs.unlinkSync(ttsPath)
			                  console.log('unlinkRes',unlinkRes)
			              } catch(e) {
			                  console.error(e)
			              }
			          });
			          // 播放音频
			          audio.onCanplay(() => {
			              console.log('音频开始播放');
			              this.ttsAudio.play();
			              this.isPlay = true
			          })   
			      }
			  })
		}
	},
}
备注:

就想到这些,如果还有需要注意的后续再补充;最近骑电车要带头盔,飘逸的发型压得趴在头上,影响刘斩仙风度翩翩谦谦君子形象,可恶啊!

### 实现 UniApp 流式语音合成 API 接入UniApp 中实现流式语音合成 API接入主要涉及几个方面的工作:准备环境、引入必要的 SDK 或接口库、处理录音权限以及实际调用 API 进行语音合成。 #### 准备工作 确保已经安装并配置好最新版本的 UniApp 开发工具,并创建一个新的或打开现有的项目。对于需要访问麦克风或其他敏感设备的情况,应当遵循官方指南来请求相应的权限[^1]。 #### 获取录音权限 为了能够在应用程序中执行录音操作,在 Android 平台上需通过 `permission` 组件申请录音权限: ```javascript // 请求录音权限示例代码 import permission from '@dcloudio/uni-permission'; async function requestRecordPermission() { try { const res = await permission.request({ name: 'record' }); console.log('用户是否同意:', res.authSetting['scope.record']); } catch (err) { console.error(err); } } ``` 此部分逻辑应放置于适当的应用生命周期内以及时向用户发起权限请求。 #### 配置与初始化SDK 针对科大讯飞提供的 WebAPI开发者通常需要先完成注册流程获得 AppID 和 SecretKey 。接着按照其提供的开发文档说明设置相关参数并实例化对象用于后续交互[^4]。 #### 使用流式语音合成服务 当一切就绪之后就可以开始构建函数来进行具体的业务实现了。下面是一个简单的例子展示了如何利用 RESTful API 发送 POST 请求给服务器从而启动一次新的会话并接收返回的数据包直到结束整个过程为止。 ```javascript const xhr = new XMLHttpRequest(); xhr.open("POST", "https://webapi.xfyun.cn/v1/service/v1/tts"); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); let params = `text=你好世界&token=${accessToken}&aue=raw&auf=audio/L16;rate=16000&voice_name=xiaoyan`; xhr.onreadystatechange = () => { if(xhr.readyState === 4 && xhr.status === 200){ let responseText = xhr.responseText; console.log(responseText); // 处理接收到的声音数据... } }; xhr.send(params); ``` 上述代码片段仅作为概念验证用途;真实环境中还需要考虑错误处理机制、连接超时等问题。另外值得注意的是这里假设已存在有效的 access token 来鉴权。 #### 数据解析与播放 最后一步就是对接收到的数据进行解码并与前端 UI 结合起来呈现给最终使用者。这可能涉及到 Base64 编码转换成二进制格式再交给 `<audio>` 标签或者其他第三方音频组件去播放。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘斩仙的笔记本

富贵险中求

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值