Files
aggregate_translate_website/voice.html
2025-07-02 18:32:06 +08:00

1171 lines
42 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="baidu-site-verification" content="codeva-bhaFvYlfgd" />
<meta
name="keywords"
content="deepl、deepl翻译、百度翻译、谷歌翻译、腾讯翻译君"
/>
<meta
name="description"
content="聚合翻译提供即时免费的中文、英语、日语、韩语、法语、德语、俄语、西班牙语、葡萄牙语、越南语、印尼语、意大利语、荷兰语、泰语全文翻译等服务。"
/>
<meta name="baidu-site-verification" content="codeva-mXz3BqI9VN" />
<link rel="stylesheet" href="static/css/public.css" />
<link rel="stylesheet" href="static/css/layui.css" />
<script src="static/js/jquery-1.11.0.min.js"></script>
<script src="static/js/axios.min.js"></script>
<script src="static/js/countUp.min.js"></script>
<script src="static/js/vue.js"></script>
<script src="static/js/lodash.min.js"></script>
<script src="static/js/layui.all.js"></script>
<script src="static/js/common.js"></script>
<title>聚合翻译</title>
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?c4e0dd6add63dd71fa52870120ca22cf";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>
<body>
<div class="public-header normal" id="main">
<div class="container clearfix">
<div class="left">
<img class="logo default" src="static/picture/logo.png" alt="" /><img
class="logo1 default"
src="static/picture/logo1.png"
alt=""
/><img class="logo light" src="static/picture/logow.png" alt="" /><img
class="logo1 light"
src="static/picture/logo1w.png"
alt=""
/>
<div class="nav">
<a class="" href="index.html"><span>首页</span></a
><a class="" href="onlineTranslation.html"><span>文本翻译</span></a
><a class="active" href=""><span>语音翻译</span></a
><a class="" href="api.html"><span>API文档</span></a
><a class="" href="commonProblems.html"><span>常见问题</span></a>
</div>
</div>
<div v-if="userInfo!=undefined&&userInfo.userId>0" class="right">
<a href="userinfo.html" class="console">控制台</a>
<div class="user-info">
<div class="phone">{{userInfo.name}}</div>
<i></i>
<div class="log-out" @click="logOut">退出</div>
</div>
</div>
<div v-else class="right">
<a class="unlogin" href="login.html">登录</a>
</div>
</div>
<div class="bg"></div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#main",
data() {
return {
userInfo: {},
token: "",
};
},
created() {},
mounted() {
let token = localStorage.getItem("token");
if (token) {
this.token = token;
this.getUserInfo(token);
} else {
// location.href = "login.html";
}
},
methods: {
logOut() {
axios
.post("/logout", {
headers: {
Authorization: `Bearer ${this.token}`,
},
})
.then((response) => {
localStorage.removeItem("token");
location.reload();
});
},
getUserInfo(token) {
let that = this;
axios
.get("/getinfo", {
headers: {
Authorization: `Bearer ${this.token}`,
},
})
.then((response) => {
if (response.data.code === 200) {
this.userInfo = response.data.data;
console.log("userinfo", this.userInfo);
} else {
localStorage.removeItem("token");
location.href = "login.html";
}
});
},
},
});
</script>
<div class="page-translation" id="app">
<div class="w1200">
<div class="translation-engine">
<div
v-for="item in engineType"
:key="item.text"
class="voiceitem"
:class="{ on: engine.text == item.text }"
@click="onSelectEngine(item)"
>
<img
:src="engine.text == item.text ? item.icon :item.icon1 "
alt=""
/><span class="engine-name">{{ item.text }}</span>
</div>
</div>
<div
class="translation-row"
style="
padding-top: 40px;
padding-left: 62px;
border: 1px solid #fff;
padding-bottom: 40px;
display: flex;
"
>
<div class="left-side">
<div class="title">
{{ engine.text === '语音识别' ? '语音转文字,我们帮您一键识别!' :
engine.text === '语音合成' ? '录入文字,我们帮你翻译并朗读!' :
'说出中文,我们帮你语音翻译!' }}
</div>
<div class="subtitle">
{{ engine.text === '语音识别' ?
'识别结果单次识别最长支持1分钟' : engine.text === '语音合成' ?
'文字录入单次合成最长支持100字符' :
'识别结果单次识别最长支持1分钟' }}
</div>
<textarea
class="transcription-box"
:placeholder="engine.text === '语音识别' ? '这里实时显示语音识别结果' :
engine.text === '语音合成' ? '请输入要合成语音的文字内容' :
'这里实时显示翻译结果'"
disabled
></textarea>
<div class="action-button">
<div class="sound-wave-container" v-show="soundShow">
<!-- First sound wave -->
<div class="sound-wave">
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
</div>
<!-- Second sound wave -->
<div class="sound-wave">
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
</div>
<!-- Third sound wave -->
<div class="sound-wave">
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
</div>
<!-- Fourth sound wave -->
<div class="sound-wave">
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
</div>
<!-- Fifth sound wave -->
<div class="sound-wave">
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
<div class="sound-bar"></div>
</div>
</div>
</div>
<div class="synthesis-options">
<div class="synthesis-option" @click="start" v-show="!soundShow">
<img
src="static/picture/icon1.png"
alt="合成图标"
class="option-icon"
/><span
>{{ engine.text === '语音识别' ? '开始识别' : engine.text ===
'语音合成' ? '开始合成' : '开始翻译' }}</span
>
</div>
<div
class="synthesis-option"
@click="stop"
v-show="soundShow"
style="background-image: url('static/image/stopbj.png')"
>
<img
src="static/picture/icon2.png"
alt="合成图标"
class="option-icon"
/><span
>{{ engine.text === '语音识别' ? '结束识别' : engine.text ===
'语音合成' ? '结束合成' : '结束翻译' }}</span
>
</div>
</div>
<div class="balance-warning" v-show="errmsg!=''">
<div class="balance-warnings">
<img
src="static/picture/warning-icon.png"
alt="警告"
class="warning-icon"
/><span v-show="errmsg == '余额'">
余额不足,请前往控制台充值</span
><span v-show="errmsg == '登录'"> 请先登录</span>
</div>
</div>
<div style="height: 30px"></div>
</div>
<div class="right-side">
<div class="voice-input-title">
{{ engine.text === '语音识别' ? '语音录入' : engine.text ===
'语音合成' ? '语音配置' : '语音配置' }}
</div>
<div
class="language-row"
v-show="engine.text === '语音识别'"
style="margin-top: 48px"
>
<div class="original-language-text">原始语种:</div>
<div class="language-selector-box">
<div
class="translation-language"
style="padding-left: 0; border-bottom: none; width: 100%"
>
<div
class="source language-selector"
@click="onShowLanguage('sourceLanguage')"
style="
width: 100%;
margin-right: 0;
justify-content: space-between;
"
>
{{ sourceLanguage.name }}
<div
class="icon select-icons"
:class="{ rotate: languageShow }"
></div>
</div>
<div
class="language-row dropdown-menu"
:class="{ show: languageShow }"
:style="{ left: '-10px', top: '50px', width: '280px' }"
>
<div class="search">
<i class="icon"></i
><input
type="text"
class="search-input"
v-model="serachKeywords"
placeholder="搜索你想要的"
/>
</div>
<div class="row">
<div
class="cols"
v-for="(k, v) in languageCurrent"
:key="v"
:value="v"
@click="onSelectLanguage(v)"
:class="{ on: sourceLanguage.key == v}"
style="height: 34px; overflow-y: hidden"
>
<div class="cols"><span>{{ k }}</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
v-show="engine.text === '语音翻译' || engine.text === '语音合成' "
>
<div class="language-row" style="margin-top: 30px">
<div class="target-language-text">翻译类型:</div>
<div class="language-selector-box">
<div
class="translation-language"
style="padding-left: 0; border-bottom: none; width: 100%"
>
<div
class="target language-selector"
@click="onShowLanguage('transTypeValue')"
style="
width: 100%;
margin-right: 0;
justify-content: space-between;
font-size: 16px;
"
>
{{ transTypeValue.value }}
<div
class="icon select-icons"
:class="{ rotate: transShow }"
></div>
</div>
<transtype-dropdown
class="dropdown-menu"
:show="transShow"
:left="languageRowLeft"
:top="languageRowTop"
width="280px"
:current-key="transTypeValue.key"
:language-list="transType"
@select="onSelectTransType"
></transtype-dropdown>
</div>
</div>
</div>
<div
class="language-row"
v-show="engine.text === '语音翻译' && transTypeValue.key == '1' "
style="margin-top: 30px"
>
<div class="original-language-text">原始语种:</div>
<div class="language-selector-box">
<div
class="translation-language"
style="padding-left: 0; border-bottom: none; width: 100%"
>
<div
class="source"
@click="onShowLanguage('sourceLanguage')"
style="
width: 100%;
margin-right: 0;
justify-content: space-between;
font-size: 16px;
"
>
{{ sourceLanguage.name }}
<div
class="icon select-icons"
:class="{ rotate: languageShow }"
></div>
</div>
<language-dropdown
class="dropdown-menu"
:show="languageShow"
:left="languageRowLeft"
:top="languageRowTop"
width="280px"
:current-key="sourceLanguage.key"
:language-list="languageCurrent"
@select="onSelectLanguage"
></language-dropdown>
</div>
</div>
</div>
<div
class="language-row"
style="margin-top: 30px"
v-show="engine.text === '语音翻译' && transTypeValue.key == '1' "
>
<div class="target-language-text">目标语种:</div>
<div class="language-selector-box">
<div
class="translation-language"
style="padding-left: 0; border-bottom: none; width: 100%"
>
<div
class="target"
@click="onShowLanguage('targetLanguage')"
style="
width: 100%;
margin-right: 0;
justify-content: space-between;
font-size: 16px;
"
>
{{ targetLanguage.name }}
<div
class="icon select-icons"
:class="{ rotate: languageShowTarget }"
></div>
</div>
<language-dropdown
class="dropdown-menu"
:show="languageShowTarget"
:left="languageRowLeft"
:top="languageRowTop"
width="280px"
:current-key="targetLanguage.key"
:language-list="languageCurrent"
@select="onSelectLanguage"
></language-dropdown>
</div>
</div>
</div>
<div
class="language-row"
style="margin-top: 30px"
v-show="engine.text === '语音翻译' && transTypeValue.key == '2' "
>
<div class="language-selector-box">
<div
class="translation-language"
style="padding-left: 0; border-bottom: none; width: 100%"
>
<div
class="source"
@click="onShowLanguage('sourceLanguage')"
style="
width: 100%;
margin-right: 0;
justify-content: space-between;
font-size: 16px;
"
>
<div
style="
max-width: 143px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ sourceLanguage.name }}
</div>
<div
class="icon select-icons"
:class="{ rotate: languageShow }"
></div>
</div>
<language-dropdown
class="dropdown-menu"
:show="languageShow"
:left="languageRowLeft"
:top="languageRowTop"
:current-key="sourceLanguage.key"
:language-list="languageCurrent"
width="200px"
@select="onSelectLanguage"
></language-dropdown>
</div>
</div>
<div
style="
cursor: pointer;
background: url(static/image/p14.png) no-repeat center;
background-size: 19px;
width: 40px;
height: 19px;
"
@click="onSwitch"
></div>
<!-- 目标 -->
<div class="language-selector-box">
<div
class="translation-language"
style="padding-left: 0; border-bottom: none; width: 100%"
>
<div
class="target"
@click="onShowLanguage('targetLanguage')"
style="
width: 100%;
margin-right: 0;
justify-content: space-between;
font-size: 16px;
"
>
<div
style="
max-width: 143px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ targetLanguage.name }}
</div>
<div
class="icon select-icons"
:class="{ rotate: languageShowTarget }"
></div>
</div>
<language-dropdown
class="dropdown-menu"
:show="languageShowTarget"
:left="languageRowLeft"
:top="languageRowTop"
width="200px"
:current-key="targetLanguage.key"
:language-list="languageCurrent"
@select="onSelectLanguage"
></language-dropdown>
</div>
</div>
<!-- 目标 -->
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/x-template" id="transtype-dropdown">
<div class="language-row" :class="{ show: show }" :style="{ left: '-10px', top: '50px', width: '280px' }" style="height: auto;" ><!-- <div class="search"><i class="icon"></i><input
type="text"
class="search-input"
v-model="search"
placeholder="搜索你想要的"
/></div> --><div class="row cols" v-for="item in filteredOptions"
:key="item.key" @click="select(item)"
:class="{ on: currentKey === item.key }"><div
class="cols"
><span>{{ item.value }}</span></div></div></div>
</script>
<script>
Vue.component("transtype-dropdown", {
name: "transtype-dropdown",
template: "#transtype-dropdown",
props: {
show: Boolean,
left: String,
top: String,
width: {
type: String,
default: "280px",
},
currentKey: String,
languageList: {
type: Array,
default: () => [],
},
},
data() {
return {
search: "",
};
},
computed: {
filteredOptions() {
if (!this.search) return this.languageList;
return this.languageList.filter((item) =>
item.value.includes(this.search)
);
},
},
methods: {
select(key) {
this.$emit("update:modelValue", key);
this.$emit("select", key);
},
},
});
</script>
<script type="text/x-template" id="language-dropdown">
<div class="language-row" :class="{ show: show }" :style="{ left, top, width }" v-if="show"><div class="search"><i class="icon"></i><input
type="text"
class="search-input"
v-model="search"
placeholder="搜索你想要的"
/></div><div class="row"><div class="cols" v-for="(k, v) in filteredLanguages"
:key="v" @click="select(v)"
:class="{ on: currentKey === v }"
style="height: 34px; overflow-y: hidden;"><div class="cols"><span>{{ k }}</span></div></div></div></div>
</script>
<script>
Vue.component("language-dropdown", {
template: "#language-dropdown",
props: {
show: Boolean,
left: String,
top: String,
width: {
type: String,
default: "280px",
},
currentKey: String,
languageList: Object,
},
data() {
return {
search: "",
};
},
computed: {
filteredLanguages() {
if (!this.search) return this.languageList;
const result = {};
for (const key in this.languageList) {
if (this.languageList[key].includes(this.search)) {
result[key] = this.languageList[key];
}
}
return result;
},
},
methods: {
select(key) {
this.$emit("select", key);
},
},
});
</script>
<script type="text/javascript">
const CancelToken = axios.CancelToken;
let source = CancelToken.source();
new Vue({
el: "#app",
data() {
return {
soundShow: false,
engine: {},
transType: [
{ key: "1", value: "指定翻译" },
{ key: "2", value: "双向翻译" },
],
engineType: [
{
key: "baidu",
value: 0,
icon: "/static/translate/img/identify.png",
icon1: "/static/translate/img/identify1.png",
text: "语音识别",
},
// {
// key: 'baidu',
// value: 1,
// icon: '/static/translate/img/synthetic.png',
// icon1: '/static/translate/img/synthetic1.png',
// text:'语音合成',
// },
{
key: "baidu",
value: 2,
icon: "/static/translate/img/translation.png",
icon1: "/static/translate/img/translation1.png",
text: "语音翻译",
},
],
sourceLanguage: {
key: "zh-cn",
name: "中文(普通话,简体)",
},
targetLanguage: {
key: "en-US",
name: "英语(美国)",
},
transTypeValue: {
key: "1",
value: "指定翻译",
},
sourceText: "",
targetText: "",
instance: {},
serachKeywords: "",
languageShow: false,
languageShowTarget: false,
transShow: false,
languageRowLeft: "-10px",
languageRowTop: "50px",
languageTotalData: {},
isLoading: false,
selectedGender: "male",
speedValue: 5,
pitchValue: 5,
mediaRecorder: null,
audioContext: null,
processor: null,
source: null,
socket: null,
preSocket: null,
autoCloseTimer: null,
stream: null,
errmsg: "",
token: "",
sampleRate: "16000",
};
},
async created() {
this.engine = this.engineType[0];
this.getLanguage();
this.getuserinfo();
layui.use("layer", function () {
window.layer = layui.layer;
});
const tempCtx = new (window.AudioContext ||
window.webkitAudioContext)();
const sampleRate = tempCtx.sampleRate;
this.sampleRate = sampleRate;
await tempCtx.close();
},
beforeUnmount() {
this.stop();
},
mounted() {
document.addEventListener("click", this.handleOutsideClick);
},
beforeDestroy() {
document.removeEventListener("click", this.handleOutsideClick);
},
watch: {},
computed: {
languageCurrent() {
const current = this.languageTotalData;
const copyCurrent = {};
if (this.serachKeywords) {
Object.keys(current).forEach((key) => {
// console.log('current[key]', current[key])
if (current[key].indexOf(this.serachKeywords) > -1) {
copyCurrent[key] = current[key];
}
});
return copyCurrent;
}
return this.languageTotalData;
},
},
methods: {
handleOutsideClick(e) {
const dropdownButtons = document.querySelectorAll(
".translation-language"
);
const dropdownMenus = document.querySelectorAll(".dropdown-menu");
let clickedInside = false;
dropdownButtons.forEach((button) => {
if (button.contains(e.target)) {
clickedInside = true;
}
});
dropdownMenus.forEach((menu) => {
if (menu.contains(e.target)) {
clickedInside = true;
}
});
if (!clickedInside) {
this.languageShow = false;
this.languageShowTarget = false;
this.transShow = false;
}
},
getuserinfo() {
this.errmsg = "";
axios.get("/api/voice/getAmount").then((res) => {
if (res.data.code == 1) {
let result = res.data.data;
this.token = result.token;
if (
Number(result.total_amount) - Number(result.use_amount) <
0
) {
this.errmsg = "余额";
}
} else {
this.errmsg = "登录";
layer.msg(res.data.info);
}
});
},
convertFloat32ToInt16(buffer) {
let l = buffer.length;
const buf = new Int16Array(l);
while (l--) {
buf[l] = Math.min(1, buffer[l]) * 0x7fff;
}
return buf.buffer;
},
onSocketOpen() {
console.log("WebSocket已连接");
this.soundShow = true;
this.autoCloseTimer = setTimeout(() => {
this.stop();
}, 60000);
},
async start() {
if (this.errmsg != "") {
return;
}
try {
document.querySelector(".transcription-box").value = "";
this.audioContext = new (window.AudioContext ||
window.webkitAudioContext)({ sampleRate: this.sampleRate });
const sampleRate = this.audioContext.sampleRate;
this.sampleRate = sampleRate;
let url = "";
if (this.engine.text === "语音识别") {
url = `wss://wss.trans-home.com/speech/ws?token=${this.token}&language=${this.sourceLanguage.key}&sampleRate=${sampleRate}`;
} else {
url =
this.transTypeValue.key == "1"
? `wss://wss.trans-home.com/speech/ws?token=${this.token}&language=${this.sourceLanguage.key}&transLanguage=${this.targetLanguage.key}&transType=1&sampleRate=${sampleRate}`
: `wss://wss.trans-home.com/speech/ws?token=${this.token}&language=${this.sourceLanguage.key},${this.targetLanguage.key}&transType=2&sampleRate=${sampleRate}`;
}
this.socket = new WebSocket(url);
this.socket.onopen = () => {
this.onSocketOpen();
};
window.finalResult = "";
this.socket.onmessage = (event) => {
try {
if (event.data == "recharge") {
this.stop();
return;
}
const msg = JSON.parse(event.data);
console.log("收到消息:", msg);
const outputBox =
document.querySelector(".transcription-box");
if (!outputBox) return;
let tempResult = "";
if (this.engine.text === "语音识别") {
if (msg.status == "recognizing") {
tempResult = msg.text;
outputBox.value =
finalResult +
(finalResult && tempResult ? " " : "") +
tempResult;
} else if (msg.status === "recognized") {
finalResult =
finalResult + (finalResult ? " " : "") + msg.text; // 修正这里
tempResult = "";
outputBox.value = finalResult;
}
} else {
if (msg.status == "recognizing") {
tempResult =
this.transTypeValue.key == "1"
? Object.values(msg.target)[0] || ""
: this.getTranslatedText(msg) || "";
outputBox.value =
finalResult +
(finalResult && tempResult ? " " : "") +
tempResult;
} else if (msg.status === "recognized") {
let val =
this.transTypeValue.key == "1"
? Object.values(msg.target)[0] || ""
: this.getTranslatedText(msg) || "";
finalResult =
finalResult + (finalResult ? " " : "") + val; // 修正这里
tempResult = "";
outputBox.value = finalResult;
}
}
} catch (err) {
console.error("消息处理错误:", err);
}
};
this.socket.onerror = (error) => {
console.error("WebSocket错误:", error);
this.stop();
};
this.socket.onclose = () => {
console.log("WebSocket已关闭");
this.cleanupResources();
};
// 初始化音频处理
this.stream = this.stream
? this.stream
: await navigator.mediaDevices.getUserMedia({ audio: true });
this.source = this.audioContext.createMediaStreamSource(
this.stream
);
this.processor = this.audioContext.createScriptProcessor(
4096,
1,
1
);
// 安全发送数据函数
const safeSend = (data) => {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
try {
this.socket.send(data);
} catch (err) {
console.error("发送数据失败:", err);
this.stop(); // 出错时自动停止
}
}
};
this.processor.onaudioprocess = (e) => {
if (!this.socket || this.socket.readyState !== WebSocket.OPEN)
return;
const input = e.inputBuffer.getChannelData(0);
const pcmData = this.convertFloat32ToInt16(input);
safeSend(pcmData);
};
this.source.connect(this.processor);
this.processor.connect(this.audioContext.destination);
} catch (err) {
layer.msg("初始化错误");
console.error("初始化错误:", err);
this.stop();
}
},
getTranslatedText(data) {
const mainLang = data.language.split("-")[0];
const entries = Object.entries(data.target);
const nonMainLangEntry = entries.find(
([lang]) => !lang.startsWith(mainLang)
);
return nonMainLangEntry
? nonMainLangEntry[1]
: entries[0]
? entries[0][1]
: null;
},
stop() {
console.log("停止");
window.finalResult = "";
// 关闭WebSocket
if (this.socket) {
if (
this.socket.readyState === WebSocket.OPEN ||
this.socket.readyState === WebSocket.CONNECTING
) {
this.socket.close();
}
this.socket = null;
}
// 清理音频资源
this.cleanupResources();
if (this.autoCloseTimer) {
clearTimeout(this.autoCloseTimer);
this.autoCloseTimer = null;
}
this.soundShow = false;
//过一秒调用
setTimeout(() => {
this.getuserinfo();
}, 1000);
},
// 清理音频资源
cleanupResources() {
if (this.processor) {
this.processor.disconnect();
this.processor = null;
}
if (this.source) {
this.source.disconnect();
this.source = null;
}
if (this.audioContext) {
this.audioContext.close().catch((e) => {
console.error("关闭AudioContext失败:", e);
});
this.audioContext = null;
}
},
copy() {
navigator.clipboard
.writeText(this.targetText)
.then(() => {
window.alert("复制成功");
})
.catch((err) => {
window.alert("复制失败");
});
},
onShowLanguage(key) {
if (!this.soundShow) {
if (key === "sourceLanguage") {
this.languageShow = !this.languageShow;
this.languageShowTarget = false;
this.transShow = false;
} else if (key === "targetLanguage") {
this.languageShowTarget = !this.languageShowTarget;
this.languageShow = false;
this.transShow = false;
} else if (key === "transTypeValue") {
this.transShow = !this.transShow;
this.languageShow = false;
this.languageShowTarget = false;
}
} else {
layer.msg("目前识别中,不可修改!");
}
this.currentKey = key;
},
onSelectEngine(e) {
if (this.soundShow) {
layer.msg("目前识别中,不可修改!");
return;
}
this.engine = e;
(this.sourceLanguage = {
key: "zh-cn",
name: "中文(普通话,简体)",
}),
(this.targetLanguage = {
key: "en-US",
name: "英语(美国)",
});
},
getLanguage() {
axios.get("/api/voice/getLanguage").then((res) => {
if (res.data.code == 1) {
this.languageTotalData = res.data.data;
console.log("res", this.languageTotalData);
}
});
},
onSelectTransType(e) {
if (this.soundShow) {
layer.msg("目前识别中,不可修改!");
return;
}
this.transTypeValue = e;
this.transShow = false;
},
onSelectLanguage(e) {
console.log(this.currentKey);
if (this.soundShow) {
layer.msg("目前识别中,不可修改!");
return;
}
this[this.currentKey] = {
key: e,
name: this.languageCurrent[e],
};
this.languageShow = false;
this.languageShowTarget = false;
console.log(this[this.currentKey]);
},
onSwitch() {
if (this.soundShow) {
layer.msg("目前识别中,不可修改!");
return;
}
const copySource = JSON.parse(JSON.stringify(this.sourceLanguage));
const copyTarget = JSON.parse(JSON.stringify(this.targetLanguage));
this.targetLanguage = copySource;
this.sourceLanguage = copyTarget;
},
onInput(e) {
if (this.sourceText) {
// _.debounce(this.translate, 500)
// this.translate()
} else {
this.targetText = "";
}
},
},
});
</script>
<div class="public-footer">
<div class="w1200">
<div class="left"><img src="static/picture/logo.png" alt="" /></div>
<div
style="
flex-direction: column;
line-height: 23px;
padding-left: 100px;
color: #fff;
font-size: 12px;
"
>
<p style="color: #fff; font-size: 12px"><span>官方频道:@apiapl_news</span></p>
<p style="color: #fff; font-size: 12px"><span>咨询客服:@apiapl</span></p>
<span></span>
</p>
</div>
<div class="right" style="white-space: nowrap">
<p></p>
<p><span>技术服务:@apiapl_sdk</span></p>
<p><span>联系邮箱info@apiapl.com</span></p>
<p class=""><span>联系电话:+18435173355 </span></p>
</div>
</div>
<div class="copyright">
<a href="https://beian.miit.gov.cn/" target="blank"
></a
>
</div>
</div>
</body>
</html>