电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

瀏覽:7日期:2022-10-25 14:20:46

引言

在與實(shí)現(xiàn)了語(yǔ)音合成、語(yǔ)義分析、機(jī)器翻譯等算法的后端交互時(shí),頁(yè)面可以設(shè)計(jì)成更為人性化、親切的方式。我們采用類似于聊天對(duì)話的實(shí)現(xiàn),效果如下:

智能客服(輸入文本,返回引擎處理后的文本結(jié)果)

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

語(yǔ)音合成(輸入文本,返回文本以及合成的音頻)

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

如上圖所示,返回文本后,再返回合成出的音頻。音頻按鈕嵌在對(duì)話氣泡中,可以點(diǎn)擊播放。

語(yǔ)音識(shí)別(在頁(yè)面錄制語(yǔ)音發(fā)送,頁(yè)面實(shí)時(shí)展示識(shí)別出的文本結(jié)果)

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

實(shí)現(xiàn)功能及技術(shù)要點(diǎn)

1、基于WebSocket實(shí)現(xiàn)對(duì)話流頁(yè)面與后端的交互是實(shí)時(shí)互動(dòng)的,所以采用WebSocket協(xié)議,而不是HTTP請(qǐng)求,這樣后端推送回的消息可以實(shí)時(shí)顯示在頁(yè)面上。WebSocket的返回是隊(duì)列的、無(wú)序的,在后續(xù)處理中我們也需要注意這一點(diǎn),在后文中會(huì)說(shuō)到。2、調(diào)用設(shè)備麥克風(fēng)進(jìn)行音頻錄制和轉(zhuǎn)碼加頭,基于WebAudio、WaveSurferJS等實(shí)現(xiàn)音頻處理和繪制3、基于Vue的響應(yīng)式頁(yè)面實(shí)現(xiàn)4、CSS3 + Canvas + JS 交互效果優(yōu)化

錄制音頻CSS動(dòng)畫效果 聊天記錄自動(dòng)滾動(dòng)

下面給出部分實(shí)現(xiàn)代碼。

集成WebSocket

我們的聊天組件是頁(yè)面?zhèn)冗叴蜷_(kāi)的抽屜(el-drawer),Vue組件會(huì)在打開(kāi)時(shí)創(chuàng)建,關(guān)閉時(shí)銷毀。在組件中引入WebSocket,并管理它的開(kāi)、關(guān)、消息接收和發(fā)送,使它的生命周期與組件一致(打開(kāi)窗口時(shí)創(chuàng)建ws連接,關(guān)閉窗口時(shí)關(guān)閉連接,避免與后臺(tái)連接過(guò)多。)

