Skip to content

Commit

Permalink
更新1.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
liugaowei committed Apr 18, 2023
1 parent fde0d05 commit b803224
Show file tree
Hide file tree
Showing 9 changed files with 2,325 additions and 2,514 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ dist-ssr

release
.vscode/.debug.env
.vscode/settings.json
9 changes: 8 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
}
"cSpell.words": [
"customvoiceconnectionid",
"KHTML",
"mstts",
"southeastasia",
"ssml"
]
}
9 changes: 8 additions & 1 deletion electron/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { app, BrowserWindow, shell, ipcMain } from "electron";
import { release } from "os";
import { join } from "path";
import api from "../utils/api";

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

Expand Down Expand Up @@ -164,4 +165,10 @@ ipcMain.on("openDevTools", async (event, arg) => {
// Get desktop path
ipcMain.on("getDesktopPath", async (event) => {
event.returnValue = app.getPath("desktop");
});
});

// Get desktop path
ipcMain.handle("speech", async (event, ssml) => {
const res = api.speechApi(ssml);
return res;
});
50 changes: 50 additions & 0 deletions electron/utils/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
var axios = require("axios");const fs = require("fs");

const speechApi = (ssml: string) => {
var data = JSON.stringify({
ssml,
ttsAudioFormat: "audio-24khz-160kbitrate-mono-mp3",
offsetInPlainText: 0,
properties: {
SpeakTriggerSource: "AccTuningPagePlayButton",
},
});

var config = {
method: "post",
url: "https://southeastasia.api.speech.microsoft.com/accfreetrial/texttospeech/acc/v3.0-beta1/vcg/speak",
responseType: "arraybuffer",
headers: {
authority: "southeastasia.api.speech.microsoft.com",
accept: "*/*",
"accept-language": "zh-CN,zh;q=0.9",
customvoiceconnectionid: "d8a3a480-dd87-11ed-8758-97b5a7fbfaf6",
origin: "https://speech.microsoft.com",
"sec-ch-ua":
'"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-site",
"user-agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
"content-type": "application/json",
},

data: data,
};

return new Promise((resolve, reject) => {
axios(config)
.then(function (response) {
resolve(response.data);
})
.catch(function (error) {
reject(error);
});
});
};
export default {
speechApi,
};
15 changes: 13 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tts-vue",
"version": "1.8.8",
"version": "1.9.0",
"main": "dist/electron/main/index.js",
"description": "🎤 微软语音合成工具,使用 Electron + Vue + ElementPlus + Vite 构建。",
"author": "沫離Loker <[email protected]>",
Expand Down
2 changes: 1 addition & 1 deletion src/components/footer/Footer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<script setup lang="ts">
import { useTtsStore } from "@/store/store";
import { storeToRefs } from "pinia";
import { Download } from '@element-plus/icons-vue';
import { Download } from "@element-plus/icons-vue";
const ttsStore = useTtsStore();
const { config, currMp3Url, isLoading, audioPlayer } = storeToRefs(ttsStore);
Expand Down
131 changes: 10 additions & 121 deletions src/store/play.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,7 @@
const axios = require("axios");
const { v4: uuidv4 } = require("uuid");
const ws = require("nodejs-websocket");
const { ipcRenderer } = require("electron");

async function getAuthToken() {
const res = await axios.get(
"https://azure.microsoft.com/zh-cn/products/cognitive-services/speech-translation/"
);

const reg = /token: \"(.*?)\"/;

if (reg.test(res.data)) {
const token = RegExp.$1;

return "bearer " + token;
}
}

function getXTime() {
return new Date().toISOString();
}

function wssSend(connect: any, msg: string) {
return new Promise((resolve, reject) => {
connect.send(msg, resolve);
});
}

function wssConnect(url: string) {
return new Promise((resolve, reject) => {
const connect = ws.connect(
url,
{
extraHeaders: {
Origin: "https://azure.microsoft.com",
},
},
function () {
resolve(connect);
}
);
});
}
const fs = require("fs");

async function getTTSData(
inps: any,
Expand All @@ -51,10 +11,9 @@ async function getTTSData(
rate = 0,
pitch = 0
) {
try {
let SSML = "";
if (inps.activeIndex == "1") {
SSML = `
let SSML = "";
if (inps.activeIndex == "1") {
SSML = `
<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">
<voice name="${voice}">
<mstts:express-as ${
Expand All @@ -67,82 +26,12 @@ async function getTTSData(
</voice>
</speak>
`;
} else {
SSML = inps.inputValue;
}
ipcRenderer.send("log.info", SSML);
console.log(SSML);

console.log("获取Token...");
const Authorization = await getAuthToken();
const XConnectionId = uuidv4().toUpperCase().replaceAll("-", "");

ipcRenderer.send("log.info", "创建webscoket连接...");
// const connect: any = await wssConnect(
// `wss://eastus.tts.speech.microsoft.com/cognitiveservices/websocket/v1?Authorization=${Authorization}&X-ConnectionId=${XConnectionId}`
// );
console.log("创建webscoket连接...");
console.log("Authorization:", Authorization);
console.log("XConnectionId:", XConnectionId);
const connect: any = await wssConnect(
`wss://eastus.api.speech.microsoft.com/cognitiveservices/websocket/v1?TrafficType=AzureDemo&Authorization=${Authorization}&X-ConnectionId=${XConnectionId}`
);

ipcRenderer.send("log.info", "第1次上报...");
console.log("第1次上报...");
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)"}}}}`;
await wssSend(connect, message_1);

ipcRenderer.send("log.info", "第2次上报...");
console.log("第2次上报...");
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"}}}`;
await wssSend(connect, message_2);

ipcRenderer.send("log.info", "第3次上报...");
console.log("第3次上报...");
const message_3 = `Path: ssml\r\nX-RequestId: ${XConnectionId}\r\nX-Timestamp: ${getXTime()}\r\nContent-Type: application/ssml+xml\r\n\r\n${SSML}`;
await wssSend(connect, message_3);

return new Promise((resolve, reject) => {
let final_data = Buffer.alloc(0);
connect.on("text", (data: string | string[]) => {
if (data.indexOf("Path:turn.end") >= 0) {
ipcRenderer.send("log.info", "已完成");
console.log("已完成");
connect.close();
resolve(final_data);
}
});
connect.on(
"binary",
function (response: {
on: (arg0: string, arg1: { (): void; (): void }) => void;
read: () => any;
}) {
console.log("正在接收数据...");
let data = Buffer.alloc(0);
response.on("readable", function () {
const newData = response.read();
if (newData)
data = Buffer.concat(
[data, newData],
data.length + newData.length
);
});
response.on("end", function () {
const index = data.toString().indexOf("Path:audio") + 10;
const cmbData = data.slice(index + 2);
final_data = Buffer.concat([final_data, cmbData]);
});
}
);
connect.on("close", function (code: any, reason: any) {});
});
} catch (error) {
console.log(error);
return new Promise((resolve, reject) => {
reject(error);
});
} else {
SSML = inps.inputValue;
}
ipcRenderer.send("log.info", SSML);
console.log(SSML);
const result = await ipcRenderer.invoke("speech", SSML);
return result;
}
export default getTTSData;
Loading

0 comments on commit b803224

Please sign in to comment.