前言
最近在我的学习卡盒小程序中增加了一个卡片人声朗读的效果,点击右小角的播放按钮就会播放卡片中的文字对应的人声朗读效果。效果如下图:
主要的原理是用到了小程序的同声传译插件,下面就详细讲讲如何将这个插件集成,以及交互应该怎么做.
引用插件
微信的同声传译插件有三个功能,分别是 语音输入,文本翻译和语音合成(文字转语音),我用到的就是语音合成功能。
首先微信服务市场中登录并添加同声传译插件,我是个人账号同样可以申请,链接在这里:fuwu.weixin.qq.com/service/det…
添加完成后在小程序后台 mp.weixin.qq.com/ 点击左下角的账号设置
顶部 Tab 栏选择第三方设置,在插件管理中找到同声传译插件,点击详情
在详情中可以查看插件的 APPID,提前复制好
接下来在小程序项目的 manifest.json 文件中添加一个插件引用:
"mp-weixin": {
"appid": "wxff30426f8850b0d7",
"setting": {
"urlCheck": false
},
"usingComponents": true,
+ "plugins": {
+ "WechatSI": {
+ "provider": "上一步复制的 APPID",
+ "version": "0.3.6"
}
}
},
如此操作,插件就算是在项目中成功引用了。
功能使用
首先,在代码中引用插件:
const plugin = requirePlugin('WechatSI')
下一步尝试调用一下 API 看看能不能调通:
plugin?.textToSpeech({
content,
lang: 'zh_CN',
success: (res) => {
audio.src = res.filename
audio.play()
},
fail: (err) => {
console.log('err: ', err)
uni.showToast({
icon: 'none',
title: '朗读失败,请稍后重试',
})
},
这里的 content 是文本内容,lang 是语言,更多参数可以查看文档,如果能够顺利调通就可以开始尝试搭配功能使用。上面的代码可以看到,调用成功返回了一个音频文件的地址,因此我们需要播放这个音频文件。
const audio = uni.createInnerAudioContext()
audio.src = res.filename
audio.play()
音频的播放需要用到小程序的 createInnerAudioContext API 去创建音频上下文实例,然后修改实例的 src 属性指定播放音频的链接,在执行 play() 就可以将音频播放。
完整的配置大家可以参考我的代码示例,上手即用:
const onPlaying = ref(false) // 播放状态,true表示正在播放,false表示未播放
const onAudioLoading = ref(false) // 加载状态,true表示正在加载音频,false表示加载完成或未开始加载
// 使用reactive来创建一个响应式对象,用于缓存音频文件的名称
const audioCacheFileName = reactive({})
// 创建一个内部音频上下文,用于控制音频的播放、停止等
const audio = uni.createInnerAudioContext()
// 使用lodash的debounce函数来防抖处理点击事件,确保在短时间内多次点击只执行一次操作
const onSpeakBtnClick = _.debounce(() => {
// 如果当前正在播放音频,则停止播放
if (onPlaying.value) {
audio.stop()
return
}
// 根据当前卡片索引和翻转状态获取要朗读的内容
const content =
cardItemList.value[currentCardIndex.value]?.[
isCardFlipped(currentCardIndex.value) ? 'backContent' : 'frontContent'
]?.trim()
// 检查缓存中是否已存在该内容的音频文件
if (audioCacheFileName[content]) {
// 如果存在,则直接使用缓存的音频文件
audio.src = audioCacheFileName[content]
audio.play()
return
}
// 设置加载状态为true,表示开始加载音频
onAudioLoading.value = true
// 调用文本转语音插件,将文本转换为语音
plugin?.textToSpeech({
content, // 要转换的文本内容
lang: 'zh_CN', // 使用的语言,这里是中国大陆普通话
success: (res) => {
// 成功获取音频文件后,设置音频源为转换后的文件,并缓存文件名
audio.src = res.filename
audioCacheFileName[content] = res.filename
audio.play() // 播放音频
},
fail: (err) => {
// 转换失败时,输出错误信息并显示提示
console.log('err: ', err)
uni.showToast({
icon: 'none',
title: '朗读失败,请稍后重试',
})
},
complete: () => {
// 无论成功或失败,完成后都将加载状态设置为false
onAudioLoading.value = false
},
})
}, 300) // 防抖时间间隔设置为300毫秒
// 监听音频播放事件,当音频开始播放时,将播放状态设置为true
audio.onPlay(() => {
onPlaying.value = true
})
注意点
-
大家可以看到我的代码示例中指定了语言为中文,其实我的小程序中是既有中文也有英文的,在最开始我自己实现了一个判断字符串中英文和符号的函数,但是后面发现无论是中文还是英文,指定为中文都可以正常朗读,省去了很多判断,而且中文的人声更好听,音质也更好,如果指定英文读出来的机械感很重,所以这里大家不必花心思去判断语言类型。
-
API 的调用是有限额的,因此播放按钮最好做个防抖处理。除了防抖,在我的代码中我还简单实现了一个缓存机制,当段文本播放过之后就会放到
audioCacheFileName对象中,每次播放时,先对比一下当前的文本是不是已经朗读过了,如果已经朗读过了,并且内容没有修改就直接播放已经请求过的那个音频,这样可以大大减少 API 的调用次数。
总结
微信小程序的朗读功能实现还是比较简单的,跟着步骤走一个小时就做好了。如果文章对你有帮助请帮我点个赞,目前小程序已经上线,小程序名称为 “学习卡盒”,紫色图标那个,已经在通过认证了,可以在卡片内体验一下朗读的效果。