1 //html部分 2 <template> 3 <div style="background-color:#F6F6F6 ;height:100vh;"> 4 <header><van-icon name="arrow-left" class="iconreturn" @click="$router.go(-1)" />{{ $t('function.votra') }}</header> 5 <div class="speakbg"> 6 <img src="../../../assets/speak.png" class="imgk" @touchstart="beginspeak" @touchend="endspeak" id="imgs" 7 ref="btnRef"> 8 <!-- <img src="../../../assets/speak.png" class="imgk" @click="endspeak" id="imgs" ref="btnRef"> --> 9 10 <p class="wkspeak">欢迎使用语音模式 </p> 11 <P class="beginspeak" v-if="speakopen">请轻点图标开始/暂停说话</P> 12 <P class="beginspeak" v-else>正在聆听中,请稍等</P> 13 14 <!-- <p class="release" @click="hearlongs">播放语音</p> --> 15 <!-- <div id="my_camera"></div> --> 16 </div> 17 <div class="resultbg"> 18 <div class="result"><el-input type="textarea" class="textareaone" v-model="textone" resize="false" :readonly="true"> 19 20 </el-input> 21 <span class="result-titles">原语音内容</span> 22 <el-button class="result-release" @click="releaseMusic" type="text"><img 23 src='../../../assets/release.png'></el-button> 24 25 </div> 26 <div class="results"><el-input type="textarea" class="textareaone" v-model="texttwo" resize="false" 27 :readonly="true"></el-input> 28 <span class="results-title">转译内容</span> 29 <span class="results-lan" @click="openLanChoose"><img :src="imgs">{{ lan }}<i 30 class="el-icon-arrow-down"></i></span> 31 <el-button class="results-release" @click="releaseNewMusic" type="text"><img 32 src='../../../assets/release.png'></el-button> 33 </div> 34 </div> 35 36 <van-action-sheet v-model="show" :actions="actions" @select="onSelect" title="语言切换" /> 37 </div> 38 </template> 39 <script > 40 import Recorder from 'js-audio-recorder'; 41 import lanList from '../../../utils/laug' 42 export default { 43 props: { 44 }, 45 data() { 46 return { 47 textone: '', 48 texttwo: '', 49 show: false, 50 values: 'zh-cn', 51 lan: '英语', 52 speakopen: true, 53 speaker: 'en-US-RogerNeural', 54 actions: lanList.lanList.countryList, 55 imgs: require('../../../assets/country/UK.png'), 56 recorder: new Recorder({ 57 sampleBits: 16, // 采样位数,支持 8 或 16,默认是16 58 sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000 59 numChannels: 1, // 声道,支持 1 或 2, 默认是1 60 // compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false 61 }) 62 }; 63 }, 64 watch: { 65 66 }, 67 mounted() { 68 console.log(this.actions) 69 70 }, 71 methods: { 72 beginspeak() { 73 this.textone = ''; 74 this.texttwo = ''; 75 Recorder.getPermission().then( 76 () => { 77 console.log("开始录音"); 78 this.speakopen = false; 79 this.recorder.start(); // 开始录音 80 }, 81 (error) => { 82 this.$message({ 83 message: error.message, 84 type: "info", 85 }); 86 console.log(`${error.name} : ${error.message}`); 87 } 88 ); 89 }, 90 endspeak() { 91 // 暂停录音 92 this.speakopen = true; 93 // 获取录音结果 94 // this.recorderEx.getPlayTime(); 95 this.recorder.stop(); 96 const wavBlob = this.recorder.getWAVBlob() // blob格式 97 // this.recorder.downloadWAV('翻译'); 98 const newbolb = new Blob([wavBlob], { type: 'audio/wav' }) 99 //获取当时时间戳作为文件名 100 const fileOfBlob = new File([newbolb], new Date().getTime() + '.wav') 101 console.log(fileOfBlob) 102 this.file = fileOfBlob; 103 this.lanChangeText(); 104 }, 105 106 onSelect(val) { 107 console.log(val, 'askdjsa'); 108 this.lan = val.cname; 109 this.imgs = val.img; 110 this.values = val.type; 111 this.getVals(this.textone) 112 this.speaker = val.speaker; 113 // this.getVal(val); 114 }, 115 getWAVRecordAudioData() { 116 var wavBlob = this.recorder.getWAVBlob(); 117 }, 118 openLanChoose() { 119 this.actions.map((item,index)=>{ 120 item.name = item.cname 121 }) 122 this.show = true; 123 }, 124 releaseMusic() { 125 this.recorder.play() 126 }, 127 hearlongs() { 128 recorder.play() 129 }, 130 releaseNewMusic() { 131 this.$axios({ 132 url: this.loginbases + '/textToSpeek/222.mp3', 133 method: 'POST', 134 headers: { 135 'Content-Type': 'application/x-www-form-urlencoded' 136 }, 137 responseType: 'arraybuffer', 138 data: { 139 voice: this.speaker, 140 rate: '+0%', 141 volume: '+10%', 142 text: this.texttwo 143 } 144 }).then((res) => { 145 console.log(res) 146 this.dataurl = this.getObjectURL(res.data, 'audio/mp3'); 147 console.log(this.dataurl) 148 var player = new Audio(this.dataurl); 149 player.play() 150 151 }) 152 }, 153 // 将返回的流数据转换为url 154 getObjectURL(file, type) { 155 return window.URL.createObjectURL(new Blob([file], { type })) 156 }, 157 158 //调用语音转换文字的功能 159 lanChangeText() { 160 this.$axios({ 161 url: this.loginbases + '/audioToText', 162 method: 'POST', 163 headers: { 164 'Content-Type': 'multipart/form-data' 165 }, 166 data: { 167 file: this.file 168 } 169 }).then((res) => { 170 console.log(res.data.data) 171 this.texttwo = res.data.data; 172 this.getVal(this.texttwo) 173 174 }) 175 176 }, 177 getVal(val) { 178 this.$axios({ 179 url: this.loginbases + '/translation', 180 method: 'POST', 181 headers: { 182 'Content-Type': 'application/x-www-form-urlencoded' 183 }, 184 data: { 185 text: val, 186 dest: this.values 187 188 } 189 }).then((res) => { 190 console.log(res) 191 if (res.data.code == 200) { 192 193 this.textone = res.data.data; 194 } 195 }) 196 197 198 }, 199 getVals(val) { 200 this.$axios({ 201 url: this.loginbases + '/translation', 202 method: 'POST', 203 headers: { 204 'Content-Type': 'application/x-www-form-urlencoded' 205 }, 206 data: { 207 text: val, 208 dest: this.values 209 210 } 211 }).then((res) => { 212 console.log(res) 213 if (res.data.code == 200) { 214 215 this.texttwo = res.data.data; 216 } 217 }) 218 219 220 }, 221 222 223 224 }, 225 mounted() { 226 227 228 }, 229 230 }; 231 232 </script> 233 <style lang="scss" scoped> 234 .pic { 235 width: 200px; 236 height: 200px; 237 } 238 239 .van-action-sheet { 240 max-height: 30%; 241 } 242 243 .van-action-sheet__header { 244 font-size: 10px; 245 line-height: 3.6rem; 246 } 247 248 .van-action-sheet__header { 249 background: rgba(244,238,235,0.5); 250 } 251 .van-action-sheet__item{ 252 background: rgba(244,238,235,0.5); 253 color: #5F5650; 254 font-weight: 400; 255 } 256 .van-action-sheet__item:hover{ 257 background:rgba(183,173,168,0.15); 258 color: #2F2620; 259 font-weight: 500; 260 } 261 // .van-action-sheet 262 .van-action-sheet__item { 263 font-size: 10px; 264 line-height: 3rem; 265 padding: 5px 0; 266 } 267 268 .van-action-sheet__close { 269 font-size: 10px; 270 padding: 0 10px; 271 } 272 273 >>>.el-textarea__inner { 274 height: 120px; 275 background: #fff; 276 font-size: 10px; 277 border-radius: 6.4px; 278 border: none; 279 padding-top: 28px; 280 margin-top: 10px; 281 text-indent: 12px; 282 283 } 284 285 #my_camera { 286 height: 100vh; 287 } 288 289 .iconreturn { 290 position: absolute; 291 left: 8px; 292 top: 10px; 293 } 294 295 .speakbg { 296 background-color: #fff; 297 padding-bottom: 20px; 298 } 299 300 .imgk { 301 width: 60px; 302 height: 60px; 303 margin-top: 52px; 304 305 -webkit-touch-callout: none; 306 -webkit-user-select: none; 307 -khtml-user-select: none; 308 -moz-user-select: none; 309 -ms-user-select: none; 310 user-select: none; 311 } 312 313 .wkspeak { 314 margin-top: 3px; 315 color: #B7ADA8; 316 } 317 318 .results { 319 position: relative; 320 321 &-title { 322 position: absolute; 323 left: 16px; 324 top: 22px; 325 font-size: 9px; 326 color: #019EFF 327 } 328 329 &-release { 330 position: absolute; 331 top: 26px; 332 left: 12px; 333 font-size: 12px; 334 color: #019EFF 335 } 336 337 &-lan { 338 position: absolute; 339 right: 10px; 340 top: 25px; 341 display: flex; 342 color: #019EFF; 343 font-size: 8px; 344 line-height: 8px; 345 346 img { 347 width: 10px; 348 height: 10px; 349 padding: 0 4px; 350 line-height: 4px; 351 // position: absolute; 352 right: 35px; 353 margin-top: -2px; 354 355 } 356 357 i { 358 margin-left: 2px; 359 } 360 } 361 } 362 363 .result { 364 position: relative; 365 366 &-titles { 367 position: absolute; 368 left: 16px; 369 top: 22px; 370 color: #FF6201; 371 font-size: 9px; 372 } 373 374 &-release { 375 position: absolute; 376 top: 26px; 377 left: 12px; 378 font-size: 12px 379 } 380 381 } 382 383 .beginspeak { 384 color: #36291E; 385 font-size: 12px; 386 margin-top: 8px; 387 } 388 </style>