created(){ if (typeof WebSocket === ’undefined’) { alert(’您的瀏覽器不支持socket’) } else { // 實(shí)例化socket this.socket = new WebSocket(this.socketServerPath) // 監(jiān)聽(tīng)socket連接 this.socket.onopen = this.open // 監(jiān)聽(tīng)socket錯(cuò)誤信息 this.socket.onerror = this.error // 監(jiān)聽(tīng)socket消息 this.socket.onmessage = this.onMessage this.socket.onclose = this.close }}destroyed(){ this.socket.close()}

如上,將WebSocket的事件綁定到JS方法中,可以在對(duì)應(yīng)方法中實(shí)現(xiàn)對(duì)數(shù)據(jù)的接收和發(fā)送。打開(kāi)瀏覽器控制臺(tái),選中指定的標(biāo)簽,便于對(duì)WebSocket連接進(jìn)行監(jiān)控和查看。

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

音頻錄制采集

從瀏覽器端音頻和視頻采集基于網(wǎng)頁(yè)即時(shí)通信(Web Real-TimeCommunication,簡(jiǎn)稱WebRTC) 的API。通過(guò)WebRTC的getUserMedia實(shí)現(xiàn),獲取一個(gè)MediaStream對(duì)象,將該對(duì)象關(guān)聯(lián)到AudioContext即可獲得音頻。

可參考RecorderJS的實(shí)現(xiàn): https://github.com/mattdiamond/Recorderjs/blob/master/examples/example_simple_exportwav.html

if (navigator.getUserMedia) { navigator.getUserMedia( { audio: true }, // 只啟用音頻 function(stream) { var context = new(window.webkitAudioContext || window.AudioContext)() var audioInput = context.createMediaStreamSource(stream) var recorder = new Recorder(audioInput) }, function(error) { switch (error.code || error.name) { case ’PERMISSION_DENIED’: case ’PermissionDeniedError’: throwError(’用戶拒絕提供信息。’) break case ’NOT_SUPPORTED_ERROR’: case ’NotSupportedError’: throwError(’瀏覽器不支持硬件設(shè)備。’) break case ’MANDATORY_UNSATISFIED_ERROR’: case ’MandatoryUnsatisfiedError’: throwError(’無(wú)法發(fā)現(xiàn)指定的硬件設(shè)備。’) break default: throwError(’無(wú)法打開(kāi)麥克風(fēng)。異常信息:’ + (error.code || error.name)) break } } ) } else { throwError(’當(dāng)前瀏覽器不支持錄音功能。’) }

注意: 若navigator.getUserMedia獲取到的是undefined,是Chrome瀏覽器的安全策略導(dǎo)致的,需要通過(guò)https請(qǐng)求或配置瀏覽器,配置地址: chrome://flags/#unsafely-treat-insecure-origin-as-secure

瀏覽器采集到的音頻為PCM格式(PCM (脈沖編碼調(diào)制 Pulse Code Modulation)),需要對(duì)音頻加頭才能在頁(yè)面上進(jìn)行播放。注意加頭時(shí)采樣率、采樣頻率、聲道數(shù)量等必須與采樣時(shí)相同,不然加完頭后的音頻無(wú)法解碼。參考查看https://github.com/mattdiamond/Recorderjs/blob/master/src/recorder.js中exportWav方法。

業(yè)務(wù)中對(duì)接的語(yǔ)音識(shí)別引擎為實(shí)時(shí)轉(zhuǎn)寫引擎,即:不是錄制完成后再發(fā)送,而是一邊錄制一邊進(jìn)行編碼并發(fā)送。使用onaudioprocess方法監(jiān)聽(tīng)語(yǔ)音的輸入:

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

參考這個(gè)實(shí)現(xiàn),我們可以在每次監(jiān)聽(tīng)到有數(shù)據(jù)寫入時(shí),從buffer中獲取到錄制到的數(shù)據(jù),并進(jìn)行編碼、壓縮,再通過(guò)WebSocket發(fā)送。

Vue組件設(shè)計(jì)和業(yè)務(wù)實(shí)現(xiàn)

分析頁(yè)面業(yè)務(wù)邏輯,將代碼拆分成兩個(gè)組件:ChatDialog.vue 聊天對(duì)話框頁(yè)面,根據(jù)輸入類型,分為文本輸入、語(yǔ)音輸入。ChatRecord.vue聊天記錄組件,根據(jù)發(fā)送方(自己或者系統(tǒng))展示向左/向右的氣泡,根據(jù)內(nèi)容顯示文本、音頻等。ChatDialog是ChatRecord的父組件,遍歷ChatDialog中的chatList對(duì)象(Array),將chatList中的項(xiàng)注入到ChatRecord中。

<div class='chat-list'> <div v-for='(item,index) in chatList' :key='index' class='msg-wrapper'> <chat-record ref='chatRecord' :data='item' @showJson='showJsonDialog'></chat-record> </div> <div style='height:0px; overflow:hidden'></div> </div></div>

對(duì)于聊天記錄的氣泡展示,與數(shù)據(jù)類型相關(guān)性很強(qiáng),ChatRecord組件只關(guān)心對(duì)數(shù)據(jù)的處理和展示,我們可以完全不用關(guān)心消息的發(fā)送、接收、音頻的錄制、停止錄制、接受音頻等邏輯,只需要根據(jù)數(shù)據(jù)來(lái)展示不同的樣式即可。這樣Vue的響應(yīng)式就充分獲得了用武之地:無(wú)需用代碼對(duì)樣式展示進(jìn)行控制,只需要設(shè)計(jì)合理的數(shù)據(jù)格式和樣式模板,然后注入不同的數(shù)據(jù)即可。模板頁(yè)面: 使用v-if控制,修改chatList里的對(duì)象內(nèi)容即可改變頁(yè)面展示。

根據(jù)業(yè)務(wù)需求,將ChatRecord可能接收到的數(shù)據(jù)分為以下幾類:

發(fā)送方為自己:

文本輸入,顯示文本

實(shí)現(xiàn)簡(jiǎn)單,不做贅述。

語(yǔ)音輸入 Loading狀態(tài),顯示波紋動(dòng)畫和計(jì)時(shí)

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

該動(dòng)畫使用CSS實(shí)現(xiàn),參考地址: https://www.cnblogs.com/lhb25/p/loading-spinners-animated-with-css3.html

計(jì)時(shí)器使用JS的setInterval方法,每100ms更新一次錄制時(shí)長(zhǎng)

this.recordTimer = setInterval(() => { this.audioDuration = this.audioDuration + 0.1 }, 100)

停止后清空計(jì)時(shí)器:

語(yǔ)音輸入完畢,根據(jù)錄制的語(yǔ)音,繪制波紋

效果:

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

使用wavesurfer插件:

initWaveSurfer() { this.$nextTick(() => { this.wavesurfer = WaveSurfer.create({ container: this.$refs.waveform, height: 20, waveColor: ’#3d6fff’, progressColor: ’blue’, backend: ’MediaElement’, mediaControls: false, audioRate: ’1’, fillParent: false, maxCanvasWidth: 500, barWidth: 1, barGap: 2, barHeight: 5, barMinHeight: 3, normalize: true, cursorColor: ’#409EFF’ }) this.convertAudioToUrl(this.waveAudio).then((res) => { this.wavesurfer.load(res) setTimeout(() => { this.audioDuration = this.getAudioDuration() }, 100) }) }) }, // 將音頻轉(zhuǎn)化成url地址 convertAudioToUrl(audio) { let blobUrl = ’’ if (this.data.sendBy === ’self’) { blobUrl = window.URL.createObjectURL(audio) return new Promise((resolve) => { resolve(blobUrl) }) } else { return this.base64ToBlob({ b64data: audio, contentType: ’audio/wav’ }) } }, base64ToBlob({ b64data = ’’, contentType = ’’, sliceSize = 512 } = {}) { return new Promise((resolve, reject) => { // 使用 atob() 方法將數(shù)據(jù)解碼 let byteCharacters = atob(b64data) let byteArrays = [] for ( let offset = 0; offset < byteCharacters.length; offset += sliceSize ) { let slice = byteCharacters.slice(offset, offset + sliceSize) let byteNumbers = [] for (let i = 0; i < slice.length; i++) { byteNumbers.push(slice.charCodeAt(i)) } // 8 位無(wú)符號(hào)整數(shù)值的類型化數(shù)組。內(nèi)容將初始化為 0。 // 如果無(wú)法分配請(qǐng)求數(shù)目的字節(jié),則將引發(fā)異常。 byteArrays.push(new Uint8Array(byteNumbers)) } let result = new Blob(byteArrays, { type: contentType }) result = Object.assign(result, { // 這里一定要處理一下 URL.createObjectURL preview: URL.createObjectURL(result), name: `XXX.wav` }) resolve(window.URL.createObjectURL(result)) }) },

發(fā)送方為系統(tǒng):

僅返回文本:顯示文本 僅返回音頻(參考發(fā)送方為自己的實(shí)現(xiàn))

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

返回文本,隨即返回文本對(duì)應(yīng)的合成音頻,顯示文本和播放按鈕

Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例

頁(yè)面嵌入audio標(biāo)簽,將hidden設(shè)置為true使其不顯示:

<div class='audio-player'> <svg-icon v-if='!isPlaying' icon-class=’play’ @click='onClickAudioPlayer' /> <svg-icon v-else icon-class=’pause’ @click='onClickAudioPlayer' /> <audio :src='http://www.hdgsjgj.cn/bcjs/playAudioUrl' autostart='true' hidden='true' ref='audioPlayer' /> </div>

playAudioUrl的生成參考上面生成的wavesurfer的url。使用isPlaying參數(shù)記錄當(dāng)前音頻的播放狀態(tài),并使用setTimeout方法,當(dāng)播放了音頻時(shí)長(zhǎng)后,將播放按鈕自動(dòng)置為play。

onClickAudioPlayer() { if (this.isPlaying) { this.$refs.audioPlayer.pause() this.isPlaying = false } else { // 每次點(diǎn)擊時(shí),開(kāi)始播放,并在播放完畢將isPlaying置為false this.$refs.audioPlayer.currentTime = 0 this.$refs.audioPlayer.play() this.isPlaying = true setTimeout(() => { // 將正在播放重置為false this.isPlaying = false }, Math.ceil(this.$refs.audioPlayer.duration) * 1000) } },

聊天記錄自動(dòng)定位到最后一條:

使用scrollIntoView()方法

記錄每次會(huì)話對(duì)應(yīng)的記錄ID(recordId):

定義單次會(huì)話的id,并在返回的消息中回傳,從而建立多條websocket返回的關(guān)聯(lián)關(guān)系。

以上就是全部實(shí)現(xiàn)。難點(diǎn)主要是請(qǐng)求麥克風(fēng)權(quán)限和對(duì)音頻進(jìn)行編碼,在加wav頭時(shí)必須保證和采樣時(shí)的采樣率、頻率一致 。

以上就是Vue +WebSocket + WaveSurferJS 實(shí)現(xiàn)H5聊天對(duì)話交互的實(shí)例的詳細(xì)內(nèi)容,更多關(guān)于vue 實(shí)現(xiàn)H5聊天對(duì)話交互的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 流程管理|流程管理软件|企业流程管理|微宏科技-AlphaFlow_流程管理系统软件服务商 | 浙江红酒库-冰雕库-气调库-茶叶库安装-医药疫苗冷库-食品物流恒温恒湿车间-杭州领顺实业有限公司 | 云南成考网_云南成人高考报名网 粤丰硕水性环氧地坪漆-防静电自流平厂家-环保地坪涂料代理 | 垃圾处理设备_餐厨垃圾处理设备_厨余垃圾处理设备_果蔬垃圾处理设备-深圳市三盛环保科技有限公司 | 超声波清洗机_细胞破碎仪_实验室超声仪器_恒温水浴-广东洁盟深那仪器 | 数码听觉统合训练系统-儿童感觉-早期言语评估与训练系统-北京鑫泰盛世科技发展有限公司 | 蓝鹏测控平台 - 智慧车间系统 - 车间生产数据采集与分析系统 | 上海刑事律师|刑事辩护律师|专业刑事犯罪辩护律师免费咨询-[尤辰荣]金牌上海刑事律师团队 | 厂房出售_厂房仓库出租_写字楼招租_土地出售-中苣招商网-中苣招商网 | 超声波清洗机-超声波清洗设备定制生产厂家 - 深圳市冠博科技实业有限公司 | 建筑资质代办_工程施工资质办理_资质代办公司_北京众聚企服 | 镀锌角钢_槽钢_扁钢_圆钢_方矩管厂家_镀锌花纹板-海邦钢铁(天津)有限公司 | 插针变压器-家用电器变压器-工业空调变压器-CD型电抗器-余姚市中驰电器有限公司 | 电磁流量计厂家_涡街流量计厂家_热式气体流量计-青天伟业仪器仪表有限公司 | 北京森语科技有限公司-模型制作专家-展览展示-沙盘模型设计制作-多媒体模型软硬件开发-三维地理信息交互沙盘 | 气弹簧定制-气动杆-可控气弹簧-不锈钢阻尼器-工业气弹簧-可调节气弹簧厂家-常州巨腾气弹簧供应商 | 知名电动蝶阀,电动球阀,气动蝶阀,气动球阀生产厂家|价格透明-【固菲阀门官网】 | 皮带式输送机械|链板式输送机|不锈钢输送机|网带输送机械设备——青岛鸿儒机械有限公司 | 「钾冰晶石」氟铝酸钾_冰晶石_氟铝酸钠「价格用途」-亚铝氟化物厂家 | 玉米深加工设备|玉米加工机械|玉米加工设备|玉米深加工机械-河南成立粮油机械有限公司 | 南京和瑞包装有限公司| 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | 贵州水玻璃_-贵阳花溪闽兴水玻璃厂 | 无锡市珂妮日用化妆品有限公司|珂妮日化官网|洗手液厂家 | 齿轮减速机电机一体机_齿轮减速箱加电机一体化-德国BOSERL蜗轮蜗杆减速机电机生产厂家 | 广东护栏厂家-广州护栏网厂家-广东省安麦斯交通设施有限公司 | 安全,主动,被动,柔性,山体滑坡,sns,钢丝绳,边坡,防护网,护栏网,围栏,栏杆,栅栏,厂家 - 护栏网防护网生产厂家 | 杭州代理记账多少钱-注册公司代办-公司注销流程及费用-杭州福道财务管理咨询有限公司 | 轴流风机-鼓风机-离心风机-散热风扇-罩极电机,生产厂家-首肯电子 | 茅茅虫AI论文写作助手-免费AIGC论文查重_写毕业论文降重 | 南京蜂窝纸箱_南京木托盘_南京纸托盘-南京博恒包装有限公司 | 聚氨酯保温钢管_聚氨酯直埋保温管道_聚氨酯发泡保温管厂家-沧州万荣防腐保温管道有限公司 | 环讯传媒,永康网络公司,永康网站建设,永康小程序开发制作,永康网站制作,武义网页设计,金华地区网站SEO优化推广 - 永康市环讯电子商务有限公司 | 合肥升降机-合肥升降货梯-安徽升降平台「厂家直销」-安徽鼎升自动化科技有限公司 | 合肥网络推广_合肥SEO网站优化-安徽沃龙First | 郑州水质检测中心_井水检测_河南废气检测_河南中环嘉创检测 | 聚氨酯催化剂K15,延迟催化剂SA-1,叔胺延迟催化剂,DBU,二甲基哌嗪,催化剂TMR-2,-聚氨酯催化剂生产厂家 | 【化妆品备案】进口化妆品备案流程-深圳美尚美化妆品有限公司 | 换链神器官网-友情链接交换、购买交易于一体的站长平台 | 超细粉碎机|超微气流磨|气流分级机|粉体改性设备|超微粉碎设备-山东埃尔派粉碎机厂家 | 地图标注-手机导航电子地图如何标注-房地产商场地图标记【DiTuBiaoZhu.net】 |