fix: 讯飞鉴权签名与官方demo对齐+结束帧+文字修改
- ReportEditor: getXfAuthUrl signatureOrigin去掉引号,Base64改用CryptoJS.enc.Base64.stringify与demo完全一致 - ReportEditor: 第一帧增加dwa: wpgs动态修正参数 - ReportEditor: 停止录音时先发送status:2结束帧再关闭WebSocket - SystemSettings: 标题改为讯飞语音听写Websocket接口配置
This commit is contained in:
@@ -897,11 +897,11 @@ export default function ReportEditor() {
|
||||
async function getXfAuthUrl(apiKey: string, apiSecret: string): Promise<string> {
|
||||
const host = 'iat-api.xfyun.cn';
|
||||
const date = new Date().toUTCString();
|
||||
const signatureOrigin = `host: "${host}"\ndate: "${date}"\nGET /v2/iat HTTP/1.1`;
|
||||
const signature = CryptoJS.HmacSHA256(signatureOrigin, apiSecret).toString(CryptoJS.enc.Base64);
|
||||
const signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/iat HTTP/1.1`;
|
||||
const signature = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(signatureOrigin, apiSecret));
|
||||
const authorizationOrigin = `api_key="${apiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${signature}"`;
|
||||
const authorization = btoa(authorizationOrigin);
|
||||
return `wss://iat-api.xfyun.cn/v2/iat?authorization=${encodeURIComponent(authorization)}&date=${encodeURIComponent(date)}&host=${encodeURIComponent(host)}`;
|
||||
const authorization = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(authorizationOrigin));
|
||||
return `wss://iat-api.xfyun.cn/v2/iat?authorization=${authorization}&date=${date}&host=${host}`;
|
||||
}
|
||||
|
||||
function floatTo16BitPCM(input: Float32Array): ArrayBuffer {
|
||||
@@ -925,6 +925,12 @@ export default function ReportEditor() {
|
||||
const toggleListening = async () => {
|
||||
if (isListening) {
|
||||
setIsListening(false);
|
||||
if (xfWsRef.current && xfWsRef.current.readyState === WebSocket.OPEN) {
|
||||
try {
|
||||
const endFrame = { data: { status: 2, format: 'audio/L16;rate=16000', encoding: 'raw', audio: '' } };
|
||||
xfWsRef.current.send(JSON.stringify(endFrame));
|
||||
} catch {}
|
||||
}
|
||||
if (xfWsRef.current) { try { xfWsRef.current.close(); } catch {} xfWsRef.current = null; }
|
||||
if (xfAudioContextRef.current) { try { xfAudioContextRef.current.close(); } catch {} xfAudioContextRef.current = null; }
|
||||
if (xfMediaStreamRef.current) { xfMediaStreamRef.current.getTracks().forEach(t => t.stop()); xfMediaStreamRef.current = null; }
|
||||
@@ -955,7 +961,7 @@ export default function ReportEditor() {
|
||||
const pcmBuffer = floatTo16BitPCM(inputData);
|
||||
const base64Audio = arrayBufferToBase64(pcmBuffer);
|
||||
const frame: any = { data: { status: frameStatus, format: 'audio/L16;rate=16000', encoding: 'raw', audio: base64Audio } };
|
||||
if (frameStatus === 0) { frame.common = { app_id: xfConfig.appId }; frame.business = { language: 'zh_cn', domain: 'iat', accent: 'mandarin' }; }
|
||||
if (frameStatus === 0) { frame.common = { app_id: xfConfig.appId }; frame.business = { language: 'zh_cn', domain: 'iat', accent: 'mandarin', dwa: 'wpgs' }; }
|
||||
ws.send(JSON.stringify(frame));
|
||||
frameStatus = 1;
|
||||
};
|
||||
|
||||
@@ -429,7 +429,7 @@ export default function SystemSettings() {
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h3 className="text-lg font-bold text-text-main flex items-center gap-2">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-accent"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>
|
||||
讯飞语音配置
|
||||
讯飞语音听写Websocket接口配置
|
||||
</h3>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
|
||||
Reference in New Issue
Block a user