vue3 ant ts 集成wavesurfer

实现功能有:音词同步,倍速播放,拖拽播放,快进\退 ,重播,显示总 时长,关闭页面时关闭声音等功能

package.json 引入 "wavesurfer.js": "^7.7.14",

父页面引入自己封的 MyWaveSurfer.vue

 <!--    waveSrc 录音地址参数 --><WaveSurfer :waveSrc="model['fsFilepath']"></WaveSurfer><script lang="ts" setup>import WaveSurfer from "@/views/recordCdr/MyWaveSurfer.vue";

MyWaveSurfer.vue

<template><a-card><Spin :tip="null" :spinning="loadLoading"><div :class="`wave-surfer`"  id="waveform" ></div><!-- <div id="wave-timeline" ref="wave-timeline" style="height: 0px;"> --><!--时间轴 --></div></Spin></a-card><a-card style="height: 62px"><div style="float: left;" v-if="playMs"><div style=";float: left">播放:&nbsp;&nbsp;</div><Icon icon="ant-design:play-circle-outlined"  title="播放" class="playIcon" style="font-size: 32px;color: #2e9aff"   @click="playMusic()"> </Icon></div><div style="float: left;" v-if="!playMs"><div style="float: left">暂停:&nbsp;&nbsp;</div><Icon icon="ant-design:pause-circle-outlined" title="暂停"    style="font-size: 30px;color: #2e9aff" @click="downMusic()"></Icon></div><div style="float: left;margin-left: 5%;"> 倍速:&nbsp;&nbsp;<a-select style="width: 90px;" :disabled="false" v-model:value="speedValue"  @change="speedClick"><a-select-option   value="1">1.0px</a-select-option><a-select-option v-for="item in options" :key="item.value"  :value="item.value">{{ item.text }}</a-select-option></a-select></div><div style="float: left;margin-left: 5%;"><Icon icon="ant-design:notification-filled" title="声音"     style="float: left;font-size: 29px;;color: #2e9aff" @click="downMusic()"></Icon><a-slider style="float: left;width: 200px"  v-model:value="voiceValue"   @afterChange="setVolume"  /></div><div style="float: left;margin-left: 5%;"><div style="float: left;margin-top: 2px">快退/快进 :&nbsp;&nbsp;</div><Icon icon="ant-design:fast-backward-filled" title="快退"     style="float: left;font-size: 29px;;color: #2e9aff" @click="rew()"></Icon><div style="float: left;margin-top: 2px"> &nbsp;&nbsp;--&nbsp;&nbsp;</div><Icon icon="ant-design:fast-forward-filled" title="快进"     style="float: left;font-size: 29px;;color: #2e9aff" @click="speed()"></Icon></div><div style="float: left;margin-left: 5%;"><div style="float: left;margin-top: 2px">重播 :&nbsp;&nbsp;</div><Icon icon="ant-design:reload-outlined" title="重播"     style="float: left;font-size: 25px;color: #2e9aff" @click="replay()"></Icon></div><div style="float: left;margin-left: 5%;">总时长:&nbsp;&nbsp;<span style="color:#2e9aff">{{totalTime}}</span> 秒</div></a-card><div style="width:100%"><a-card style="width: 49%;float: left;height: 500px;overflow-y: auto"><div id="speech_feature"      ref="myDiv"><div v-for="(line, index) in lyrics" class="myTextClass"><p v-if="line.user_type == 'agent'" :id="Math.round(line.begin_time/100)" class="blueColor"  style="text-align:left;"><Icon icon="ant-design:customer-service-filled" title="座席"     style="float: left;font-size: 22px;color: #707fe3"  ></Icon>:{{ line.res }}</p><p v-else  style="text-align:right" :id="Math.round(line.begin_time/100)" class="blueColor">{{line.res}} :<Icon icon="ant-design:message-filled" title="客户"     style="float: right;font-size: 22px;color: #707fe3"  ></Icon></p></div></div></a-card><a-card style="width: 49%;float: left;height: 500px"><a-tabs v-model:activeKey="activeKey"><a-tab-pane key="1" tab="Tab 1">Content of Tab Pane 1</a-tab-pane><a-tab-pane key="2" tab="Tab 2" force-render>Content of Tab Pane 2</a-tab-pane><a-tab-pane key="3" tab="Tab 3">Content of Tab Pane 3</a-tab-pane></a-tabs></a-card></div></template>
<script lang="ts">
import { Spin } from 'ant-design-vue';
import {defineComponent, toRefs, ref, onMounted,onUnmounted, nextTick,} from 'vue';
import { getUploadFileAccessHttpUrl } from '/@/utils/common/compUtils';
import Icon from '/@/components/Icon';import WaveSurfer from '@/ext_node_modules/wavesurfer.js/dist/wavesurfer'/*import CursorPlugin from '@/ext_node_modules/wavesurfer.js/dist/plugin/wavesurfer.cursor.js'
import Timeline from '@/ext_node_modules/wavesurfer.js/dist/plugin/wavesurfer.timeline.js'
import Regions from '@/ext_node_modules/wavesurfer.js/dist/plugin/wavesurfer.regions.js'*/import _default from "ant-design-vue/es/vc-slick/inner-slider";
import DictItemList from "@/views/system/dict/components/DictItemList.vue";export default defineComponent({name: 'WaveSurfer',components: {DictItemList, Icon, Spin },props: {waveSrc: {type: String,// default: '../../../src/assets/images/test.mp3',},index: {type: Number,},},setup(props) {const myDiv = ref(null);const activeKey = ref('1');let totalTime = ref<number>(0);const voiceValue = ref<number>(30);const playMs = ref(true);const { waveSrc } = toRefs(props);const icon = ref('icon-bofang');let wavesurfer = [];const loadLoading = ref(false);const speedValue = ref(1);const options = ref([{ value: 1.0, text: '1.0X' },{ value: 1.25, text: '1.25X' },{ value: 1.5, text: '1.5X' },{ value: 1.75, text: '1.75X' },{ value: 2.0, text: '2.0X' },])const lyrics = ref([{"res": ["有什么可以帮您?"],"end_time": 7700,"begin_time": 5900,"words_info": [],"sn": "96541708621716291667","corpus_no": "7371416581381329804","user_type": "agent"}, {"res": ["我客户想把那个会员号变更一下可以吗?"],"end_time": 17700,"begin_time": 8340,"words_info": [],"sn": "92604005381716291667","corpus_no": "7371416580911366314","user_type": "cust"}, {"res": ["嗯,可以的,还是需要给顾客自己近先联系我们。"],"end_time": 18860,"begin_time": 17000,"words_info": [],"sn": "92604005381716291667","corpus_no": "7371416580911366314","user_type": "agent"}, {"res": ["如果变更成别的号码,这个等级还在吗?"],"end_time": 19860,"begin_time":18860 ,"words_info": [],"sn": "381723455751716291667","corpus_no": "7371416581432964228","user_type": "cust"}, {"res": ["您您放心,会保留他的一个等级和这个积分的。"],"end_time": 28020,"begin_time": 26060,"words_info": [],"sn": "381723455751716291667","corpus_no": "7371416581432964228","user_type": "agent"}, {"res": ["好累,好让我让他打电话过来哈,"],"end_time": 42280,"begin_time": 33880,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "cust"}, {"res": ["请问下,可以帮您的吗?"],"end_time": 42280,"begin_time": 36880,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "agent"}, {"res": ["啊没有了,谢谢啊,我让他打过来,"],"end_time": 40280,"begin_time": 39880,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "cust"}, {"res": ["祝您生活愉快,再见,"],"end_time": 40280,"begin_time": 40000,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "agent"}, {"res": ["好的"],"end_time": 40280,"begin_time": 40080,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "cust"}, {"res": ["祝您生活愉快,再见,"],"end_time": 40280,"begin_time": 40500,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "agent"}, {"res": ["好的"],"end_time": 40280,"begin_time": 40800,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "cust"}, {"res": ["祝您生活愉快,再见,"],"end_time": 40280,"begin_time": 41000,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "agent"}, {"res": ["好的"],"end_time": 40280,"begin_time": 41200,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "cust"}, {"res": ["祝您生活愉快,再见,"],"end_time": 40280,"begin_time": 41400,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "agent"}, {"res": ["。。。。,"],"end_time": 40280,"begin_time": 41600,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "cust"}, {"res": ["祝您生活愉快,再见,"],"end_time": 40280,"begin_time": 41800,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "agent"}, {"res": ["。。。。。"],"end_time": 40280,"begin_time": 41900,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "cust"}, {"res": ["祝您生活愉快,再见,"],"end_time": 40280,"begin_time": 42200,"words_info": [],"sn": "912755075221716291667","corpus_no": "7371416581565561738","user_type": "agent"}])//点击倍速播放function speedClick() {console.info(speedValue.value)// console.log("fieldValue===============",fieldValue);playMusic();}//生成wavesurferfunction render( selector, url) {loadLoading.value = true;var domEl = document.createElement('div');document.querySelector(selector).appendChild(domEl);wavesurfer = WaveSurfer.create({container: domEl,waveColor: 'rgb(57 171 132)',progressColor: '#e0820e',cursorColor: 'rgb(57 171 132)',abnormalvolume:{"1":"violet"},/* plugins: [CursorPlugin.create({showTime: true,opacity: 0.2,customShowTimeStyle: {'background-color': '#000',color: '#fff',padding: '2px','font-size': '20px'}}),Timeline.create({container: '#wave-timeline'}),Regions.create()]*/});// url="../../../src/assets/images/test.mp3";wavesurfer.load(url);//获取当前播放进度的时间点wavesurfer.on('audioprocess', (time) => {//console.log("======time======",time)// 根据当前音频播放进度 time 来同步显示歌词Math.round(line.begin_time/100)const currentLine =Math.round(time*10) ; // 假设每行歌词对应的时间间隔为 10 秒//console.log("======currentLine======",currentLine)var mytextId=document.getElementById(currentLine);changeBackground(time);if(mytextId!=undefined){mytextId.className= "redColor";setTimeout(function(){mytextId.scrollIntoView({ behavior: "smooth", block: 'center' }); //0.1秒滑动到指定位置*},100);}});//拖拽进度条播放wavesurfer.on('seek', function () {playMusic();});wavesurfer.on('error', function (e) {console.warn(e);});//加载后事件wavesurfer.on('ready', function () {loadLoading.value = false;totalTime.value = wavesurfer.getDuration();console.log('音频总时长:', totalTime, '秒');});return wavesurfer;}//组件加载时加载录音onMounted(() => {setTimeout(()=>{if(waveSrc.value!=undefined){const fileAccessHttpUrl= getUploadFileAccessHttpUrl(waveSrc.value)nextTick(() => {render( '.wave-surfer' , fileAccessHttpUrl);});}},100)});//页面关闭时,组件关闭, 关闭录音onUnmounted(()=>{console.info( '组件关闭时 关闭录音====')wavesurfer.stop() ; //停止wavesurfer.destroy();//销毁})//设置音量大小function setVolume(val) {wavesurfer.setVolume(val / 100);//console.log(val)}//根据播放进度改编已播放的字体样式function changeBackground(nowTime) {nowTime=Math.round(nowTime*10)const elements = document.querySelectorAll('.myTextClass > *');elements.forEach(element => {if(element.id>nowTime){element.className="blueColor";}else{element.className="redColor";}});}//暂停function downMusic() {playMs.value = true;icon.value = 'icon-bofang';wavesurfer.playPause();}//播放function playMusic() {playMs.value = false;icon.value = 'icon-bofang';wavesurfer.setPlaybackRate(speedValue.value)wavesurfer.play();}// 回退function  rew() {wavesurfer.skip(-3);goPlay();}// 快进function  speed() {wavesurfer.skip(3);goPlay();}function goPlay() {let start = wavesurfer.getCurrentTime();wavesurfer.play(start);}// 重载function replay() {wavesurfer.stop();wavesurfer.clearRegions();wavesurfer.play(0);}return {  playMusic, icon, loadLoading,playMs,speedClick,speedValue,options,downMusic,totalTime,setVolume,voiceValue,lyrics,changeBackground,myDiv,speed,rew ,replay,activeKey};},
});
</script>
<style lang="less">
.playIcon {line-height: 36px;margin-right: 8px;cursor: pointer;
}
.waveform {}
.redColor {color: #d96f00;;
}
.blueColor {color: #292a2f;
}</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/16250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

将推荐算法应用到llm上之comi_rec_sa

参考地址 https://aistudio.baidu.com/projectdetail/7943516 数据生成 import pandas as pd import numpy as npimport json import numpy as np with open("唐诗.json","r",encoding="utf-8") as f:data

深度讲解Spring Bean扫描类:源码深度剖析与实战策略

1. 引言 在Spring框架中&#xff0c;Bean的扫描是一个至关重要的过程&#xff0c;它决定了哪些类会被Spring容器管理并作为Bean实例化。对于高级Java工程师而言&#xff0c;深入理解这一过程不仅有助于提升对Spring框架的掌握程度&#xff0c;还能在实际开发中更加灵活地运用S…

归并排序算法(经典、常见)

今天我们不刷力扣了&#xff0c;我们来复习&#xff08;手撕&#xff09;一下数据结构中的八大排序算法之一&#xff0c;归并排序 基本概念&#xff1a; 归并排序&#xff08;Merge sort&#xff09;是建立在归并操作上的一种有效的排序算法&#xff0c;该算法是采用分治法&am…

SpringBoot中如何在服务器进行校验?

数据校验就是数据的合法性检查&#xff0c;在服务器端也可以对数据进行校验&#xff0c;一般使用JSR303 校验 JSR303是Java为Bean数据合法性校验提供的标准框架&#xff0c;是一种声明式校验 JSR303通过在Bean属性上标注类似于NotNull、Max等注解来指定校验规则&#xff0c;并…

小苯的排列构造(最大公约数,构造,数学推导)

文章目录 题目描述输入格式输出格式样例输入1样例输出1提交链接提示 解析参考代码 题目描述 格格有一个长度为 n n n 的排列 p p p&#xff0c;但她不记得 p p p 具体的样子&#xff0c;她只记得数组 a a a。 其中&#xff1a; a i g c d ( p 1 , p 2 , . . . , p i ) a…

【网络技术】【Kali Linux】Wireshark嗅探(十五)SSDP(简单服务发现协议)报文捕获及分析

往期 Kali Linux 上的 Wireshark 嗅探实验见博客&#xff1a; 【网络技术】【Kali Linux】Wireshark嗅探&#xff08;一&#xff09;ping 和 ICMP 【网络技术】【Kali Linux】Wireshark嗅探&#xff08;二&#xff09;TCP 协议 【网络技术】【Kali Linux】Wireshark嗅探&…

与MySQL DDL 对比分析OceanBase DDL的实现

本文将简要介绍OceanBase的DDL实现方式&#xff0c;并通过与MySQL DDL实现的对比&#xff0c;帮助大家更加容易理解。 MySQL DDL 的算法 MySQL 的DDL实现算法主要有 copy、inplace和instant。 copy copy算法的实现相对简单&#xff0c;MySQL首先会创建一个临时表&#xff0…

C++:STL

STL 文章目录 STLSTL 绪论迭代器&#xff08;iterators&#xff09;容器&#xff08;Containers&#xff09;vectorset,multisetmap,multimapstackqueuedequepriority_queuebitset 算法&#xff08;Algorithms&#xff09;sort,count,find,lower_bound,upper_bound,binary_sear…

(2024,attention,可并行计算的 RNN,并行前缀扫描)将注意力当作 RNN

Attention as an RNN 公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 3. 方法 3.1 注意力作为一种&#xff08;多对一的&#xff09;RNN 3.2 注意力作为&#xff08;多对多&…

多语言印度红绿灯系统源码带三级分销代理功能

前端为2套UI&#xff0c;一套是html写的&#xff0c;一套是编译后的前端 后台功能很完善&#xff0c;带预设、首充返佣、三级分销机制、代理功能。 东西很简单&#xff0c;首页就是红绿灯的下注页面&#xff0c;玩法虽然单一&#xff0c;好在不残缺可以正常跑。

Putty: 随心御剑——远程启动服务工具plink

一、引言:如何远程控制 也许你会有这样的场景,交互程序(以下简称UI程序)跑在windows端,而控制程序跑在Linux上。我们想要通过windows端 UI程序来启动Linux下面的服务,来一场酣畅淋漓的御剑飞行咋办,难道要自己十年磨一剑,在Linux下编写一个受控服务程序么.计算机科技发…

【MATLAB】信号的熵

近似熵、样本熵、模糊熵、排列熵|、功率谱熵、奇异谱熵、能量熵、包络熵 代码内容&#xff1a; 获取代码请关注MATLAB科研小白的个人公众号&#xff08;即文章下方二维码&#xff09;&#xff0c;并回复信号的熵本公众号致力于解决找代码难&#xff0c;写代码怵。各位有什么急需…

FreeRTOS中断中释放信号量

串口接收&#xff1a;中断程序中逆序打印字符串 串口接收&#xff1a;逆序回环实验思路 注&#xff1a;任务优先级较高会自动的切换上下文进行运行 FreeRTOS中的顶半操作和底半操作 顶半操作和底半操作“这种叫法源自与Linux”在嵌入式开发中&#xff0c;为了和Linux操作系统做…

kafka 案例

kafka 案例 目录概述需求&#xff1a; 设计思路实现思路分析1.kafka案例_API 带回调函数的生产者2.kafka案例_API生产者分区策略测试3.kafka案例_自定义分区的生产者4.kafka案例_API同步发送生产者5.kafka案例_API简单消费者5.kafka案例_API消费者重置offset 参考资料和推荐阅读…

Linux网络编程: 网络基础

Linux网络编程: 网络基础 1.网络划分 一.网络通信1.网络通信和本地通信的联系2.网络通信与本地通信最本质的区别及其衍生出的问题 二.网络协议初识1.为何本地通信不行&#xff1f;2.打电话的例子体会分层模型的好处3.OSI七层模型的提出4.OSI七层模型与TCP/IP五层模型1.TCP/IP与…

二十九篇:构建未来:信息系统的核心框架与应用

构建未来&#xff1a;信息系统的核心框架与应用 1. 引言 在这个充满挑战和机遇的信息时代&#xff0c;信息系统已经成为现代组织不可或缺的神经中枢。它们不仅革新了我们处理信息的方式&#xff0c;更是极大地增强了决策制定的效率和质量。在这篇文章中&#xff0c;我将分享我…

php 一个数组中的元素是否在一个字符串中包含

php 一个数组中的元素是否在一个字符串中包含 要检查一个数组中的元素是否在一个字符串中出现&#xff0c;你可以使用strpos()函数。这个函数返回子字符串首次出现的位置索引&#xff0c;如果没有找到&#xff0c;它会返回false。 $array [apple, banana, cherry]; $string …

Java进阶-SpringCloud使用BeanUtil工具类简化对象之间的属性复制和操作

在Java编程中&#xff0c;BeanUtil工具类是一种强大且便捷的工具&#xff0c;用于简化对象之间的属性复制和操作。本文将介绍BeanUtil的基本功能&#xff0c;通过详细的代码示例展示其应用&#xff0c;并与其他类似工具进行对比。本文还将探讨BeanUtil在实际开发中的优势和使用…

有效的字母异位词-力扣

看到题目首先想到的解法是使用unordered_map容器来做&#xff0c;遍历第一个字符串&#xff0c;统计每个char出现的次数&#xff0c;然后遍历第二个字符串&#xff0c;出现一个char&#xff0c;map对应值就减一&#xff0c;最后判断map容器所有键值是否为0&#xff0c;如果全部…

5.26牛客循环结构

1002. 难点&#xff1a; 两层循环条件设置 思路 可以设置三个变量 代码 1003 思路&#xff1a; 与星号双塔差不多&#xff0c;在此基础上加大一点难度 每日练题5.23 &#xff08;EOF用法&#xff09;-CSDN博客 代码 1004 代码