AKIRA
Finalize all local changes
b3b0b53
raw
history blame
6.43 kB
// FINAL VERSION: v30 - Robust error handling and UI updates
// Helper function to show detailed errors
function showDetailedError(title, content) {
wx.showModal({
title: title,
content: typeof content === 'object' ? JSON.stringify(content) : String(content),
showCancel: false
});
}
Page({
data: {
languages: {
'zh': { name: '中文', flag: 'cn' },
'en': { name: 'English', flag: 'us' },
'ja': { name: '日本語', flag: 'jp' },
'ko': { name: '한국어', flag: 'kr' }
},
sourceLang: 'zh',
targetLang: 'en',
transcript: '',
outputText: '',
isRecording: false,
hfSpaceUrl: 'https://dazaozi-wechat-translator-app.hf.space',
},
onLoad: function () {
this.recorderManager = wx.getRecorderManager();
this.initRecorderManager();
this.setData({
sourceLanguages: Object.keys(this.data.languages).map(key => ({ ...this.data.languages[key], langCode: key })),
targetLanguages: Object.keys(this.data.languages).map(key => ({ ...this.data.languages[key], langCode: key }))
});
},
// --- Language Selection & UI ---
selectSourceLanguage: function (e) { this.setData({ sourceLang: e.currentTarget.dataset.langCode }); },
selectTargetLanguage: function (e) { this.setData({ targetLang: e.currentTarget.dataset.langCode }); },
swapLanguages: function () {
this.setData({ sourceLang: this.data.targetLang, targetLang: this.data.sourceLang, transcript: this.data.outputText, outputText: this.data.transcript });
},
// --- Recorder Initialization ---
initRecorderManager: function () {
this.recorderManager.onStart(() => {
this.setData({ isRecording: true, transcript: '正在聆听...', outputText: '' });
});
this.recorderManager.onStop((res) => {
this.setData({ isRecording: false });
if (res.tempFilePath) {
this.uploadAudioForASR(res.tempFilePath);
} else {
this.setData({ transcript: '录音时间太短或无效' });
}
});
this.recorderManager.onError((res) => {
this.setData({ isRecording: false });
showDetailedError('录音发生错误', res);
});
},
// --- Record Button Handler ---
handleRecordToggle: function() {
if (this.data.isRecording) {
this.stopRecording();
return;
}
wx.getSetting({
success: (res) => {
if (!res.authSetting['scope.record']) {
wx.authorize({ scope: 'scope.record', success: this.startRecording, fail: (err) => showDetailedError('授权失败', err) });
} else {
this.startRecording();
}
},
fail: (err) => showDetailedError('无法获取权限设置', err)
});
},
// --- Start/Stop Recording ---
startRecording: function () {
const options = {
duration: 60000,
sampleRate: 16000,
numberOfChannels: 1,
encodeBitRate: 48000,
format: 'mp3'
};
this.recorderManager.start(options);
},
stopRecording: function () {
this.recorderManager.stop();
},
// --- ASR & Translation Flow ---
uploadAudioForASR: function (filePath) {
this.setData({ transcript: '正在识别...' });
wx.getFileSystemManager().readFile({ filePath, encoding: 'base64', success: (res) => {
wx.request({
url: `${this.data.hfSpaceUrl}/api/asr`,
method: 'POST',
data: { "audio_base64": res.data },
timeout: 120000,
success: (asrRes) => {
console.log("ASR Response:", asrRes); // Log for debugging
if (asrRes.statusCode === 200 && asrRes.data && typeof asrRes.data.text !== 'undefined') {
const transcript = asrRes.data.text;
if (transcript) {
this.setData({ transcript });
this.translate(transcript);
} else {
// Handle successful response with empty transcript
this.setData({ transcript: '未能识别到语音,请重试。' });
}
} else {
// Handle non-200 responses or malformed data
this.setData({ transcript: '识别失败,请重试。' });
showDetailedError('语音识别失败', asrRes.data || '服务器返回异常');
}
},
fail: (err) => {
this.setData({ transcript: '识别请求失败。' });
if (err.errMsg && err.errMsg.includes('timeout')) {
showDetailedError('识别超时', '服务器处理时间过长,请稍后再试或尝试更短的语音。');
} else {
showDetailedError('识别请求失败', err);
}
}
});
}});
},
translate: function (text) {
if (!text) return;
const { sourceLang, targetLang } = this.data;
if (sourceLang === targetLang) {
return this.setData({ outputText: text });
}
this.setData({ outputText: '正在翻译...' });
wx.request({
url: `${this.data.hfSpaceUrl}/api/translate`,
method: 'POST',
data: { "text": text, "source_lang": sourceLang, "target_lang": targetLang },
timeout: 45000,
success: (res) => {
if (res.statusCode === 200 && res.data && res.data.translated_text) {
this.setData({ outputText: res.data.translated_text });
} else {
this.setData({ outputText: '翻译失败' });
showDetailedError('翻译失败', res.data || '服务器返回异常');
}
},
fail: (err) => {
this.setData({ outputText: '翻译请求失败' });
showDetailedError('翻译请求失败', err);
}
});
}
});