<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useIsMystore } from '@/store/index'
const myStore = useIsMystore()
const emit = defineEmits(['talkMsg'])
const meetingInfo = JSON.parse(myStore.userInfo).meetingInfo
const userInfo = JSON.parse(myStore.userInfo).user
const currentSessionId = ref(null);
const eventSource = ref(null);
const isLlmEnabled = ref(false);
const lastRecognitionText = ref(null);
const mediaRecorder = ref(null);
const audioContext = ref(null);
const websocket = ref(null);
const isRecording = ref(false);
const initAudio = async () => {
try {
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
throw new Error('您的浏览器不支持访问麦克风。请使用最新版本的 Chrome、Firefox 或 Edge 浏览器。');
}
const devices = await navigator.mediaDevices.enumerateDevices();
const audioInputs = devices.filter(device => device.kind === 'audioinput');
if (audioInputs.length === 0) {
throw new Error('未检测到麦克风设备。请确保您的设备已正确连接麦克风。');
}
console.log('可用的音频输入设备:', audioInputs);
const stream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true
}
});
const audioContext = new (window.AudioContext || window.webkitAudioContext)({
sampleRate: 16000
});
const source = audioContext.createMediaStreamSource(stream);
const processor = audioContext.createScriptProcessor(4096, 1, 1);
source.connect(processor);
processor.connect(audioContext.destination);
processor.onaudioprocess = (e) => {
if (websocket.value && websocket.value.readyState === WebSocket.OPEN) {
const inputData = e.inputBuffer.getChannelData(0);
const pcmData = new Int16Array(inputData.length);
for (let i = 0; i < inputData.length; i++) {
pcmData[i] = Math.max(-32768, Math.min(32767, Math.round(inputData[i] * 32768)));
}
websocket.value.send(pcmData.buffer);
}
};
mediaRecorder.value = {
stream: stream,
processor: processor,
source: source,
context: audioContext,
stop: () => {
processor.disconnect();
source.disconnect();
stream.getTracks().forEach(track => track.stop());
}
};
return stream;
} catch (error) {
console.error('Error accessing microphone:', error);
let errorMessage = '无法访问麦克风: ';
if (error.name === 'NotFoundError') {
errorMessage += '未找到麦克风设备。请确保您的设备已正确连接麦克风。';
} else if (error.name === 'NotAllowedError') {
errorMessage += '麦克风访问被拒绝。请在浏览器设置中允许访问麦克风。';
} else if (error.name === 'NotReadableError') {
errorMessage += '麦克风可能被其他应用程序占用。请关闭其他使用麦克风的应用程序后重试。';
} else {
errorMessage += error.message || '未知错误';
}
throw error;
}
}
const createWebSocket = (sessionId) => {
let wsUrl = `${configURl[import.meta.env.MODE].talkSocketUrl}/seminar/speechWebsocket/${meetingInfo.id}/${userInfo.id}`;
ws://1.1.1.1:1111/speechWebsocket/{meetingId}/{userId}
websocket.value = new WebSocket(wsUrl);
websocket.value.onopen = () => {
console.log('WebSocket connection established');
};
websocket.value.onmessage = (event) => {
const data = JSON.parse(event.data);
lastRecognitionText.value = data.content;
console.log(data)
emit('talkMsg', data)
};
websocket.value.onerror = (error) => {
console.error('WebSocket error:', error);
};
websocket.value.onclose = () => {
console.log('WebSocket connection closed');
};
}
const startRecording = async () => {
try {
const stream = await initAudio();
mediaRecorder.value = new MediaRecorder(stream, {
mimeType: 'audio/webm;codecs=opus',
audioBitsPerSecond: 16000
});
mediaRecorder.value.ondataavailable = (event) => {
if (event.data.size > 0 && websocket.value && websocket.value.readyState === WebSocket.OPEN) {
event.data.arrayBuffer().then(buffer => {
websocket.value.send(buffer);
});
}
};
mediaRecorder.value.start(100);
isRecording.value = true;
} catch (error) {
console.error('Error starting recording:', error);
}
}
const stopRecording = () => {
if (mediaRecorder.value && isRecording.value) {
mediaRecorder.value.stop();
mediaRecorder.value.stream.getTracks().forEach(track => track.stop());
isRecording.value = false;
}
if (websocket.value) {
websocket.value.disconnect();
}
}
onMounted(() => {
})
const init = () => {
createWebSocket()
startRecording()
}
defineExpose({ init })
</script>