File size: 6,337 Bytes
b3b0b53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
const recorderManager = wx.getRecorderManager();

Page({
    data: {
        languages: {
            'zh': { name: '中文', flag: 'cn' },
            'en': { name: 'English', flag: 'us' },
            'ja': { name: '日本語', flag: 'jp' },
            'ko': { name: '한국어', flag: '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.initRecorderManager();
    },

    // --- Language Selection Logic ---
    initializeLanguages: function () {
        const { langCodes, languages, sourceLang, targetLang } = this.data;
        this.setData({
            sourceLanguages: langCodes.map(c => ({ ...languages[c], langCode: c, selected: c === sourceLang })),
            targetLanguages: langCodes.map(c => ({ ...languages[c], langCode: c, selected: c === targetLang }))
        });
    },
    selectSourceLanguage: function(e) { this.setData({ sourceLang: e.currentTarget.dataset.langCode }, this.initializeLanguages); },
    selectTargetLanguage: function(e) { this.setData({ targetLang: e.currentTarget.dataset.langCode }, this.initializeLanguages); },
    swapLanguages: function() {
        this.setData({
            sourceLang: this.data.targetLang,
            targetLang: this.data.sourceLang,
            transcript: this.data.outputText,
            outputText: this.data.transcript
        }, this.initializeLanguages);
    },

    // --- Simplified, Unified, and Correct Recording Logic ---
    initRecorderManager: function() {
        recorderManager.onStart = () => {
            this.setData({ isRecording: true, transcript: '正在聆听...', outputText: '' });
        };

        recorderManager.onStop = (res) => {
            this.setData({ isRecording: false });
            if (res.tempFilePath) {
                this.uploadAudioForASR(res.tempFilePath);
            } else {
                this.setData({ transcript: '录音文件获取失败' });
            }
        };

        recorderManager.onError = (res) => {
            this.setData({ isRecording: false, transcript: '识别失败', outputText: res.msg });
        };
    },

    startRecording: function () {
        recorderManager.start({ duration: 60000, sampleRate: 16000, numberOfChannels: 1, encodeBitRate: 96000, format: 'mp3' });
    },

    stopRecording: function () {
        recorderManager.stop();
    },

    // --- Unified Backend Flow ---
    uploadAudioForASR: function (filePath) {
        this.setData({ transcript: '正在识别 (1/3)...' });
        const fileSystemManager = wx.getFileSystemManager();
        fileSystemManager.readFile({ filePath, encoding: 'base64', success: (res) => {
            wx.request({
                url: `${this.data.hfSpaceUrl}/api/asr`,
                method: 'POST',
                header: { 'Content-Type': 'application/json' },
                data: { "audio_data_uri": `data:audio/mp3;base64,${res.data}` },
                timeout: 60000,
                success: (asrRes) => {
                    if (asrRes.statusCode === 200 && asrRes.data.transcript) {
                        const transcript = asrRes.data.transcript;
                        this.setData({ transcript });
                        // If source and target are the same, no need to translate
                        if (this.data.sourceLang === this.data.targetLang) {
                            this.setData({ outputText: transcript });
                            return;
                        }
                        this.fullBackendBridge(transcript, this.data.sourceLang, this.data.targetLang);
                    } else { this.setData({ transcript: 'HF识别失败' }); }
                },
                fail: () => { this.setData({ transcript: 'HF识别请求失败' }); }
            });
        }});
    },

    fullBackendBridge: function(text, sourceLang, targetLang) {
        // If source is not English, bridge through English
        if (sourceLang !== 'en') {
            this.setData({ outputText: '翻译中 (2/3)..' });
            this.translateViaHF(text, sourceLang, 'en', (englishResult) => {
                if (englishResult) {
                    // If the final target was English, we are done
                    if (targetLang === 'en') {
                        this.setData({ outputText: englishResult });
                    } else {
                        this.setData({ outputText: '翻译中 (3/3)..' });
                        this.translateViaHF(englishResult, 'en', targetLang, (finalResult) => {
                            if (finalResult) {
                                this.setData({ outputText: finalResult });
                            }
                        });
                    }
                }
            });
        } else {
            // If source is English, directly translate to target
            this.setData({ outputText: '翻译中 (2/2)..' });
            this.translateViaHF(text, sourceLang, targetLang, (finalResult) => {
                if (finalResult) {
                    this.setData({ outputText: finalResult });
                }
            });
        }
    },

    translateViaHF: function(text, sourceLang, targetLang, callback) {
        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.translated_text) {
                    callback(res.data.translated_text);
                } else {
                    this.setData({ outputText: `HF翻译失败 (${sourceLang}->${targetLang})` });
                    callback(null);
                }
            },
            fail: () => {
                this.setData({ outputText: `HF翻译请求失败 (${sourceLang}->${targetLang})` });
                callback(null);
            }
        });
    }
});