Files
aggregate_translate_website/voice.html

1171 lines
42 KiB
HTML
Raw Permalink Normal View History

2025-07-02 18:32:06 +08:00
<!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>