-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript.js
184 lines (153 loc) · 6.18 KB
/
script.js
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
const apiKeyInput = document.getElementById('api-key-input');
const apiUrlSelect = document.getElementById('api-url-select');
const saveApiKeyBtn = document.getElementById('save-api-key-btn');
const fileUpload = document.getElementById('file-upload');
const translateBtn = document.getElementById('translate-btn');
const transcriptionDiv = document.getElementById('transcription');
const translationDiv = document.getElementById('translation');
const translationDivGPT = document.getElementById('translationGPT');
// 尝试从 local storage 中加载 API key
const apiKey = localStorage.getItem('apiKey');
if (apiKey) {
apiKeyInput.value = apiKey;
}
const apiUrl = localStorage.getItem('apiUrl');
if (apiUrl) {
apiUrlSelect.value = apiUrl;
}
// 监听保存 API key 的按钮点击事件
saveApiKeyBtn.addEventListener('click', () => {
// 从输入框中获取 API key
const apiKey = apiKeyInput.value;
const apiUrl = apiUrlSelect.value;
// 保存 API key 到 local storage
localStorage.setItem('apiKey', apiKey);
localStorage.setItem('apiUrl', apiUrl);
// 提示用户保存成功
alert('配置保存成功!');
});
// 发送音频文件和 API key 到 https://api.openai.com/v1/audio/translations 进行翻译
const transcribeAudio = async (apiKey,apiUrl,file) => {
const formData = new FormData();
formData.append('file', file);
formData.append('model', 'whisper-1');
const response = await fetch(`${apiUrl}/v1/audio/transcriptions`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`
} ,
body: formData
});
if (response.ok) { // 检查 status code 是否为 200
const responseData = await response.json();
return responseData.text;
} else {
const errorResponse = await response.text();
alert(`Error: ${response.status} \n\n${errorResponse}`);
}
};
// 使用 Google translate API 将文本翻译成中文
const translateText = async (text) => {
// 对 text 进行 url 编码
const encodedText = encodeURIComponent(text);
// 调用 Google translate 的 get api 将原始文本翻译成 Chinese
const translateResponse = await fetch(`https://translate.googleapis.com/translate_a/single?dt=t&dt=bd&dt=qc&dt=rm&client=gtx&sl=auto&tl=zh-CN&hl=en-US&dj=1&q=${encodedText}&tk=574558.574558`);
if (translateResponse.ok){
const translateResponseData = await translateResponse.json();
// 提取 sentences[*].trans 并合并为一行
const translation = translateResponseData.sentences.map(sentence => sentence.trans).join('');
return translation;
} else {
const errorResponse = await translateResponse.text();
alert(`Error: ${response.status} \n\n${errorResponse}`);
}
};
// 使用 GPT 3.5 将文本翻译成中文
const translateTextGPT = async (text) => {
// 构造请求消息,要求模型翻译 text
const requestBody = {
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "I want you to act as an Chinese translator, spelling corrector and improver. I will speak to you in any language and you will detect the language, translate it and answer in the corrected and improved version of my text, in Chinese. I want you to only reply the correction, the improvements and nothing else, do not write explanations"
},
{
"role": "user",
"content": `"${text}"`
}
]
};
const response = await fetch(`${apiUrl}/v1/chat/completions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`
},
body: JSON.stringify(requestBody)
});
if (response.ok) {
const responseData = await response.json();
return responseData.choices[0].message.content.trim();
} else {
const errorResponse = await response.text();
alert(`Error: ${response.status} \n\n${errorResponse}`);
}
};
async function convertOggToMp3(file) {
// 加载FFmpeg
if (!ffmpeg.isLoaded()) {
await ffmpeg.load();
}
const { name } = file;
const inputPath = `/${name}`;
const outputPath = `/${name.replace('.ogg', '')}.mp3`;
// 将OGG文件从File对象转换为Uint8Array格式
const arrayBuffer = await file.arrayBuffer();
const uint8Array = new Uint8Array(arrayBuffer);
// 将Uint8Array格式的文件写入FFmpeg内存中
await ffmpeg.FS('writeFile', inputPath, uint8Array);
// 调用FFmpeg进行转换
await ffmpeg.run('-i', inputPath, '-acodec', 'libmp3lame', outputPath);
// 将转换后的MP3文件从FFmpeg内存中读取到Uint8Array格式中
const mp3Data = await ffmpeg.FS('readFile', outputPath);
const mp3File = new File([mp3Data.buffer], name.replace('.ogg', '.mp3'), { type: 'audio/mp3' });
return mp3File;
}
translateBtn.addEventListener('click', async () => {
// 从 local storage 中加载 API key
const apiKey = localStorage.getItem('apiKey');
if (!apiKey) {
alert('请先输入并保存 API key!');
return;
}
// 从文件上传控件中获取文件,File uploads are currently limited to 25 MB and the following input file types are supported: mp3, mp4, mpeg, mpga, m4a, wav, and webm.
const file = fileUpload.files[0];
if (!file) {
alert('请选择一个音视频文件!');
return;
}
if (file.size > 25 * 1024 * 1024) {
alert('文件大小不能超过 25MB!');
return;
}
let transcription;
if (file.type === 'audio/ogg') {
// 更改 Tab 的标题为"ogg 转换较慢,请耐心等待"
document.title = '音频翻译-ogg 转换较慢,请耐心等待';
// 将OGG文件转换为MP3格式
const mp3File = await convertOggToMp3(file);
// 调用openai和google translate完成音频翻译
transcription = await transcribeAudio(apiKey,apiUrl, mp3File);
} else {
// 直接调用openai和google translate完成音频翻译
transcription = await transcribeAudio(apiKey,apiUrl, file);
}
// let transcription = "这是一段测试文本,用于测试翻译功能。"
const translation = await translateText(transcription);
const translationGPT = await translateTextGPT(transcription);
// 在页面上显示转写结果和翻译结果
transcriptionDiv.innerText = transcription;
translationDiv.innerText = translation;
translationDivGPT.innerText = translationGPT;
});