'commit'
This commit is contained in:
@@ -93,4 +93,10 @@ HS_VOICE_TYPE_QINCANG = "BV701_V2_streaming" # 中年男声,用于朗读古
|
||||
#LibLib的配置
|
||||
LIBLIB_URL="https://openapi.liblibai.cloud"
|
||||
LIBLIB_ACCESSKEY="sOCtVLVTNOZkRMajlhzCmg"
|
||||
LIBLIB_SECRETKEY="PUe8QTRG9i0G9EbpedHmIpLQ0FyxoYY9"
|
||||
LIBLIB_SECRETKEY="PUe8QTRG9i0G9EbpedHmIpLQ0FyxoYY9"
|
||||
|
||||
|
||||
# 科大讯飞
|
||||
XF_APPID="5b83f8d6"
|
||||
XF_APISECRET="604fa6cb9c5ab664a0d153fe0ccc6802"
|
||||
XF_APIKEY="5beb887923204000bfcb402046bb05a6"
|
Binary file not shown.
@@ -2,12 +2,12 @@ import logging
|
||||
import os
|
||||
import uuid
|
||||
import time
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks, Query, UploadFile, File
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks, Query, UploadFile, File, Form
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
import tempfile
|
||||
from Util.ObsUtil import ObsUploader
|
||||
from Config.Config import OBS_BUCKET, OBS_SERVER
|
||||
from Config.Config import OBS_BUCKET, OBS_SERVER, XF_APPID, XF_APISECRET, XF_APIKEY
|
||||
from fastapi.responses import StreamingResponse
|
||||
import requests
|
||||
|
||||
@@ -36,19 +36,19 @@ class AudioEvaluationResponse(BaseModel):
|
||||
|
||||
# 科大讯飞API配置(需要根据实际情况配置)
|
||||
XUNFEI_CONFIG = {
|
||||
"appid": "your_appid_here",
|
||||
"api_key": "your_api_key_here",
|
||||
"api_secret": "your_api_secret_here"
|
||||
"appid": XF_APPID,
|
||||
"api_key": XF_APISECRET,
|
||||
"api_secret": XF_APIKEY
|
||||
}
|
||||
|
||||
@router.post("/evaluate-audio", response_model=AudioEvaluationResponse)
|
||||
async def evaluate_audio(
|
||||
background_tasks: BackgroundTasks,
|
||||
language: str = Query("chinese", description="评测语言: chinese 或 english"),
|
||||
text: str = Query(..., description="评测文本内容"),
|
||||
group: str = Query("adult", description="群体类型: adult, youth, pupil"),
|
||||
check_type: str = Query("common", description="检错严格程度: easy, common, hard"),
|
||||
grade: str = Query("middle", description="学段: junior, middle, senior"),
|
||||
language: str = Form("chinese", description="评测语言: chinese 或 english"),
|
||||
text: str = Form(..., description="评测文本内容"),
|
||||
group: str = Form("adult", description="群体类型: adult, youth, pupil"),
|
||||
check_type: str = Form("common", description="检错严格程度: easy, common, hard"),
|
||||
grade: str = Form("middle", description="学段: junior, middle, senior"),
|
||||
audio_file: UploadFile = File(...)):
|
||||
"""
|
||||
语音评测接口 - 支持中文和英文篇章朗读判分
|
||||
|
Binary file not shown.
@@ -104,7 +104,6 @@
|
||||
<div class="form-group">
|
||||
<button id="recordBtn" class="btn btn-record">开始录音</button>
|
||||
<button id="stopBtn" class="btn btn-stop" disabled>停止录音</button>
|
||||
<button id="evaluateBtn" class="btn" disabled>提交评测</button>
|
||||
</div>
|
||||
|
||||
<div id="status" class="status">准备就绪</div>
|
||||
@@ -125,7 +124,7 @@
|
||||
const textInput = document.getElementById('text');
|
||||
const recordBtn = document.getElementById('recordBtn');
|
||||
const stopBtn = document.getElementById('stopBtn');
|
||||
const evaluateBtn = document.getElementById('evaluateBtn');
|
||||
// 删除提交按钮引用
|
||||
const statusDiv = document.getElementById('status');
|
||||
const resultDiv = document.getElementById('result');
|
||||
const resultContent = document.getElementById('resultContent');
|
||||
@@ -150,6 +149,24 @@
|
||||
statusDiv.textContent = '正在获取麦克风权限...';
|
||||
statusDiv.className = 'status';
|
||||
|
||||
// ==== 插入WebSocket认证代码 ====
|
||||
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const wsUrl = `${wsProtocol}//${window.location.host}/ws/audio-evaluation?token=${getAuthToken()}`;
|
||||
const ws = new WebSocket(wsUrl);
|
||||
|
||||
// WebSocket事件处理
|
||||
ws.onopen = () => {
|
||||
console.log('WebSocket连接已建立');
|
||||
statusDiv.textContent = 'WebSocket连接已建立,准备录音...';
|
||||
};
|
||||
|
||||
ws.onerror = (error) => {
|
||||
console.error('WebSocket错误:', error);
|
||||
statusDiv.textContent = 'WebSocket连接失败,请刷新页面重试';
|
||||
statusDiv.className = 'status error';
|
||||
};
|
||||
// ==== 插入结束 ====
|
||||
|
||||
// 使用更明确的提示并添加详细的错误处理
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
|
||||
.catch(err => {
|
||||
@@ -174,8 +191,10 @@
|
||||
|
||||
mediaRecorder.onstop = () => {
|
||||
audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
|
||||
statusDiv.textContent = '录音完成,可以提交评测';
|
||||
evaluateBtn.disabled = false;
|
||||
statusDiv.textContent = '录音完成,正在自动提交评测...';
|
||||
// 添加WebSocket关闭逻辑
|
||||
if (ws) ws.close(1000, '录音已完成');
|
||||
submitEvaluation();
|
||||
};
|
||||
|
||||
// 添加录音最大时长限制(60秒)
|
||||
@@ -218,8 +237,8 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 提交评测
|
||||
evaluateBtn.addEventListener('click', async () => {
|
||||
// 将提交评测逻辑提取为独立函数
|
||||
async function submitEvaluation() {
|
||||
if (!audioBlob) {
|
||||
statusDiv.textContent = '请先完成录音';
|
||||
statusDiv.className = 'status error';
|
||||
@@ -235,7 +254,6 @@
|
||||
try {
|
||||
statusDiv.textContent = '正在提交评测...';
|
||||
statusDiv.className = 'status';
|
||||
evaluateBtn.disabled = true;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('audio_file', audioBlob, 'recording.webm');
|
||||
@@ -268,10 +286,8 @@
|
||||
console.error('评测失败:', error);
|
||||
statusDiv.textContent = '评测失败: ' + error.message;
|
||||
statusDiv.className = 'status error';
|
||||
} finally {
|
||||
evaluateBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 显示评测结果
|
||||
function displayResults(results) {
|
||||
@@ -313,6 +329,16 @@
|
||||
|
||||
resultContent.innerHTML = html;
|
||||
}
|
||||
// 在<script>标签内添加getAuthToken实现
|
||||
function getAuthToken() {
|
||||
// 实际项目中应从Cookie、localStorage或后端API获取
|
||||
return 'your_auth_token_here'; // 临时占位,需替换为真实认证逻辑
|
||||
}
|
||||
|
||||
// 页面卸载时关闭连接
|
||||
window.addEventListener('beforeunload', () => {
|
||||
if (ws) ws.close(1001, '页面即将关闭');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user