菏泽北京网站建设,湖南省建设人力资源网,wordpress数据库优化,生意街创业商机网一、效果展示
我们有一个按钮#xff0c;点击“开始录音”按钮#xff0c;此时按钮变成“停止录音”并开始计时#xff0c;点击停止录音后#xff0c;界面上即可展示返回的文字
二、代码实现
完整代码实现见github
1.小程序端代码
// index.js
const recorderManager…一、效果展示
我们有一个按钮点击“开始录音”按钮此时按钮变成“停止录音”并开始计时点击停止录音后界面上即可展示返回的文字
二、代码实现
完整代码实现见github
1.小程序端代码
// index.js
const recorderManager wx.getRecorderManager();Page({data: {recordState: false, // 录音状态recordTime: 0, // 录音时长voices: [], // 语音消息列表},// 开始录音startRecord() {const options {duration: 60000, // 最长录音时间单位mssampleRate: 16000,numberOfChannels: 1,encodeBitRate: 48000,format: mp3,};recorderManager.start(options);this.setData({ recordState: true, recordTime: 0 });this.startTimer();recorderManager.onStart(() {console.log(recorder start);});recorderManager.onError((res) {console.error(recorder error:, res);});},// 停止录音stopRecord() {recorderManager.stop();this.setData({ recordState: false });this.clearTimer();recorderManager.onStop((res) {console.log(recorder stop, res);this.uploadVoice(res.tempFilePath);});},// 上传语音文件并转换为文本uploadVoice(filePath) {wx.showLoading({ title: 识别中... });wx.uploadFile({url: http://localhost:3000/upload, // 替换为你的服务器地址filePath: filePath,name: file,success: (res) {wx.hideLoading();const data JSON.parse(res.data);if (data.text) {this.setData({voices: [...this.data.voices, { type: text, content: data.text }]});}},fail: (error) {wx.hideLoading();console.error(Upload failed, error);wx.showToast({title: 上传失败,icon: none});}});},// 开始计时器startTimer() {this.timer setInterval(() {this.setData({ recordTime: this.data.recordTime 1 });}, 1000);},// 清除计时器clearTimer() {if (this.timer) {clearInterval(this.timer);this.timer null;}},// 组件生命周期函数onUnload() {this.clearTimer();}
});2.服务端代码
const path require(path);
const fs require(fs);
const express require(express);
const axios require(axios);
const multer require(multer);
const FormData require(form-data);require(dotenv).config();
const { APP_ID, APP_SECRET, PORT } process.env// 确保 uploads 目录存在
const uploadsDir path.join(__dirname, uploads);
if (!fs.existsSync(uploadsDir)) {fs.mkdirSync(uploadsDir);
}const app express();// 替换为你的 AppID 和 AppSecret
const appId APP_ID;
const appSecret APP_SECRET;// 配置 multer 来处理文件上传
const storage multer.diskStorage({destination: function (req, file, cb) {cb(null, uploads/)},filename: function (req, file, cb) {cb(null, file.fieldname - Date.now() path.extname(file.originalname))}
});const upload multer({ storage: storage });// 获取 ACCESS_TOKEN 的函数
async function getAccessToken() {const url https://api.weixin.qq.com/cgi-bin/token?grant_typeclient_credentialappid${appId}secret${appSecret};try {const response await axios.get(url);console.log(Access token response:, response.data);if (response.data.access_token) {return response.data.access_token;} else {throw new Error(Failed to get access token);}} catch (error) {console.error(Error getting access token:, error);return null;}
}// 调用微信语音识别接口
async function recognizeSpeech(accessToken, filePath) {try {console.log(Reading file:, filePath);// const fileContent fs.readFileSync(filePath);// const base64Audio fileContent.toString(base64);const form new FormData();form.append(media, fs.createReadStream(filePath));const voice_id Date.now().toString();const url https://api.weixin.qq.com/cgi-bin/media/voice/addvoicetorecofortext?access_token${accessToken}formatmp3voice_id${voice_id}langzh_CNconsole.log(Calling WeChat API..., url);const response await axios.post(url,form,{headers: form.getHeaders(),});console.log(WeChat API response:, response.data);if (response.data.errcode) {throw new Error(WeChat API error: ${response.data.errmsg});}const queryRecoresultUrl https://api.weixin.qq.com/cgi-bin/media/voice/queryrecoresultfortext?access_token${accessToken}voice_id${voice_id}langzh_CNconst res await axios.post(queryRecoresultUrl,{},{headers: { Content-Type: application/json }});console.log(xxxxx, res.data)return res.data.result;} catch (error) {console.error(Error recognizing speech:, error);throw error;}
}// 处理语音文件上传和识别
app.post(/upload, upload.single(file), async (req, res) {if (!req.file) {return res.status(400).send(No file uploaded.);}console.log(File uploaded:, req.file);try {let accessToken;let recognitionResult;let retries 1;while (retries 0) {try {accessToken await getAccessToken();console.log(Got access token:, accessToken);recognitionResult await recognizeSpeech(accessToken, uploads/0.mp3);console.log(Recognition result:, recognitionResult);break;} catch (error) {console.error(Attempt failed, retries left: ${retries - 1}, error);retries--;if (retries 0) throw error;await new Promise(resolve setTimeout(resolve, 1000)); // 等待1秒后重试}}// 删除临时文件fs.unlinkSync(req.file.path);res.json({ text: recognitionResult });} catch (error) {console.error(Error:, error);res.status(500).send(Server error: error.message);}
});// 启动服务器
app.listen(PORT, () {console.log(Server is running on http://localhost:${PORT});
});三、返回示例 四、遗留问题
可能由于个人水平问题有以后遗留问题如果大家解决方案或问题欢迎随时交流
此代码在服务端写死了一个待转换的mp3文件因为开发环境本底录音无法试听录音不知道什么原因可能会有一半不会被翻译暂时没有找到解决方案多次上传同一个录音后会返回空的转换结果