微信小程序实现录音转文字,并调用后端服务(Node.js)进行语音识别和,然后调用DeepSeek 处理的完整实现。
整体架构
- 前端(微信小程序):
- 实现录音功能。
- 将录音文件上传到后端。
- 接收后端返回的语音识别结果,并显示在可编辑的文本框中。
- 调用 DeepSeek 处理文本。
- 后端(Node.js):
- 接收小程序上传的录音文件。
- 调用腾讯云语音识别(ASR)服务,将语音转换为文字。
- 返回识别结果给小程序。
- 提供 DeepSeek 处理接口。
步骤 1:后端开发(Node.js)
1. 项目结构
复制
backend/
├── server.js # 主入口文件
├── config.js # 配置文件
├── asrService.js # 腾讯云语音识别服务
├── deepseekService.js # DeepSeek 处理服务
└── package.json # 依赖文件
2. 安装依赖
bash
复制
npm install express multer tencentcloud-sdk-nodejs axios
3. 配置文件 (config.js
)
javascript
复制
module.exports = {
tencentCloud: {
secretId: 'your-tencent-secret-id', // 腾讯云 SecretId
secretKey: 'your-tencent-secret-key', // 腾讯云 SecretKey
region: 'ap-guangzhou' // 腾讯云区域
},
deepseek: {
apiKey: 'your-deepseek-api-key', // DeepSeek API 密钥
apiUrl: 'https://api.deepseek.com/v1/chat/completions' // DeepSeek API 地址
}
};
4. 腾讯云语音识别服务 (asrService.js
)
javascript
复制
const tencentcloud = require('tencentcloud-sdk-nodejs');
const AsrClient = tencentcloud.asr.v20190614.Client;
const { tencentCloud } = require('./config');
const client = new AsrClient({
credential: {
secretId: tencentCloud.secretId,
secretKey: tencentCloud.secretKey,
},
region: tencentCloud.region,
profile: {
httpProfile: {
endpoint: 'asr.tencentcloudapi.com',
},
},
});
/**
* 调用腾讯云语音识别
* @param {string} audioBase64 - 音频文件的 base64 数据
* @returns {Promise<string>} - 识别结果
*/
async function recognizeAudio(audioBase64) {
const params = {
EngineModelType: '16k_zh', // 16k 中文普通话
VoiceFormat: 'wav', // 音频格式
Data: audioBase64 // 音频数据
};
const response = await client.SentenceRecognition(params);
return response.Result;
}
module.exports = { recognizeAudio };
5. DeepSeek 处理服务 (deepseekService.js
)
javascript
复制
const axios = require('axios');
const { deepseek } = require('./config');
/**
* 调用 DeepSeek 处理文本
* @param {string} text - 需要处理的文本
* @returns {Promise<string>} - 处理结果
*/
async function processText(text) {
const response = await axios.post(
deepseek.apiUrl,
{
model: 'deepseek-chat',
messages: [
{ role: 'system', content: '你是一个文本处理助手。' },
{ role: 'user', content: text }
]
},
{
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${deepseek.apiKey}`
}
}
);
return response.data.choices[0].message.content;
}
module.exports = { processText };
6. 主入口文件 (server.js
)
javascript
复制
const express = require('express');
const multer = require('multer');
const { recognizeAudio } = require('./asrService');
const { processText } = require('./deepseekService');
const path = require('path');
const app = express();
const upload = multer({ dest: 'uploads/' }); // 临时存储上传文件
// 语音识别接口
app.post('/api/recognize', upload.single('audio'), async (req, res) => {
try {
const filePath = req.file.path;
const fileData = require('fs').readFileSync(filePath, { encoding: 'base64' });
const result = await recognizeAudio(fileData);
res.json({ success: true, data: result });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
});
// DeepSeek 处理接口
app.post('/api/process', express.json(), async (req, res) => {
try {
const { text } = req.body;
const result = await processText(text);
res.json({ success: true, data: result });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
});
// 启动服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
步骤 2:前端开发(微信小程序)
1. 项目结构
复制
miniprogram/
├── pages/
│ ├── index/
│ │ ├── index.js # 页面逻辑
│ │ ├── index.wxml # 页面结构
│ │ └── index.wxss # 页面样式
├── app.js # 小程序逻辑
├── app.json # 小程序配置
└── app.wxss # 全局样式
2. 页面逻辑 (index.js
)
javascript
复制
const app = getApp();
Page({
data: {
isRecording: false, // 是否正在录音
recordTime: 0, // 录音时长
resultText: '', // 识别结果
editedText: '', // 编辑后的文本
isLoading: false // 加载状态
},
// 开始录音
startRecord() {
this.setData({ isRecording: true, recordTime: 0 });
this.recorderManager = wx.getRecorderManager();
this.recorderManager.start({
format: 'wav', // 录音格式
sampleRate: 16000, // 采样率
numberOfChannels: 1, // 声道数
encodeBitRate: 48000 // 编码码率
});
this.timer = setInterval(() => {
this.setData({ recordTime: this.data.recordTime + 1 });
}, 1000);
this.recorderManager.onStop((res) => {
clearInterval(this.timer);
this.setData({ isRecording: false });
this.uploadAudio(res.tempFilePath); // 上传录音文件
});
},
// 停止录音
stopRecord() {
if (this.recorderManager) {
this.recorderManager.stop();
}
},
// 上传录音文件
uploadAudio(filePath) {
this.setData({ isLoading: true });
wx.uploadFile({
url: 'http://localhost:3000/api/recognize', // 后端语音识别接口
filePath: filePath,
name: 'audio',
success: (res) => {
const result = JSON.parse(res.data);
if (result.success) {
this.setData({ resultText: result.data, editedText: result.data });
} else {
wx.showToast({ title: '识别失败', icon: 'none' });
}
},
fail: (err) => {
wx.showToast({ title: '上传失败', icon: 'none' });
},
complete: () => {
this.setData({ isLoading: false });
}
});
},
// 编辑文本
handleEditText(e) {
this.setData({ editedText: e.detail.value });
},
// 调用 DeepSeek 处理文本
processText() {
const { editedText } = this.data;
if (!editedText) {
wx.showToast({ title: '请输入文本', icon: 'none' });
return;
}
this.setData({ isLoading: true });
wx.request({
url: 'http://localhost:3000/api/process', // 后端 DeepSeek 处理接口
method: 'POST',
data: { text: editedText },
success: (res) => {
if (res.data.success) {
this.setData({ resultText: res.data.data });
} else {
wx.showToast({ title: '处理失败', icon: 'none' });
}
},
fail: (err) => {
wx.showToast({ title: '网络错误', icon: 'none' });
},
complete: () => {
this.setData({ isLoading: false });
}
});
}
});
3. 页面结构 (index.wxml
)
xml
复制
<view class="container">
<!-- 录音按钮 -->
<view class="record-button">
<button
bindtap="{{isRecording ? 'stopRecord' : 'startRecord'}}"
class="{{isRecording ? 'stop-button' : 'start-button'}}"
>
{{isRecording ? '停止录音' : '开始录音'}}
</button>
<text class="record-time" wx:if="{{isRecording}}">{{recordTime}}s</text>
</view>
<!-- 识别结果 -->
<view class="result-box">
<text class="result-title">识别结果:</text>
<textarea
value="{{editedText}}"
bindinput="handleEditText"
placeholder="识别结果将显示在这里"
class="result-text"
></textarea>
</view>
<!-- 处理按钮 -->
<button bindtap="processText" class="process-button">调用 DeepSeek 处理</button>
<!-- 处理结果 -->
<view class="result-box">
<text class="result-title">处理结果:</text>
<textarea
value="{{resultText}}"
placeholder="处理结果将显示在这里"
disabled
class="result-text"
></textarea>
</view>
<!-- 加载状态 -->
<view class="loading" wx:if="{{isLoading}}">
<text>处理中...</text>
</view>
</view>
运行 HTML
4. 页面样式 (index.wxss
)
css
复制
.container {
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.record-button {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20px;
}
.start-button {
background-color: #07c160;
color: white;
}
.stop-button {
background-color: #f5222d;
color: white;
}
.record-time {
margin-top: 10px;
font-size: 14px;
color: #666;
}
.result-box {
width: 100%;
margin-top: 20px;
}
.result-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
.result-text {
width: 100%;
height: 100px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
font-size: 14px;
}
.process-button {
margin-top: 20px;
background-color: #1890ff;
color: white;
}
.loading {
margin-top: 20px;
font-size: 14px;
color: #666;
}
5. 小程序配置 (app.json
)
json
复制
{
"pages": [
"pages/index/index"
],
"window": {
"navigationBarTitleText": "录音转文字",
"navigationBarBackgroundColor": "#07c160",
"navigationBarTextStyle": "white"
}
}
步骤 3:测试
启动后端服务:
bash
复制
node server.js
在微信开发者工具中运行小程序。
测试录音、语音识别、文本编辑和 DeepSeek 处理功能。
注意事项
- 后端部署:
- 将后端服务部署到云服务器(如腾讯云、阿里云),并配置 HTTPS。
- API 密钥安全:
- 不要将 API 密钥暴露在前端代码中。
- 录音权限:
- 确保小程序已获取录音权限。