Spaces:
Sleeping
Sleeping
File size: 6,428 Bytes
b3b0b53 ad71343 52747f1 ad71343 52747f1 ad71343 52747f1 b3b0b53 ad71343 52747f1 ad71343 52747f1 b3b0b53 52747f1 ad71343 52747f1 ad71343 52747f1 ad71343 52747f1 b3b0b53 ad71343 52747f1 ad71343 52747f1 ad71343 52747f1 ad71343 52747f1 b3b0b53 ad71343 b3b0b53 ad71343 52747f1 ad71343 52747f1 b3b0b53 52747f1 ad71343 b3b0b53 ad71343 b3b0b53 ad71343 b3b0b53 52747f1 ad71343 b3b0b53 ad71343 52747f1 ad71343 52747f1 ad71343 52747f1 ad71343 52747f1 b3b0b53 ad71343 b3b0b53 52747f1 b3b0b53 52747f1 0564665 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
// 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);
}
});
}
}); |