update readme and fixed bug in ngpu (#2451)

* update readme and fixed ngpu bug

* update png in readme

* update readme and FT web ttsText
pull/2460/head
Ming 2 years ago committed by GitHub
parent b058a2d3fe
commit e65622548d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -28,7 +28,7 @@ Paddle Speech Demo 是一个以 PaddleSpeech 的语音交互功能为主体开
运行效果:
![效果](https://user-images.githubusercontent.com/30135920/191188766-12e7ca15-f7b4-45f8-9da5-0c0b0bbe5fcb.png)
![效果](https://user-images.githubusercontent.com/30135920/192155349-9ef93d20-730b-413d-8d50-412fedf11d4b.png)
@ -36,6 +36,7 @@ Paddle Speech Demo 是一个以 PaddleSpeech 的语音交互功能为主体开
### 后端环境安装
```bash
# 需要先安装 PaddleSpeech
cd speech_server
pip install -r requirements.txt -i https://mirror.baidu.com/pypi/simple
cd ../
@ -44,6 +45,8 @@ cd ../
### 前端环境安装
前端依赖 `node.js` ,需要提前安装,确保 `npm` 可用,`npm` 测试版本 `8.3.1`,建议下载[官网](https://nodejs.org/en/)稳定版的 `node.js`
如果因为网络问题,无法下载依赖库,可以参考 FAQ 部分,`npm / yarn 下载速度慢问题`
```bash
# 进入前端目录
cd web_client
@ -70,7 +73,7 @@ mkdir -p source/model
cd source/model
# 下载IE模型
wget https://bj.bcebos.com/paddlenlp/applications/speech-cmd-analysis/finetune/model_state.pdparams
cd ../../
cd ../../../
```
#### 启动后端服务
@ -84,6 +87,10 @@ python main.py --port 8010
### 启动 `vc.py` 后端服务
参照下面的步骤自行配置项目所需环境。
Aistudio 在线体验小样本合成后端功能:[【PaddleSpeech进阶】PaddleSpeech小样本合成方案体验](https://aistudio.baidu.com/aistudio/projectdetail/4573549?sUid=2470186&shared=1&ts=1664174385948)
#### 下载相关模型和音频
```bash
@ -172,8 +179,19 @@ cd web_client
yarn dev --port 8011
```
默认配置下,前端中配置的后台地址信息是 localhost确保后端服务器和打开页面的游览器在同一台机器上不在一台机器的配置方式见下方的 FAQ【后端如果部署在其它机器或者别的端口如何修改】
默认配置下,前端配置的后台地址信息是 `localhost`,确保后端服务器和打开页面的游览器在同一台机器上,不在一台机器的配置方式见下方的 FAQ【后端如果部署在其它机器或者别的端口如何修改】
#### 关于前端的一些说明
为了方便后期的维护,这里并没有给出打包好的 HTML 文件,而是 Vue3 的项目,使用 `yarn dev --port 8011` 的方式启动测试方便大家debug相当于是启动了一个前端服务器。
比如我们在本机启动的这个前端服务(运行 `yarn dev --port 8011` ),我们就可以通过在游览器中通过 `http://localhost:8011` 访问前端页面
如果我们在其它服务器上(例如:`*.*.*.*` )启动这个前端服务(运行 `yarn dev --port 8011` ),我们就可以通过在游览器中访问 `http://*.*.*.*:8011` 访问前端页面
那前端跟后端是什么关系呢? 两个是独立的,只要前端能够通过代理访问到后端的接口,那就没有问题。你可以在 A 机器上部署后端服务,然后在 B 机器上部署前端服务。我们在 `./web_client/vite.config.js` 中将 `/api` 映射到的是 `http://localhost:8010`,你可以把它配置成任意你想要访问后端地址。
当前端在以 `*.*.*.*` 这类以 IP 地址形式的网页中访问时,由于游览器的安全限制,会禁止录音,需要重新配置游览器的安全策略, 可以看下面 FAQ 部分: [【前端以IP地址的形式访问无法录音】]
## FAQ
@ -210,12 +228,24 @@ ASR_SOCKET_RECORD: 'ws://localhost:8010/ws/asr/onlineStream', // Stream ASR 接
TTS_SOCKET_RECORD: 'ws://localhost:8010/ws/tts/online', // Stream TTS 接口
```
#### Q后端以IP地址的形式前端无法录音
#### Q前端以IP地址的形式访问无法录音
A这里主要是游览器安全策略的限制需要配置游览器后重启。游览器修改配置可参考[使用js-audio-recorder报浏览器不支持getUserMedia](https://blog.csdn.net/YRY_LIKE_YOU/article/details/113745273)
chrome设置地址: chrome://flags/#unsafely-treat-insecure-origin-as-secure
#### Q: npm / yarn 配置淘宝镜像源
A: 配置淘宝镜像源,详细可以参考 [【yarn npm 设置淘宝镜像】](https://www.jianshu.com/p/f6f43e8f9d6b)
```bash
# npm 配置淘宝镜像源
npm config set registry https://registry.npmmirror.com
# yarn 配置淘宝镜像源
yarn config set registry http://registry.npm.taobao.org/
```
## 参考资料
vue实现录音参考资料https://blog.csdn.net/qq_41619796/article/details/107865602#t1

@ -1,5 +1,6 @@
import os
from .util import get_ngpu
from .util import MAIN_ROOT
from .util import run_cmd
@ -171,6 +172,7 @@ class SAT:
output_name: str,
source_lang: str,
target_lang: str):
ngpu = get_ngpu()
cmd = f"""
FLAGS_allocator_strategy=naive_best_fit \
FLAGS_fraction_of_gpu_memory_to_use=0.01 \
@ -189,7 +191,8 @@ class SAT:
--voc_config={voc_config} \
--voc_ckpt={voc_ckpt} \
--voc_stat={voc_stat} \
--output_name={output_name}
--output_name={output_name} \
--ngpu={ngpu}
"""
return cmd

@ -1,5 +1,6 @@
import os
from .util import get_ngpu
from .util import MAIN_ROOT
from .util import run_cmd
@ -38,7 +39,7 @@ class FineTune:
dump_dir = os.path.join(exp_dir, 'dump')
output_dir = os.path.join(exp_dir, 'exp')
lang = "zh"
ngpu = 1
ngpu = get_ngpu()
cmd = f"""
# check oov
@ -91,7 +92,7 @@ class FineTune:
output_dir = os.path.join(exp_dir, 'exp')
text_path = os.path.join(exp_dir, 'sentences.txt')
lang = "zh"
ngpu = 1
ngpu = get_ngpu()
model_path = f"{output_dir}/checkpoints"
ckpt = find_max_ckpt(model_path)
@ -117,7 +118,8 @@ class FineTune:
--output_dir={out_wav_dir} \
--phones_dict={dump_dir}/phone_id_map.txt \
--speaker_dict={dump_dir}/speaker_id_map.txt \
--spk_id=0
--spk_id=0 \
--ngpu={ngpu}
"""
out_path = os.path.join(out_wav_dir, f"{wav_name}.wav")

@ -1,6 +1,7 @@
import os
import shutil
from .util import get_ngpu
from .util import MAIN_ROOT
from .util import run_cmd
@ -30,11 +31,12 @@ class VoiceCloneGE2E():
ref_audio_dir = os.path.realpath("tmp_dir/ge2e")
if os.path.exists(ref_audio_dir):
shutil.rmtree(ref_audio_dir)
else:
os.makedirs(ref_audio_dir, exist_ok=True)
shutil.copy(input_wav, ref_audio_dir)
os.makedirs(ref_audio_dir, exist_ok=True)
shutil.copy(input_wav, ref_audio_dir)
output_dir = os.path.dirname(out_wav)
ngpu = get_ngpu()
cmd = f"""
python3 {self.BIN_DIR}/voice_cloning.py \
@ -50,7 +52,8 @@ class VoiceCloneGE2E():
--text="{text}" \
--input-dir={ref_audio_dir} \
--output-dir={output_dir} \
--phones-dict={self.phones_dict}
--phones-dict={self.phones_dict} \
--ngpu={ngpu}
"""
output_name = os.path.join(output_dir, full_file_name)

@ -1,6 +1,7 @@
import os
import shutil
from .util import get_ngpu
from .util import MAIN_ROOT
from .util import run_cmd
@ -27,11 +28,11 @@ class VoiceCloneTDNN():
ref_audio_dir = os.path.realpath("tmp_dir/tdnn")
if os.path.exists(ref_audio_dir):
shutil.rmtree(ref_audio_dir)
else:
os.makedirs(ref_audio_dir, exist_ok=True)
shutil.copy(input_wav, ref_audio_dir)
os.makedirs(ref_audio_dir, exist_ok=True)
shutil.copy(input_wav, ref_audio_dir)
output_dir = os.path.dirname(out_wav)
ngpu = get_ngpu()
cmd = f"""
python3 {self.BIN_DIR}/voice_cloning.py \
@ -47,7 +48,8 @@ class VoiceCloneTDNN():
--input-dir={ref_audio_dir} \
--output-dir={output_dir} \
--phones-dict={self.phones_dict} \
--use_ecapa=True
--use_ecapa=True \
--ngpu={ngpu}
"""
output_name = os.path.join(output_dir, full_file_name)

@ -2,10 +2,19 @@ import os
import random
import subprocess
import paddle
NOW_FILE_PATH = os.path.dirname(__file__)
MAIN_ROOT = os.path.realpath(os.path.join(NOW_FILE_PATH, "../../../../"))
def get_ngpu():
if paddle.device.get_device() == "cpu":
return 0
else:
return 1
def randName(n=5):
return "".join(random.sample('zyxwvutsrqponmlkjihgfedcba', n))

@ -281,15 +281,18 @@ async def VcCloneG2P(base: VcBaseText):
if base.func == 'ge2e':
wavName = base.wavName
wavPath = os.path.join(VC_OUT_PATH, wavName)
vc_model.vc(
wavPath = vc_model.vc(
text=base.text, input_wav=base.wavPath, out_wav=wavPath)
else:
wavName = base.wavName
wavPath = os.path.join(VC_OUT_PATH, wavName)
vc_model_tdnn.vc(
wavPath = vc_model_tdnn.vc(
text=base.text, input_wav=base.wavPath, out_wav=wavPath)
res = {"wavName": wavName, "wavPath": wavPath}
return SuccessRequest(result=res)
if wavPath:
res = {"wavName": wavName, "wavPath": wavPath}
return SuccessRequest(result=res)
else:
return ErrorRequest(message="克隆失败,检查克隆脚本是否有效")
except Exception as e:
print(e)
return ErrorRequest(message="克隆失败,合成过程报错")

@ -47,7 +47,7 @@ import FineTuneT from './SubMenu/FineTune/FineTune.vue'
<el-tab-pane label="小数据微调" key="7">
<FineTuneT></FineTuneT>
</el-tab-pane>
<el-tab-pane label="ENIRE SAT" key="8">
<el-tab-pane label="ENIRE-SAT" key="8">
<ENIRE_SATT></ENIRE_SATT>
</el-tab-pane>
</el-tabs>

@ -58,9 +58,6 @@ export default {
mounted () {
this.wsUrl = apiURL.ASR_SOCKET_RECORD
this.ws = new WebSocket(this.wsUrl)
if(this.ws.readyState === this.ws.CONNECTING){
this.$message.success("实时识别 Websocket 连接成功")
}
var _that = this
this.ws.addEventListener('message', function (event) {
var temp = JSON.parse(event.data);
@ -78,7 +75,7 @@ export default {
// websocket
// debugger
if(this.ws.readyState != this.ws.OPEN){
this.$message.error("websocket 链接失败,请检查链接地址是否正确")
this.$message.error("websocket 链接失败,请检查 Websocket 后端服务是否正确开启")
return
}

@ -1,298 +0,0 @@
<template>
<div class="chatbox">
<h3>语音聊天</h3>
<div class="home" style="margin:1vw;">
<el-button :type="recoType" @click="startRecorder()" style="margin:1vw;">{{ recoText }}</el-button>
<!-- <el-button :type="playType" @click="playRecorder()" style="margin:1vw;"> {{ playText }}</el-button> -->
<el-button :type="envType" @click="envRecorder()" style="margin:1vw;"> {{ envText }}</el-button>
<!-- <el-button :type="envType" @click="getTts(ttsd)" style="margin:1vw;"> TTS </el-button> -->
<el-button type="warning" @click="clearChat()" style="margin:1vw;"> 清空聊天</el-button>
</div>
<div v-for="Result in allResultList">
<h3>{{Result}}</h3>
</div>
</div>
</template>
<script>
import Recorder from 'js-audio-recorder'
const recorder = new Recorder({
sampleBits: 16, // 8 1616
sampleRate: 16000, // 110251600022050240004410048000chrome48000
numChannels: 1, // 1 2 1
compiling: true
})
export default {
name: 'home',
data () {
return {
recoType: "primary",
recoText: "开始录音",
playType: "success",
playText: "播放录音",
envType: "success",
envText: "环境采样",
asrResultList: [],
nlpResultList: [],
ttsResultList: [],
allResultList: [],
webSocketRes: "websocket",
drawRecordId: null,
onReco: false,
onPlay: false,
onRecoPause: false,
ws: '',
ttsd: "你的名字叫什么,你的名字叫什么,你的名字叫什么你的名字叫什么",
audioCtx: '',
source: '',
typedArray: '',
ttsResult: '',
}
},
mounted () {
//
var AudioContext = window.AudioContext || window.webkitAudioContext;
this.audioCtx = new AudioContext({
latencyHint: 'interactive',
sampleRate: 24000,
});
// play
recorder.onplayend = () => {
this.onPlay = false
this.playText = "播放录音"
this.playType = "success"
this.$nextTick(()=>{})
}
// ws
this.ws = new WebSocket("ws://localhost:8010/ws/asr/offlineStream");
//
var _that = this
this.ws.addEventListener('message', function (event) {
_that.allResultList.push("asr:" + event.data)
_that.$nextTick(()=>{})
_that.getNlp(event.data)
})
},
methods: {
//
clearChat(){
this.allResultList = []
},
//
startRecorder () {
if(!this.onReco){
this.resumeRecordOnline()
recorder.start().then(() => {
setInterval(() => {
//
let newData = recorder.getNextData();
if (!newData.length) {
return;
}
// 1
this.uploadChunk(newData)
}, 500)
}, (error) => {
console.log("录音出错");
})
this.onReco = true
this.recoType = "danger"
this.recoText = "结束录音"
this.$nextTick(()=>{
})
} else {
//
recorder.stop()
this.onReco = false
this.recoType = "primary"
this.recoText = "开始录音"
this.$nextTick(()=>{})
recorder.clear()
// wav,
// const wavs = recorder.getWAVBlob()
// this.uploadFile(wavs, "/api/asr/offline")
// console.log(wavs)
// ,
this.stopRecordOnline()
}
},
//
envRecorder () {
if(!this.onReco){
recorder.start().then(() => {
}, (error) => {
console.log("录音出错");
})
this.onReco = true
this.envType = "danger"
this.envText = "结束采样"
this.$nextTick(()=>{
})
} else {
//
recorder.stop()
this.onReco = false
this.envType = "success"
this.envText = "环境采样"
this.$nextTick(()=>{})
const wavs = recorder.getWAVBlob()
this.uploadFile(wavs, "/api/asr/collectEnv")
}
},
//
playRecorder () {
if(!this.onPlay){
//
recorder.play()
this.onPlay = true
this.playText = "结束播放"
this.playType = "warning"
this.$nextTick(()=>{})
} else {
recorder.stopPlay()
this.onPlay = false
this.playText = "播放录音"
this.playType = "success"
this.$nextTick(()=>{})
}
},
//
async uploadFile(file, post_url){
const formData = new FormData()
formData.append('files', file)
const result = await this.$http.post(post_url, formData);
if (result.data.code === 0) {
this.asrResultList.push(result.data.result)
// this.$message.success(result.data.message);
} else {
this.$message.error(result.data.message);
}
},
// chunk
async uploadChunk(chunkDatas) {
chunkDatas.forEach((chunkData) => {
this.ws.send(chunkData)
})
},
// ,pcm
async stopRecordOnline(){
const result = await this.$http.get("/api/asr/stopRecord");
if (result.data.code === 0) {
console.log("Online 录音停止成功")
} else {
// console.log("chunk ")
}
},
//
async resumeRecordOnline(){
const result = await this.$http.get("/api/asr/resumeRecord");
if (result.data.code === 0) {
console.log("chunk 发送成功")
} else {
// console.log("chunk ")
}
},
// NLP
async getNlp(asrText){
//
this.onRecoPause = true
recorder.pause()
this.stopRecordOnline()
console.log('录音暂停')
const result = await this.$http.post("/api/nlp/chat", { chat: asrText});
if (result.data.code === 0) {
this.allResultList.push("nlp:" + result.data.result)
this.getTts(result.data.result)
// this.$message.success(result.data.message);
} else {
this.$message.error(result.data.message);
}
// console.log("")
},
base64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
},
// TTS
async getTts(nlpText){
// base64
this.ttsResult = await this.$http.post("/api/tts/offline", { text : nlpText});
this.typedArray = this.base64ToUint8Array(this.ttsResult.data.result)
// console.log("chat", this.typedArray.buffer)
this.playAudioData( this.typedArray.buffer )
},
// play
playAudioData( wav_buffer ) {
this.audioCtx.decodeAudioData(wav_buffer, buffer => {
this.source = this.audioCtx.createBufferSource();
this.source.onended = () => {
//
if(this.onRecoPause){
console.log("恢复录音")
this.onRecoPause = false
//
recorder.resume()
//
this.resumeRecordOnline()
}
}
this.source.buffer = buffer;
this.source.connect(this.audioCtx.destination);
this.source.start();
}, function(e) {
Recorder.throwError(e);
});
}
},
}
</script>
<style lang='less' scoped>
.chatbox {
border: 4px solid #F00;
// position: fixed;
width: 100%;
height: 20%;
overflow: auto;
}
</style>

@ -91,6 +91,10 @@ export default {
methods: {
//
startRecorder(){
if(this.ws.readyState != this.ws.OPEN){
this.$message.error("websocket 链接失败,请检查 Websocket 后端服务是否正确开启")
return
}
this.allResultList = []
if(!this.onReco){
this.asrResult = this.speakingText

@ -98,7 +98,7 @@
</el-row>
<el-row :gutter="20">
<el-button v-if='this.cloneWav' type="success" @click="PlaySyn()"></el-button>
<el-button v-else disabled type="success" @click="PlaySyn()"></el-button>
<el-button v-else disabled type="primary" @click="PlaySyn()"></el-button>
<el-button v-if='this.cloneWav' type="primary" @click="downLoadCloneWav()"></el-button>
<el-button v-else disabled type="primary" @click="downLoadCloneWav()"></el-button>
</el-row>

@ -80,7 +80,7 @@
</el-row>
<el-row :gutter="20">
<el-button v-if='this.cloneWav' type="primary" @click="PlaySyn()"></el-button>
<el-button v-if='this.cloneWav' type="success" @click="PlaySyn()"></el-button>
<el-button v-else disabled type="primary" @click="PlaySyn()"></el-button>
<el-button v-if='this.cloneWav' type="primary" @click="downLoadCloneWav()"></el-button>
<el-button v-else disabled type="primary" @click="downLoadCloneWav()"></el-button>
@ -126,7 +126,7 @@
expPath: '',
wav: '',
wav_base64: '',
ttsText: '',
ttsText: '欢迎使用飞桨语音套件',
cloneWav: '',
onEnrollRec: 0, //

@ -1,125 +0,0 @@
<template>
<div class="iebox">
<h1>信息抽取体验</h1>
<el-button :type="recoType" @click="startRecorder()" style="margin:1vw;">{{ recoText }}</el-button>
<h3>识别结果: {{ asrResultOffline }}</h3>
<h4>时间{{ time }}</h4>
<h4>出发地{{ outset }}</h4>
<h4>目的地{{ destination }}</h4>
<h4>费用{{ amount }}</h4>
</div>
</template>
<script>
import Recorder from 'js-audio-recorder'
const recorder = new Recorder({
sampleBits: 16, // 8 1616
sampleRate: 16000, // 110251600022050240004410048000chrome48000
numChannels: 1, // 1 2 1
compiling: true
})
export default {
name: "IE",
data(){
return {
streamAsrResult: '',
recoType: "primary",
recoText: "开始录音",
playType: "success",
asrResultOffline: '',
onReco: false,
ws:'',
time: '',
outset: '',
destination: '',
amount: ''
}
},
methods: {
startRecorder () {
if(!this.onReco){
recorder.clear()
recorder.start().then(() => {
}, (error) => {
console.log("录音出错");
})
this.onReco = true
this.recoType = "danger"
this.recoText = "结束录音"
this.time = ''
this.outset=''
this.destination = ''
this.amount = ''
this.$nextTick(()=>{
})
} else {
//
recorder.stop()
this.onReco = false
this.recoType = "primary"
this.recoText = "开始录音"
this.$nextTick(()=>{})
// wav,
const wavs = recorder.getWAVBlob()
this.uploadFile(wavs, "/api/asr/offline")
}
},
async uploadFile(file, post_url){
const formData = new FormData()
formData.append('files', file)
const result = await this.$http.post(post_url, formData);
if (result.data.code === 0) {
this.asrResultOffline = result.data.result
this.$nextTick(()=>{})
this.$message.success(result.data.message);
this.informationExtract()
} else {
this.$message.error(result.data.message);
}
},
async informationExtract(){
const postdata = {
chat: this.asrResultOffline
}
const result = await this.$http.post('/api/nlp/ie', postdata)
console.log("ie", result)
if(result.data.result[0]['时间']){
this.time = result.data.result[0]['时间'][0]['text']
}
if(result.data.result[0]['出发地']){
this.outset = result.data.result[0]['出发地'][0]['text']
}
if(result.data.result[0]['目的地']){
this.destination = result.data.result[0]['目的地'][0]['text']
}
if(result.data.result[0]['费用']){
this.amount = result.data.result[0]['费用'][0]['text']
}
}
},
}
</script>
<style lang="less" scoped>
.iebox {
border: 4px solid #F00;
top:80%;
width: 100%;
height: 20%;
overflow: auto;
}
</style>

@ -228,6 +228,10 @@ export default {
},
// WS
async getTtsChunkWavWS(){
if(this.ws.readyState != this.ws.OPEN){
this.$message.error("websocket 链接失败,请检查 Websocket 后端服务是否正确开启")
return
}
// chunks
chunks = []
chunk_index = 0

@ -1,178 +0,0 @@
<template>
<div class="vprbox">
<div>
<h1>声纹识别展示</h1>
<el-input
v-model="spk_id"
class="w-50 m-2"
size="large"
placeholder="spk_id"
/>
<el-button :type="recoType" @click="startRecorder()" style="margin:1vw;">{{ recoText }}</el-button>
<el-button type="primary" @click="Enroll(spk_id)" style="margin:1vw;"> 注册 </el-button>
<el-button type="primary" @click="Recog()" style="margin:1vw;"> 识别 </el-button>
</div>
<div>
<h2>声纹得分结果</h2>
<el-table :data="score_result" style="width: 40%">
<el-table-column prop="spkId" label="spk_id" />
<el-table-column prop="score" label="score" />
</el-table>
</div>
<div>
<h2>声纹数据列表</h2>
<el-table :data="vpr_datas" style="width: 40%">
<el-table-column prop="spkId" label="spk_id" />
<el-table-column label="wav">
<template #default="scope2">
<audio :src="'/VPR/vpr/data/?vprId='+scope2.row.vprId" controls>
</audio>
</template>
</el-table-column>
<el-table-column fixed="right" label="Operations">
<template #default="scope">
<el-button @click="Del(scope.row.spkId)" type="text" size="small">Delete</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
import Recorder from 'js-audio-recorder'
const recorder = new Recorder({
sampleBits: 16, // 8 1616
sampleRate: 16000, // 110251600022050240004410048000chrome48000
numChannels: 1, // 1 2 1
compiling: true
})
export default {
name: "VPR",
data () {
return {
url_enroll: '/VPR/vpr/enroll', //
url_recog: '/VPR/vpr/recog', //
url_del: '/VPR/vpr/del', //
url_list: '/VPR/vpr/list', //
url_data: '/VPR/vpr/data', //
spk_id: 'sss',
onRecord: false,
recoType: "primary",
recoText: "开始录音",
wav: '',
score_result: [],
vpr_datas: []
}
},
mounted () {
this.GetList()
},
methods: {
startRecorder () {
this.score_result = []
if(!this.onReco){
recorder.start().then(() => {
}, (error) => {
console.log("录音出错");
})
this.onReco = true
this.recoType = "danger"
this.recoText = "结束录音"
this.$nextTick(()=>{
})
} else {
//
recorder.stop()
this.onReco = false
this.recoType = "primary"
this.recoText = "开始录音"
this.$nextTick(()=>{})
// wav,
this.wav = recorder.getWAVBlob()
}
},
async Enroll(spk_id){
if(this.wav === ''){
this.$message.error("请先完成录音");
return
}
let formData = new FormData()
formData.append('spk_id', this.spk_id)
formData.append('audio', this.wav)
console.log("formData", formData)
console.log("spk_id", this.spk_id)
const result = await this.$http.post(this.url_enroll, formData);
if(result.data.status){
this.$message.success("声纹注册成功")
} else {
this.$message.error(result.data.msg)
}
console.log(result)
this.GetList()
},
async Recog(){
this.score_result = []
if(this.wav === ''){
this.$message.error("请先完成录音");
return
}
let formData = new FormData()
formData.append('audio', this.wav)
const result = await this.$http.post(this.url_recog, formData);
console.log(result)
result.data.forEach(dat => {
this.score_result.push({
spkId: dat[0],
score: dat[1][1]
})
});
},
async Del(spkId){
console.log('spkId', spkId)
//
const result = await this.$http.post(this.url_del, {spk_id: spkId});
if(result.data.status){
this.$message.success("删除成功")
} else {
this.$message.error(result.data.msg)
}
this.GetList()
},
async GetList(){
this.vpr_datas =[]
const result = await this.$http.get(this.url_list);
console.log("list", result)
for(let i=0; i<result.data[0].length; i++){
this.vpr_datas.push({
spkId: result.data[0][i],
vprId: result.data[1][i]
})
}
this.$nextTick(()=>{})
},
GetData(){},
},
}
</script>
<style lang='less' scoped>
.vprbox {
border: 4px solid #F00;
// position: fixed;
top:60%;
width: 100%;
height: 20%;
overflow: auto;
}
</style>

@ -214,14 +214,17 @@ export default {
let formData = new FormData()
formData.append('spk_id', this.enrollSpkId)
formData.append('audio', this.wav)
const result = await vprEnroll(formData)
if (!result){
this.$message.error("请检查后端服务是否正确开启")
return
}
if(result.data.status){
this.$message.success("声纹注册成功")
} else {
this.$message.error(result.data.msg)
}
// console.log(result)
this.GetList()
this.wav = ''
this.randomSpkId()

@ -71,7 +71,7 @@
</el-row>
<el-row :gutter="20">
<el-button v-if='this.cloneWav' type="primary" @click="PlaySyn()"></el-button>
<el-button v-if='this.cloneWav' type="success" @click="PlaySyn()"></el-button>
<el-button v-else disabled type="primary" @click="PlaySyn()"></el-button>
<el-button v-if='this.cloneWav' type="primary" @click="downLoadCloneWav()"></el-button>
<el-button v-else disabled type="primary" @click="downLoadCloneWav()"></el-button>
@ -270,6 +270,7 @@ export default {
} else if (this.nowIndex >= this.vcDatas.length){
return this.$message.error("当前序号不可以超过音频个数")
}
this.cloneWav = ""
let func = ''
if(this.func_radio === '1'){
func = 'ge2e'
@ -289,12 +290,12 @@ export default {
}
);
this.g2pOnSys = 0
if(!result.data.code){
if(result.data.code == 0){
this.cloneWav = result.data.result
console.log("clone wav: ", this.cloneWav)
this.$message.success("音色克隆成功")
this.$message.success("音频合成成功")
} else {
this.$message.error(result.data.msg)
this.$message.error("音频合成失败,请检查后台错误后重试!")
}
},
//

Loading…
Cancel
Save