AKIRA
Finalize all local changes
b3b0b53
raw
history blame
9.12 kB
const plugin = requirePlugin('WechatSI');
const innerAudioContext = wx.createInnerAudioContext();
Page({
data: {
languages: {
'zh': { name: '中文', flag: 'cn', code: 'zh_CN' },
'en': { name: 'English', flag: 'us', code: 'en_US' },
'ja': { name: '日本語', flag: 'jp', code: 'ja_JP' },
'ko': { name: '한국어', flag: 'kr', code: 'ko_KR' }
},
langCodes: ['zh', 'en', 'ja', 'ko'],
sourceLang: 'zh',
targetLang: 'en',
transcript: '',
outputText: '',
isRecording: false,
sourceLanguages: [],
targetLanguages: [],
hfSpaceUrl: 'https://dazaozi-wechat-translator-app.hf.space'
},
onLoad: function () {
this.initializeLanguages();
this.recorderManager = wx.getRecorderManager();
this.initRecorderManager();
plugin.getRecordRecognitionManager = wx.getRecordRecognitionManager;
},
initializeLanguages: function () {
const { langCodes, languages, sourceLang, targetLang } = this.data;
const sourceLanguages = langCodes.map(code => ({
langCode: code,
name: languages[code].name,
flag: languages[code].flag,
selected: code === sourceLang
}));
const targetLanguages = langCodes.map(code => ({
langCode: code,
name: languages[code].name,
flag: languages[code].flag,
selected: code === targetLang
}));
this.setData({ sourceLanguages, targetLanguages });
},
selectSourceLanguage: function (e) {
const newSourceLang = e.currentTarget.dataset.langCode;
this.setData({ sourceLang: newSourceLang }, () => {
this.initializeLanguages();
if (this.data.transcript.trim() && this.data.transcript !== '正在聆听...' && this.data.transcript !== '未能识别到语音') {
this.translate(this.data.transcript);
}
});
},
selectTargetLanguage: function (e) {
const newTargetLang = e.currentTarget.dataset.langCode;
this.setData({ targetLang: newTargetLang }, () => {
this.initializeLanguages();
if (this.data.transcript.trim() && this.data.transcript !== '正在聆听...' && this.data.transcript !== '未能识别到语音') {
this.translate(this.data.transcript);
}
});
},
swapLanguages: function () {
let { sourceLang, targetLang, transcript, outputText } = this.data;
const tempLang = sourceLang;
sourceLang = targetLang;
targetLang = tempLang;
const tempText = transcript;
transcript = outputText;
outputText = tempText;
this.setData({ sourceLang, targetLang, transcript, outputText }, () => {
this.initializeLanguages();
if (this.data.transcript.trim() && this.data.transcript !== '正在聆听...' && this.data.transcript !== '未能识别到语音') {
this.translate(this.data.transcript);
}
});
},
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(() => {
this.setData({ isRecording: false, transcript: '语音识别出错' });
});
},
startRecording: function () {
this.recorderManager.start({ duration: 60000, sampleRate: 16000, numberOfChannels: 1, encodeBitRate: 96000, format: 'mp3' });
},
stopRecording: function () {
this.recorderManager.stop();
},
uploadAudioForASR: function (filePath) {
this.setData({ transcript: '正在识别...' });
const fileSystemManager = wx.getFileSystemManager();
fileSystemManager.readFile({
filePath: filePath,
encoding: 'base64',
success: (res) => {
const base64Data = res.data;
const dataUri = 'data:audio/mp3;base64,' + base64Data;
wx.request({
url: `${this.data.hfSpaceUrl}/api/asr`,
method: 'POST',
header: { 'Content-Type': 'application/json' },
data: { "audio_data_uri": dataUri },
timeout: 60000,
success: (res) => {
if (res.statusCode === 200 && res.data && res.data.transcript) {
const transcript = res.data.transcript;
this.setData({ transcript: transcript });
this.translate(transcript);
} else {
this.setData({ transcript: '语音识别失败' });
}
},
fail: () => {
this.setData({ transcript: '语音识别请求失败' });
}
});
},
fail: () => {
this.setData({ transcript: '读取音频文件失败' });
}
});
},
translate: function (text) {
if (!text) return;
const { sourceLang, targetLang, languages } = this.data;
const isChineseEnglish = (sourceLang === 'zh' && targetLang === 'en') || (sourceLang === 'en' && targetLang === 'zh');
if (isChineseEnglish) {
// --- Scenario 1: Direct CN-EN translation using WeChat Plugin ---
this.setData({ outputText: '正在翻译 (微信)...' });
plugin.translate({
lfrom: languages[sourceLang].code,
lto: languages[targetLang].code,
content: text,
success: (res) => {
if (res.retcode == 0) {
this.setData({ outputText: res.result });
} else {
this.setData({ outputText: '微信翻译失败' });
}
},
fail: () => {
this.setData({ outputText: '微信翻译接口调用失败' });
}
});
} else {
// --- Scenario 2: Hybrid translation for other languages ---
this.hybridTranslate(text, sourceLang, targetLang);
}
},
hybridTranslate: function(text, sourceLang, targetLang) {
// If source is not English, first translate to English using WeChat Plugin
if (sourceLang !== 'en') {
this.setData({ outputText: '翻译中 (1/2)...' });
plugin.translate({
lfrom: this.data.languages[sourceLang].code,
lto: 'en_US',
content: text,
success: (res) => {
if (res.retcode == 0) {
const englishText = res.result;
// If the final target is English, we are done.
if (targetLang === 'en') {
this.setData({ outputText: englishText });
} else {
// Otherwise, send the high-quality English text to HF for the second leg
this.translateViaHF(englishText, 'en', targetLang);
}
} else {
this.setData({ outputText: '混合翻译失败 (1/2)' });
}
},
fail: () => {
this.setData({ outputText: '混合翻译接口调用失败 (1/2)' });
}
});
} else {
// If source is already English, directly call HF for translation
this.translateViaHF(text, sourceLang, targetLang);
}
},
translateViaHF: function(text, sourceLang, targetLang) {
this.setData({ outputText: '翻译中 (2/2)..' });
wx.request({
url: `${this.data.hfSpaceUrl}/api/translate`,
method: 'POST',
header: { 'Content-Type': 'application/json' },
data: {
"text": text,
"source_lang": sourceLang,
"target_lang": targetLang
},
timeout: 30000,
success: (res) => {
if (res.statusCode === 200 && res.data && res.data.translated_text) {
this.setData({ outputText: res.data.translated_text });
} else {
this.setData({ outputText: '混合翻译失败 (2/2)' });
}
},
fail: () => {
this.setData({ outputText: '混合翻译出错 (2/2)' });
}
});
}
});