feat(mobile): add voice transcription to practice

This commit is contained in:
2026-07-09 13:41:48 +08:00
parent 04405b5e11
commit 4ef388873b
6 changed files with 245 additions and 2 deletions
+67
View File
@@ -0,0 +1,67 @@
import type { AsrResponse, SpeechSelectedFile } from '@/types/api';
import { apiUrl, authHeaders, readTextPayload } from './api';
const audioExtensions = ['.mp3', '.wav', '.m4a', '.webm', '.aac', '.ogg'];
export const chooseSpeechAudio = () =>
new Promise<SpeechSelectedFile>((resolve, reject) => {
uni.chooseFile({
count: 1,
type: 'all',
extension: audioExtensions,
success: (result) => {
const tempFiles = Array.isArray(result.tempFiles) ? result.tempFiles : [];
const file = (tempFiles[0] || {}) as Partial<SpeechSelectedFile>;
const path = file.path || result.tempFilePaths?.[0] || '';
if (!path) {
reject(new Error('未获取到音频文件'));
return;
}
resolve({
path,
name: file.name || path.split('/').pop() || 'practice-audio',
size: Number(file.size || 0)
});
},
fail: () => reject(new Error('未选择音频'))
});
});
export const transcribeSpeechFile = (file: SpeechSelectedFile) =>
new Promise<AsrResponse>((resolve, reject) => {
uni.uploadFile({
url: apiUrl('/api/ai/asr'),
filePath: file.path,
name: 'file',
header: authHeaders(false),
success: (response) => {
try {
resolve(readTextPayload<AsrResponse>(response.statusCode, response.data));
} catch (error) {
reject(error);
}
},
fail: () => reject(new Error('语音上传失败'))
});
});
export const transcribeSpeechBlob = (blob: Blob, filename = 'practice-audio.webm') =>
new Promise<AsrResponse>((resolve, reject) => {
const form = new FormData();
form.append('file', blob, filename);
const xhr = new XMLHttpRequest();
xhr.open('POST', apiUrl('/api/ai/asr'));
xhr.timeout = 45000;
Object.entries(authHeaders(false)).forEach(([key, value]) => xhr.setRequestHeader(key, value));
xhr.onload = () => {
try {
resolve(readTextPayload<AsrResponse>(xhr.status, xhr.responseText || '{}'));
} catch (error) {
reject(error);
}
};
xhr.onerror = () => reject(new Error('语音上传失败'));
xhr.ontimeout = () => reject(new Error('语音转写超时'));
xhr.send(form);
});