'commit'
This commit is contained in:
152
dsLightRag/static/YunXiao/xueban.js
Normal file
152
dsLightRag/static/YunXiao/xueban.js
Normal file
@@ -0,0 +1,152 @@
|
||||
// 学伴录音功能核心逻辑
|
||||
// 模型配置
|
||||
|
||||
// 录音相关变量
|
||||
let mediaRecorder; let audioChunks = []; let isRecording = false;
|
||||
// 音频播放相关变量
|
||||
let audioElement = null; let isPlaying = false;
|
||||
|
||||
// 获取URL参数
|
||||
function getUrlParam(name) {
|
||||
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
|
||||
const r = window.location.search.substr(1).match(reg);
|
||||
return r ? unescape(r[2]) : null;
|
||||
}
|
||||
|
||||
// 开始录音
|
||||
function startRecording() {
|
||||
if (isRecording) return;
|
||||
|
||||
console.log("尝试开始录音");
|
||||
navigator.mediaDevices.getUserMedia({ audio: true })
|
||||
.then(stream => {
|
||||
mediaRecorder = new MediaRecorder(stream);
|
||||
audioChunks = [];
|
||||
|
||||
mediaRecorder.ondataavailable = event => {
|
||||
if (event.data.size > 0) audioChunks.push(event.data);
|
||||
};
|
||||
|
||||
mediaRecorder.onstop = () => {
|
||||
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
|
||||
console.log("录音完成,音频数据大小:", audioBlob.size);
|
||||
uploadAudioToServer(audioBlob);
|
||||
};
|
||||
|
||||
mediaRecorder.start();
|
||||
isRecording = true;
|
||||
document.getElementById('recordingIndicator').style.display = 'flex';
|
||||
document.getElementById('startRecordBtn').style.display = 'none';
|
||||
document.getElementById('stopRecordBtn').style.display = 'flex';
|
||||
console.log("开始录音成功");
|
||||
|
||||
// 设置最长录音时间为60秒
|
||||
setTimeout(stopRecording, 60000);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("获取麦克风权限失败:", error);
|
||||
alert("请授权麦克风权限以使用录音功能");
|
||||
});
|
||||
}
|
||||
|
||||
// 停止录音
|
||||
function stopRecording() {
|
||||
if (!isRecording || !mediaRecorder) return;
|
||||
|
||||
mediaRecorder.stop();
|
||||
isRecording = false;
|
||||
document.getElementById('recordingIndicator').style.display = 'none';
|
||||
document.getElementById('startRecordBtn').style.display = 'flex';
|
||||
document.getElementById('stopRecordBtn').style.display = 'none';
|
||||
console.log("停止录音");
|
||||
|
||||
if (mediaRecorder.stream) {
|
||||
mediaRecorder.stream.getTracks().forEach(track => track.stop());
|
||||
}
|
||||
}
|
||||
|
||||
// 上传音频到服务器
|
||||
function uploadAudioToServer(audioBlob) {
|
||||
console.log("开始上传音频到服务器");
|
||||
document.getElementById('thinkingIndicator').style.display = 'flex';
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', audioBlob, 'recording.wav');
|
||||
|
||||
fetch('/api/xueban/upload-audio', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error('服务器响应错误');
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
console.log("处理结果:", data);
|
||||
document.getElementById('thinkingIndicator').style.display = 'none';
|
||||
|
||||
if (data.success) {
|
||||
showResults(data.data);
|
||||
} else {
|
||||
alert('音频处理失败: ' + data.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("上传音频失败:", error);
|
||||
document.getElementById('thinkingIndicator').style.display = 'none';
|
||||
alert('上传音频失败: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
// 显示ASR识别结果和反馈
|
||||
function showResults(data) {
|
||||
const resultContainer = document.getElementById('resultContainer');
|
||||
resultContainer.style.display = 'flex';
|
||||
|
||||
document.getElementById('asrResultText').textContent = data.asr_text || '未识别到内容';
|
||||
document.getElementById('feedbackResultText').textContent = data.feedback_text || '无反馈内容';
|
||||
|
||||
if (data.audio_url) {
|
||||
if (audioElement) audioElement.pause();
|
||||
audioElement = new Audio(data.audio_url);
|
||||
audioElement.onloadedmetadata = function() {
|
||||
updateAudioTimeDisplay();
|
||||
try { audioElement.play(); isPlaying = true; updatePlayButton(); }
|
||||
catch (e) { console.error("自动播放失败:", e); }
|
||||
};
|
||||
audioElement.ontimeupdate = function() { updateAudioProgress(); updateAudioTimeDisplay(); };
|
||||
audioElement.onended = function() { isPlaying = false; updatePlayButton(); };
|
||||
document.getElementById('playAudioBtn').onclick = togglePlayAudio;
|
||||
document.getElementById('audioProgress').onclick = function(e) {
|
||||
const rect = this.getBoundingClientRect();
|
||||
audioElement.currentTime = (e.clientX - rect.left) / rect.width * audioElement.duration;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 音频播放控制函数
|
||||
function togglePlayAudio() {
|
||||
if (!audioElement) return;
|
||||
isPlaying ? audioElement.pause() : audioElement.play();
|
||||
isPlaying = !isPlaying;
|
||||
updatePlayButton();
|
||||
}
|
||||
|
||||
function updatePlayButton() {
|
||||
const btn = document.getElementById('playAudioBtn');
|
||||
btn.innerHTML = isPlaying ?
|
||||
'<svg width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M6 19H10V5H6V19ZM14 19H18V5H14V19Z" fill="white"/></svg>' :
|
||||
'<svg width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M8 5V19L19 12L8 5Z" fill="white"/></svg>';
|
||||
}
|
||||
|
||||
function updateAudioProgress() {
|
||||
if (!audioElement) return;
|
||||
const progress = (audioElement.currentTime / audioElement.duration) * 100;
|
||||
document.getElementById('progressBar').style.width = `${progress}%`;
|
||||
}
|
||||
|
||||
function updateAudioTimeDisplay() {
|
||||
if (!audioElement) return;
|
||||
const format = s => `${Math.floor(s/60).toString().padStart(2,'0')}:${Math.floor(s%60).toString().padStart(2,'0')}`;
|
||||
document.getElementById('audioTime').textContent = `${format(audioElement.currentTime)} / ${format(audioElement.duration)}`;
|
||||
}
|
Reference in New Issue
Block a user