File size: 5,584 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
// FINAL VERSION: v28 - Unified Native Recording and HF Backend
const nativeRecorderManager = wx.getRecorderManager();

// 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 () {
        // Directly create language arrays for the UI from the static config
        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 }))
        });
        this.initNativeRecorderManager();
    },

    // --- 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 });
    },

    // --- Unified Native Recorder Initialization ---
    initNativeRecorderManager: function () {
        nativeRecorderManager.onStart = () => {
            this.setData({ transcript: '正在聆听...', outputText: '' });
        };
        nativeRecorderManager.onStop = (res) => {
            this.setData({ isRecording: false });
            if (res.tempFilePath) {
                // ALL recordings go to the HF backend for ASR
                this.uploadAudioForASR(res.tempFilePath);
            } else {
                showDetailedError('录音失败', '未能获取到有效的录音文件路径。');
            }
        };
        nativeRecorderManager.onError = (res) => {
            this.setData({ isRecording: false });
            showDetailedError('录音发生错误', res);
        };
    },

    // --- Main Record Button Handler ---
    handleRecordToggle: function() {
        if (this.data.isRecording) {
            this.stopRecording();
            return;
        }
        // Check permissions before starting
        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)
        });
    },

    // --- Unified Start/Stop Recording ---
    startRecording: function () {
        this.setData({ isRecording: true });
        nativeRecorderManager.start({ format: 'mp3', sampleRate: 16000, numberOfChannels: 1 });
    },

    stopRecording: function () {
        this.setData({ isRecording: false });
        nativeRecorderManager.stop();
    },

    // --- Unified Backend ASR & Translation Flow ---
    uploadAudioForASR: function (filePath) {
        this.setData({ transcript: '正在识别 (1/2)...' });
        wx.getFileSystemManager().readFile({ filePath, encoding: 'base64', success: (res) => {
            wx.request({
                url: `${this.data.hfSpaceUrl}/api/asr`,
                method: 'POST',
                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 });
                        // After ASR, ALL translations go to the HF backend
                        this.translateViaHfBridge(transcript, this.data.sourceLang, this.data.targetLang);
                    } else {
                        showDetailedError('语音识别失败', asrRes.data);
                    }
                },
                fail: (err) => showDetailedError('识别请求失败', err)
            });
        }});
    },

    translateViaHfBridge: function(text, source, target) {
        if (source === target) {
            return this.setData({ outputText: text });
        }
        this.setData({ outputText: '正在翻译 (2/2)...' });
        wx.request({
            url: `${this.data.hfSpaceUrl}/api/translate`,
            method: 'POST',
            data: { "text": text, "source_lang": source, "target_lang": target },
            timeout: 45000,
            success: (res) => {
                if (res.statusCode === 200 && res.data.translated_text) {
                    this.setData({ outputText: res.data.translated_text });
                } else {
                    showDetailedError('翻译失败', res.data);
                }
            },
            fail: (err) => showDetailedError('翻译请求失败', err)
        });
    }
});