当前位置:网站首页>Mini Program-Voice broadcast function
Mini Program-Voice broadcast function
2022-08-10 14:53:00 【Yin qiu yi】
功能需求
Implemented by passing in“Voice copy is automatically broadcast”,如:“Test broadcast”,Voice broadcast automatically“Test broadcast”
方案
使用wx.playVoice播放语音文件
优点:使用简单,Play recorded audio files directly
缺点:Only recorded voice files can be played
Third-party voice services + wx.createInnerAudioContext
优点:功能强大,可定制,Can meet complex scenarios;
缺点:Server connection is required,付费
小程序插件 + wx.createInnerAudioContext
优点:简单快捷,适用于简单场景;
缺点:功能单一,无法定制,Uppercase English is not recognized,Some lowercase English pronunciations are inaccurate
Third-party voice platforms
语音平台
服务端
对接第三方平台,Give the converted voice data to the applet.
小程序
1.添加请求
wx.request({
url: 'https://xxxx.com',
data: { data: "The speech data to be synthesized"},
method: "get",
header: {
'content-type': 'application/json' // 默认值
},
dataType: "json",
success: function (res) {
const innerAudioContext = wx.createInnerAudioContext();
innerAudioContext.src = res.filename;
innerAudioContext.play();
}
})
微信插件
添加 微信同声传译插件:Configured on the WeChat public platform,找到设置–第三方设置–插件管理–点击添加插件
搜索 微信同声传译,点击添加
引入插件:在项目根目录app.json文件中配置
"plugins": {
// 引入插件
"WechatSI": { // 自定义的名字
"version": "0.3.5", // 引入插件的版本号
"provider": "wx069ba97219f66d99" // 引入插件的appID
}
}
使用
const plugin = requirePlugin('WechatSI');
onReady() {
this.innerAudioContext = wx.createInnerAudioContext();
const that = this;
plugin.textToSpeech({
// 调用插件的方法
lang: 'zh_CN',
content: 'Test the voice broadcast',
success: function (res) {
that.playAudio(res.filename);
}
});
},
playAudio(e) {
this.innerAudioContext.src = e;
this.innerAudioContext.play();
},
封装优化
const plugin = requirePlugin('WechatSI');
import { trim, isLetter } from '@/shared/index';
class PluginService {
innerAudioContext;
audioBroadcast(content: string): Promise<any> {
return new Promise((resolve, reject) => {
this.innerAudioContext = wx.createInnerAudioContext();
plugin.textToSpeech({
// 调用插件的方法
lang: 'zh_CN',
content,
success: res => {
this.playAudio(res.filename, resolve, reject);
},
fail: reject
});
});
}
playAudio(e, resolve, reject) {
this.innerAudioContext.src = e;
this.innerAudioContext.play();
this.innerAudioContext.onStop(() => {
console.log('[ onStop ] >');
resolve({
type: 'stop'
});
});
this.innerAudioContext.onEnded(() => {
//播放结束,销毁该实例
this.innerAudioContext.destroy();
console.log('[ onEnded ] >');
resolve({
type: 'end'
});
});
this.innerAudioContext.onError(error => {
console.log('[ onError ] >', error);
this.innerAudioContext.destroy();
reject(error);
});
}
stopAudio() {
this.innerAudioContext.stop();
this.innerAudioContext.destroy();
}
}
export default new PluginService();
在shared/indexMedium utility function:
// 去掉字符串中所有空格(包括中间空格,需要设置第2个参数为:true)
export function trim(str: string, isGlobal = true) {
if (!str) {
return str;
}
const result = str.replace(/(^\s+)|(\s+$)/g, '');
return isGlobal ? result.replace(/\s/g, '') : result;
}
// 判断是否为字母
export function isLetter(str) {
const reg = /^[A-Za-z]+$/;
return reg.test(str);
}
// Alphabet to Chinese
export function translateAlphabet(letters) {
if (!letters || !(letters.length > 0)) {
return letters;
}
let tLetters = '';
for (const key of letters) {
tLetters += alphabetComparison(key);
}
return trim(tLetters);
}
// Alphabet Chinese reading
export function alphabetComparison(letter) {
if (!letter || !isLetter(letter)) {
return letter;
}
const letterCase = letter.toUpperCase();
const letterMap = {
A: '诶',
B: 'b',
C: '西',
D: '帝',
E: '伊',
F: 'f',
G: 'g',
H: 'h',
I: 'i',
J: 'j',
K: 'k',
L: 'l',
M: 'm',
N: 'n',
O: '欧',
P: 'p',
Q: 'q',
R: 'r',
S: '爱死',
T: 't',
U: '优',
V: 'v',
W: 'w',
X: 'x',
Y: '歪',
Z: 'z'
};
return letterMap[letterCase];
}
在页面中使用
import { pluginService, translateAlphabet } from '@util';
import { formatCabinetNo, getCacheCabinet } from '@/shared/index';
Page({
...
onLoad(e) {
// Get order result type
this.autoPlay();
},
onUnload() {
pluginService.stopAudio();
},
// Polling to play multiple times
autoPlay(timerCount = 0, maxCount = 100) {
const { address, lockerName } = this.data;
console.log('timerCount:', timerCount);
if (timerCount > maxCount) {
return;
}
const tAddress = translateAlphabet(address);
console.log('[ translateAlphabet ] >', tAddress);
// 'Check the cabinet door number before storing,Don't save the wrong door'
const message = `Your cabinet door number is${tAddress}${lockerName},Please check the cabinet door number for storage,Don't save the wrong door`;
pluginService
.audioBroadcast(message)
.then(res => {
if (res.type !== 'stop') {
this.autoPlay(++timerCount);
}
console.log('audioBroadcast.complete', res);
})
.catch(err => {
console.log('[ audioBroadcast.err ] >', err);
this.autoPlay(timerCount);
});
}
});
注意:
Voice input quota:每个小程序250条/分钟,3w条/天. Text translation quota:每个小程序500次/分钟,10w次/天. Speech synthesis quota:每个小程序100次/分钟,2w次/天.
问题归档
在小程序onHide,onUnload函数里调用 stop方法无效;需要同时调用destroy方法
this.innerAudioContext.stop();
this.innerAudioContext.destroy();
After testing, it was found that uppercase English letters in Chinese could not be recognized,Some lowercase English letters are pronounced incorrectly
参考
The mobile terminal quickly accesses the voice broadcast WeChat Simultaneous Interpretation applet plugin —— 机器翻译、智能语音
关注我
利用空闲时间免费兼职(无门槛,长期有效),请联系我(PS:关注公众号后,点击“联系我”获取联系方式)~ 
边栏推荐
猜你喜欢
随机推荐
【MindSpore易点通机器人-02】设计与技术选型
波士顿房价预测
【Gazebo入门教程】第三讲 SDF文件的静/动态编程建模
2022-08-10日报: Swin Transformer作者曹越加入智源,开展视觉基础模型研究
1W字详解线程本地存储 ThreadLocal
pm2之静态文件服务
[Gazebo Introductory Tutorial] Lecture 3 Static/Dynamic Programming Modeling of SDF Files
静态变量存储在哪个区
司空见惯 - 股市狠狠下跌后,何時能反弹?
《论文阅读》PLATO: Pre-trained Dialogue Generation Model with Discrete Latent Variable
缺少比较器,运放来救场!(运放当做比较器电路记录)
PyTorch 多机多卡训练:DDP 实战与技巧
蓝帽杯半决赛火炬木wp
安装mysql报错处理
MySQL Principle and Optimization: Update Optimization
等保2.0一个中心三重防护指的是什么?如何理解?
MySQL advanced (thirty-three) MySQL data table adding fields
CSP-J1 CSP-S1 初赛 第1轮(2022.08.09)
C#实现访问OPC UA服务器
快速了解大端模式和小端模式








