feat: 改造语音的实现逻辑

This commit is contained in:
2026-05-15 12:07:27 +08:00
parent f516e4fe2e
commit f71f432a45
4 changed files with 322 additions and 98 deletions

View File

@@ -11,19 +11,21 @@
data(){
return{
recorderStatus:null,
task_id:'',
}
},
methods:{
start(){
this.webSocekt();
},
stop(){
this.recorderStatus="stop";
if(ws){
ws.close();
}
},
task_id:'',
}
},
methods:{
start(){
this.task_id='';
this.webSocekt();
},
stop(){
this.recorderStatus={
status:"stop",
saveAudioFile: !this.options || this.options.saveAudioFile !== false,
time: Date.now()
};
},
toShowToast(){
uni.showToast({
title:'发生错误,请检查是否有麦克风权限',
@@ -31,11 +33,55 @@
});
this.recorderStatus="stop";
},
startRecorder(){
this.$emit('change',{status:"START",msg:"开始录音"});
},
webSocekt(){
ws = uni.connectSocket({
startRecorder(){
this.$emit('change',{status:"START",msg:"开始录音"});
},
recordStopped(data){
setTimeout(()=>{
this.finishTask();
},80);
if(data && data.saveAudioFile === false){
this.$emit('change',{status:"STOP",msg:{}});
}
},
finishTask(){
if(!ws || !this.task_id){
this.closeSocket();
return;
}
var param={
header: {
action: "finish-task",
task_id: this.task_id,
streaming: "duplex"
},
payload:{
input:{}
}
};
ws.send({
data:JSON.stringify(param),
fail:(err)=>{
this.$emit('change',{status:"ERROR",msg:err});
this.closeSocket();
}
});
},
closeSocket(){
if(ws){
var socket=ws;
ws=null;
try{
socket.close();
}catch(e){
}
}
},
webSocekt(){
ws = uni.connectSocket({
url: 'wss://dashscope.aliyuncs.com/api-ws/v1/inference',
header: {
"Authorization": "bearer "+this.options.apikey, // 将<your_dashscope_api_key>替换成您自己的API Key
@@ -71,25 +117,39 @@
ws.send({data:JSON.stringify(param)});
});
ws.onMessage((data)=>{
var msg=JSON.parse(data.data)
if(msg.header.event=="task-started"){
this.task_id=msg.header.task_id;
this.recorderStatus="start";
}
if(msg.header.event=="result-generated"){
this.$emit('result',msg.payload.output);
}
});
ws.onMessage((data)=>{
var msg=JSON.parse(data.data)
if(msg.header.event=="task-started"){
this.task_id=msg.header.task_id;
this.recorderStatus={
status:"start",
time: Date.now()
};
}
if(msg.header.event=="result-generated"){
this.$emit('result',msg.payload.output);
}
if(msg.header.event=="task-finished"){
this.$emit('change',{status:"FINISH",msg:msg.payload || {}});
this.closeSocket();
}
if(msg.header.event=="task-failed"){
this.$emit('change',{status:"ERROR",msg:msg});
this.closeSocket();
}
});
ws.onError((err)=>{
this.$emit('change',{status:"ERROR",msg:err});
});
ws.onClose(()=>{
this.$emit('change',{status:"CLOSE",msg:"连接已关闭"});
})
ws.onClose(()=>{
ws=null;
this.$emit('change',{status:"CLOSE",msg:"连接已关闭"});
})
},
generateRandom32() {
let result = '';
@@ -102,9 +162,10 @@
return result;
},
frameRecorded({isLastFrame,frameBuffer}){
ws.send({data:uni.base64ToArrayBuffer(frameBuffer)});
},
frameRecorded({isLastFrame,frameBuffer}){
if(!ws || !frameBuffer) return;
ws.send({data:uni.base64ToArrayBuffer(frameBuffer)});
},
recordedChunks(base64){
var fileName = 'YP'+Date.now();
@@ -207,16 +268,18 @@
let recordedChunks = [];
export default {
mounted() {
},
methods: {
async startRecord(val){
if(val==null) return;
if(val == "start"){
try{
recordedChunks = [];
async startRecord(val){
if(val==null) return;
const status = typeof val === 'object' ? val.status : val;
const saveAudioFile = typeof val === 'object' ? val.saveAudioFile !== false : true;
if(status == "start"){
try{
recordedChunks = [];
// 配置参数
var a, i = 16000,
s = 1280;
@@ -281,9 +344,9 @@
this.$ownerInstance.callMethod('toShowToast');
}
}else if(val == "stop"){
this.onStop();
}
}else if(status == "stop"){
this.onStop(saveAudioFile);
}
},
onFrameRecorded({isLastFrame,frameBuffer}){
@@ -298,7 +361,7 @@
}
return window.btoa(binary);
},
async onRecordedChunks(chunks){
async onRecordedChunks(chunks){
var mergedBuffer=this.mergeAudioBuffers(chunks);
// 2. 将合并的二进制流转换为WAV格式需要添加WAV文件头
@@ -307,13 +370,11 @@
const base64 = await this.blobToBase64(wavBlob);
this.$ownerInstance.callMethod('recordedChunks',base64)
},
onStop(){
this.onFrameRecorded({isLastFrame:true,frameBuffer:''});
this.onRecordedChunks(recordedChunks);
recordedChunks = [];
if (mediaStream) {
onStop(saveAudioFile = true){
const chunks = recordedChunks;
recordedChunks = [];
if (mediaStream) {
// 停止所有媒体轨道
mediaStream.getTracks().forEach(track => track.stop());
mediaStream = null;
@@ -327,11 +388,15 @@
if (audioContext) {
// 关闭音频上下文
audioContext.close().then(() => {
audioContext = null;
});
}
},
audioContext.close().then(() => {
audioContext = null;
});
}
this.$ownerInstance.callMethod('recordStopped',{saveAudioFile});
if(saveAudioFile){
this.onRecordedChunks(chunks);
}
},
//合并所有buffer
mergeAudioBuffers(buffers) {
let totalLength = buffers.reduce((acc, buf) => acc + buf.byteLength, 0);