Skip to content

Commit b803224

Browse files
author
liugaowei
committed
更新1.9.0
1 parent fde0d05 commit b803224

File tree

9 files changed

+2325
-2514
lines changed

9 files changed

+2325
-2514
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ dist-ssr
2323

2424
release
2525
.vscode/.debug.env
26+
.vscode/settings.json

.vscode/settings.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
{
22
"typescript.tsdk": "node_modules/typescript/lib",
33
"typescript.enablePromptUseWorkspaceTsdk": true,
4-
}
4+
"cSpell.words": [
5+
"customvoiceconnectionid",
6+
"KHTML",
7+
"mstts",
8+
"southeastasia",
9+
"ssml"
10+
]
11+
}

electron/main/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { app, BrowserWindow, shell, ipcMain } from "electron";
22
import { release } from "os";
33
import { join } from "path";
4+
import api from "../utils/api";
45

56
import logger from "../utils/log";
67

@@ -164,4 +165,10 @@ ipcMain.on("openDevTools", async (event, arg) => {
164165
// Get desktop path
165166
ipcMain.on("getDesktopPath", async (event) => {
166167
event.returnValue = app.getPath("desktop");
167-
});
168+
});
169+
170+
// Get desktop path
171+
ipcMain.handle("speech", async (event, ssml) => {
172+
const res = api.speechApi(ssml);
173+
return res;
174+
});

electron/utils/api.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
var axios = require("axios");const fs = require("fs");
2+
3+
const speechApi = (ssml: string) => {
4+
var data = JSON.stringify({
5+
ssml,
6+
ttsAudioFormat: "audio-24khz-160kbitrate-mono-mp3",
7+
offsetInPlainText: 0,
8+
properties: {
9+
SpeakTriggerSource: "AccTuningPagePlayButton",
10+
},
11+
});
12+
13+
var config = {
14+
method: "post",
15+
url: "https://southeastasia.api.speech.microsoft.com/accfreetrial/texttospeech/acc/v3.0-beta1/vcg/speak",
16+
responseType: "arraybuffer",
17+
headers: {
18+
authority: "southeastasia.api.speech.microsoft.com",
19+
accept: "*/*",
20+
"accept-language": "zh-CN,zh;q=0.9",
21+
customvoiceconnectionid: "d8a3a480-dd87-11ed-8758-97b5a7fbfaf6",
22+
origin: "https://speech.microsoft.com",
23+
"sec-ch-ua":
24+
'"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
25+
"sec-ch-ua-mobile": "?0",
26+
"sec-ch-ua-platform": '"Windows"',
27+
"sec-fetch-dest": "empty",
28+
"sec-fetch-mode": "cors",
29+
"sec-fetch-site": "same-site",
30+
"user-agent":
31+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
32+
"content-type": "application/json",
33+
},
34+
35+
data: data,
36+
};
37+
38+
return new Promise((resolve, reject) => {
39+
axios(config)
40+
.then(function (response) {
41+
resolve(response.data);
42+
})
43+
.catch(function (error) {
44+
reject(error);
45+
});
46+
});
47+
};
48+
export default {
49+
speechApi,
50+
};

package-lock.json

Lines changed: 13 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tts-vue",
3-
"version": "1.8.8",
3+
"version": "1.9.0",
44
"main": "dist/electron/main/index.js",
55
"description": "🎤 微软语音合成工具,使用 Electron + Vue + ElementPlus + Vite 构建。",
66
"author": "沫離Loker <[email protected]>",

src/components/footer/Footer.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<script setup lang="ts">
2828
import { useTtsStore } from "@/store/store";
2929
import { storeToRefs } from "pinia";
30-
import { Download } from '@element-plus/icons-vue';
30+
import { Download } from "@element-plus/icons-vue";
3131
3232
const ttsStore = useTtsStore();
3333
const { config, currMp3Url, isLoading, audioPlayer } = storeToRefs(ttsStore);

src/store/play.ts

Lines changed: 10 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,7 @@
11
const axios = require("axios");
22
const { v4: uuidv4 } = require("uuid");
3-
const ws = require("nodejs-websocket");
43
const { ipcRenderer } = require("electron");
5-
6-
async function getAuthToken() {
7-
const res = await axios.get(
8-
"https://azure.microsoft.com/zh-cn/products/cognitive-services/speech-translation/"
9-
);
10-
11-
const reg = /token: \"(.*?)\"/;
12-
13-
if (reg.test(res.data)) {
14-
const token = RegExp.$1;
15-
16-
return "bearer " + token;
17-
}
18-
}
19-
20-
function getXTime() {
21-
return new Date().toISOString();
22-
}
23-
24-
function wssSend(connect: any, msg: string) {
25-
return new Promise((resolve, reject) => {
26-
connect.send(msg, resolve);
27-
});
28-
}
29-
30-
function wssConnect(url: string) {
31-
return new Promise((resolve, reject) => {
32-
const connect = ws.connect(
33-
url,
34-
{
35-
extraHeaders: {
36-
Origin: "https://azure.microsoft.com",
37-
},
38-
},
39-
function () {
40-
resolve(connect);
41-
}
42-
);
43-
});
44-
}
4+
const fs = require("fs");
455

