- 作者:老汪软件技巧
- 发表时间:2024-08-30 17:01
- 浏览量:
前言
在上一篇文章里面(传送门),我利用 vue3 langchain.js node.js 实现了一个能够和ai进行对话的dmeo, 主要的功能是前端进行语音识别,把识别到的文字传给后端,然后后端调用大模型,返回文字。从现在开始,我逐渐要把这个demo完善,升级为一个小项目。
主要升级的点有:
前端实现录音功能
前端的录音功能这里是用MediaRecorder来实现的。
const mediaRecorder = ref(null)
const chunks = ref([])
const blob = ref(null)
navigator.mediaDevices
.getUserMedia({ audio: true })
.then((stream) => {
mediaRecorder.value = new MediaRecorder(stream)
mediaRecorder.value.start()
mediaRecorder.value.addEventListener('stop', () => {
blob.value = new Blob(chunks.value, { type: 'audio/webm' })
chunks.value = []
recordFinish.value = true
})
mediaRecorder.value.addEventListener('dataavailable', (e) => {
chunks.value.push(e.data)
})
})
.catch((error) => {
console.error('Error:', error)
})
前端这里的处理比较简单,只要得到录制完成的blob数据就可以。
后端处理音频文件
后端这里的处理,主要就是把得到的音频文件传给百度的接口,但是这里会涉及到音频格式的转化,因为百度的语音识别对音频的格式有特定的要求,所以这里用到了ffmpeg这个包。
router.post('/tts', upload.single('audio'), async (ctx) => {
const file = ctx.req.file
const webmFilePath = path.join('uploads', file.filename)
const wavFilePath = path.join(`${webmFilePath.replace('.webm', '')}.wav`)
await new Promise((resolve, reject) => {
ffmpeg(webmFilePath)
.output(wavFilePath)
.format('wav')
.outputOptions('-sample_fmt s16')
.outputOptions('-ar 16000')
.outputOptions('-ac 1')
.on('end', async () => {
let voice = fs.readFileSync(wavFilePath)
let voiceBase64 = Buffer.from(voice)
try {
const res = await ttsClient.recognize(voiceBase64, 'wav', 16000, {
dev_pid: 1737
})
ctx.body = {
message: '',
code: 200,
data: {
content: Array.isArray(res.result) ? res.result[0] : res.result
}
}
resolve()
} catch (err) {
console.log('err-', err)
}
})
.on('error', (err) => {
console.error('Error during conversion:', err)
reject(err)
})
.run()
})
})
语音合成
这里的语音合成主要是针对AI输出的文字,进行语音合成。对于我们自己的声音,因为已经进行了录音,前端是有音频数据的,所以只要直接播放就能听到自己的声音了。
而对于AI返回文字的语音合成,这部分主要是后端调用一下百度的语音合成的接口:
const input = ctx.request.body.input
const config = ctx.request.body.config
try {
const res = await ttsClient.text2audio(input, config)
ctx.set('Content-Type', 'audio/mpeg')
ctx.set('Content-Disposition', 'attachment; filename=tts.mpVoice.mp3')
ctx.body = res.data
} catch (err) {
console.log('err', err)
}
项目地址
感兴趣的朋友,可以用安卓手机体验一下
项目体验地址:italk