同声传译语音合成接口,分段预合成实现丝滑的衔接效果

背景:
在使用微信官方语音合成插件的时候遇到一个问题,textToSpeech这个api的内容限制在官网的文档上明明是1000个字节,也就是说能保证333个中文字符应该是没有问题的,但是也不知道为什么我这里仅仅传了150个中文字符就报错了,报错内容返回{“retcode”:-20003,“msg”:“text to speech inner server failed.”},查了一下是因为内容过长导致的错误。
解决办法:
事实与文档说明完全不符,这个没办法解决,就想了一个分割内容分段合成的办法,但是分段吧就会有一个问题,那就是如果每段文字合成语音后,播放,然后再合成,在播放,就会出现明显的停顿,一点都不丝滑,很难受,为了解决这个问题,想了一个预加载的办法,也就是预先合成一段段的音频文件,然后将这些音频文件存到一个数组里面,通过shift函数每次从数组取出一个这样就实现了不管多少文字内容,都能够非常丝滑的合成语音文件。
代码:

    data() {
			return {
				showAudioModal: false,
				textAyy: [],
				audioAyy: [],
				content: '超长的文本'
			};
		},
	onLoad(e) {
			this.audioContext =	uni.createInnerAudioContext();
			this.audioContext.onEnded(() => {
				if(this.audioAyy && this.audioAyy.length > 0){
					this.audioContext.src = this.audioAyy.shift()
					this.audioContext.play()
				}else{
					this.showAudioModal = false
				}
			})
		},
		methods: {
		async textToSpeech(){
				this.audioAyy = []
				this.textAyy = this.splitStringByLength(this.content,100,100)
				let flag = true
				for (var i = 0,len = this.textAyy.length; i < len; i++) {
					if(i === 0){
						uni.showLoading({
							title: '语音加载中',
							mask: true
						})
					}
					await this.callTextToSpeech(this.textAyy[i]).then(res => {
						console.log(i)
						this.showAudioModal = true
						if(flag){
							this.audioContext.src = res;
							this.audioContext.play();
							flag = false
						}else{
							this.audioAyy.push(res)
						}
						uni.hideLoading()
					}).catch(() => {
						
					})
				}
				if(flag){
					uni.hideLoading()
					uni.showToast({
						title:'语音合成失败'
					})
				}

			},
			callTextToSpeech(content){
				return new Promise((resolve,reject) => {
					this.$wcs.textToSpeech({
					    lang: "zh_CN",
					    tts: true,
					    content,
					    success: (res) => {
					        console.log("succ tts", res.filename)
							resolve(res.filename)
					    },
					    fail: function(res) {
					        console.log("fail tts", res)
							reject()
					    }
					})
				})
			},
			splitStringByLength(str, maxSize, chunkSize) {
			    const totalLength = str.length;
			
			    if (totalLength <= maxSize) {
			        return [str];
			    }
			
			    const chunks = [];
			    let start = 0;
			
			    while (start < totalLength) {
			        let end = Math.min(start + chunkSize, totalLength);
			        const chunk = str.substring(start, end);
			        chunks.push(chunk);
			        start = end;
			    }
			
			    return chunks;
			},
}

大致逻辑
通过async和await保证语音合成的有序性,第一段成功的语音直接播放,后续的放入数组,等音频播放结束事件触发后,自动从数组中获取资源,这样一来就实现了预合成的效果,达到了非常丝滑的效果

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 12:06:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 12:06:02       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 12:06:02       58 阅读
  4. Python语言-面向对象

    2024-07-16 12:06:02       69 阅读

热门阅读

  1. windows下使用#include <nlohmann/json.hpp>

    2024-07-16 12:06:02       20 阅读
  2. C# winform 打印Excel

    2024-07-16 12:06:02       21 阅读
  3. Linux容器篇-kubernetes监控和日志管理

    2024-07-16 12:06:02       23 阅读
  4. PG参数深入了解

    2024-07-16 12:06:02       22 阅读
  5. AI安全入门-人工智能数据与模型安全

    2024-07-16 12:06:02       24 阅读
  6. 容器安全最佳实践和工具

    2024-07-16 12:06:02       27 阅读