466
async function getTTSData(
477
inps: any,
@@ -51,10 +11,9 @@ async function getTTSData(
5111
rate = 0,
5212
pitch = 0
5313
) {
54-
try {
55-
let SSML = "";
56-
if (inps.activeIndex == "1") {
57-
SSML = `
14+
let SSML = "";
15+
if (inps.activeIndex == "1") {
16+
SSML = `
5817
<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="en-US">
5918
<voice name="${voice}">
6019
<mstts:express-as ${
@@ -67,82 +26,12 @@ async function getTTSData(
6726
</voice>
6827
</speak>
6928
`;
70-
} else {
71-
SSML = inps.inputValue;
72-
}
73-
ipcRenderer.send("log.info", SSML);
74-
console.log(SSML);
75-
76-
console.log("获取Token...");
77-
const Authorization = await getAuthToken();
78-
const XConnectionId = uuidv4().toUpperCase().replaceAll("-", "");
79-
80-
ipcRenderer.send("log.info", "创建webscoket连接...");
81-
// const connect: any = await wssConnect(
82-
// `wss://eastus.tts.speech.microsoft.com/cognitiveservices/websocket/v1?Authorization=${Authorization}&X-ConnectionId=${XConnectionId}`
83-
// );
84-
console.log("创建webscoket连接...");
85-
console.log("Authorization:", Authorization);
86-
console.log("XConnectionId:", XConnectionId);
87-
const connect: any = await wssConnect(
88-
`wss://eastus.api.speech.microsoft.com/cognitiveservices/websocket/v1?TrafficType=AzureDemo&Authorization=${Authorization}&X-ConnectionId=${XConnectionId}`
89-
);
90-
91-
ipcRenderer.send("log.info", "第1次上报...");
92-
console.log("第1次上报...");
93-
const message_1 = `Path: speech.config\r\nX-RequestId: ${XConnectionId}\r\nX-Timestamp: ${getXTime()}\r\nContent-Type: application/json\r\n\r\n{"context":{"system":{"name":"SpeechSDK","version":"1.19.0","build":"JavaScript","lang":"JavaScript","os":{"platform":"Browser/Linux x86_64","name":"Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0","version":"5.0 (X11)"}}}}`;
94-
await wssSend(connect, message_1);
95-
96-
ipcRenderer.send("log.info", "第2次上报...");
97-
console.log("第2次上报...");
98-
const message_2 = `Path: synthesis.context\r\nX-RequestId: ${XConnectionId}\r\nX-Timestamp: ${getXTime()}\r\nContent-Type: application/json\r\n\r\n{"synthesis":{"audio":{"metadataOptions":{"sentenceBoundaryEnabled":false,"wordBoundaryEnabled":false},"outputFormat":"audio-24khz-160kbitrate-mono-mp3"}}}`;
99-
await wssSend(connect, message_2);
100-
101-
ipcRenderer.send("log.info", "第3次上报...");
102-
console.log("第3次上报...");
103-
const message_3 = `Path: ssml\r\nX-RequestId: ${XConnectionId}\r\nX-Timestamp: ${getXTime()}\r\nContent-Type: application/ssml+xml\r\n\r\n${SSML}`;
104-
await wssSend(connect, message_3);
105-
106-
return new Promise((resolve, reject) => {
107-
let final_data = Buffer.alloc(0);
108-
connect.on("text", (data: string | string[]) => {
109-
if (data.indexOf("Path:turn.end") >= 0) {
110-
ipcRenderer.send("log.info", "已完成");
111-
console.log("已完成");
112-
connect.close();
113-
resolve(final_data);
114-
}
115-
});
116-
connect.on(
117-
"binary",
118-
function (response: {
119-
on: (arg0: string, arg1: { (): void; (): void }) => void;
120-
read: () => any;
121-
}) {
122-
console.log("正在接收数据...");
123-
let data = Buffer.alloc(0);
124-
response.on("readable", function () {
125-
const newData = response.read();
126-
if (newData)
127-
data = Buffer.concat(
128-
[data, newData],
129-
data.length + newData.length
130-
);
131-
});
132-
response.on("end", function () {
133-
const index = data.toString().indexOf("Path:audio") + 10;
134-
const cmbData = data.slice(index + 2);
135-
final_data = Buffer.concat([final_data, cmbData]);
136-
});
137-
}
138-
);
139-
connect.on("close", function (code: any, reason: any) {});
140-
});
141-
} catch (error) {
142-
console.log(error);
143-
return new Promise((resolve, reject) => {
144-
reject(error);
145-
});
29+
} else {
30+
SSML = inps.inputValue;
14631
}
32+
ipcRenderer.send("log.info", SSML);
33+
console.log(SSML);
34+
const result = await ipcRenderer.invoke("speech", SSML);
35+
return result;
14736
}
14837
export default getTTSData;

0 commit comments

Comments
 (0)