给Jplayer加上声音可视化效果_2byte的博客-程序员秘密

技术标签: HTML5  

前一阵子有个网友通过之前写的一篇音频可视化的文章找到我,让我帮忙给他的音乐网站加个播放效果,自己正好没啥事做欣然答应。

由于疏于学习,基础掌握的不好,我一直以为音频可视化是通过Web audio API实现的,脑子不会转弯,总觉得只能通过这种方法载入音频:

	var audio = new Audio("hello.mp4");

然后打一套API的组合拳来读取音频数据:

	AudioContext = AudioContext || webkitAudioContext;
	context = new AudioContext;
	//加载媒体
	
	//创建节点
	source = context.createMediaElementSource(audio);
	analyser = context.createAnalyser();
	//连接:source → analyser → destination
	source.connect(analyser);
	analyser.connect(context.destination);

直到看到另一个使用Jplayer的网站才恍然大悟,完全可以获取页面上已有的audio控件来载入音频:

var audio= document.getElementById('audio');

source = context.createMediaElementSource(audio);

下面以JYMUSIC这套程序为例,写一下大概实现原理。

先在\resources\web\default\home目录的player_default.html里面加一个canvas层:

<canvas id="canvas" width="500" height="350"></canvas>

然后找到\resources\web\default\assets\js目录下面的player.js,加入如下代码:


    /*音频可视化*/
    function initVisualizer(){
    
        window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext||window.oAudioContext;
        var player = document.getElementById('jp_audio_0');
        try {
    
            var audioContext = new window.AudioContext();
        } catch (e) {
    
            alert('你的浏览器不支持AudioContext。错误:'+e);
        }
        playerAnalyser = audioContext.createAnalyser();
        playerSource = audioContext.createMediaElementSource(player);
        canvas = document.getElementById('canvas');
        context = canvas.getContext('2d');
        capStyle = 'rgba(0,255,0,.6)';//频谱颜色
        CANVAS_WIDTH = canvas.clientWidth;
        CANVAS_HEIGHT = canvas.clientHeight;
        cheight = canvas.height - 2;
        
        capYPositionArray = [];
        //以上为变量
        playerAnalyser.connect(audioContext.destination);//声音连接到扬声器
        playerSource.connect(playerAnalyser);//截取音频信号

        playerFrequencyData = new Uint8Array(playerAnalyser.frequencyBinCount);//得到音频能量值
        
        var gradient,topXy,capHeight=2;
        var meterWidth = 8, //能量条的宽度
        gap = 4, //能量条间的间距
        steplength = meterWidth + gap,
        meterNum = CANVAS_WIDTH / steplength; //计算当前画布上能画多少条

        process();


        function process() {
    
playerAnalyser.getByteFrequencyData(playerFrequencyData);//得到音频能量值
playerTimeDomainData = new Uint8Array(playerAnalyser.fftSize);
requestAnimationFrame(process)
context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
        var step = Math.floor((playerFrequencyData.length-200)/ meterNum); //计算从analyser中的采样步
        context.beginPath();
        for (var i = 0; i < meterNum; i++) {
    
            var value = playerFrequencyData[i * step];
            topXy = cheight - value;
            if(topXy==cheight){
    
                continue;
            }
            if (capYPositionArray.length < Math.round(meterNum)) {
    
                capYPositionArray.push(topXy); //初始化保存帽头位置的数组,将第一个画面的数据压入其中
            };
            context.fillStyle = "#fff";
            
            //定义一个渐变样式用于画图
            gradient = context.createLinearGradient(i * steplength , topXy+capHeight, i * steplength, cheight);
            gradient.addColorStop(0, 'rgba(255,0,0,.7)');
            gradient.addColorStop(1, 'rgba(61,247,0,.5)');
            context.fillStyle=gradient;
            context.fillRect(i * 12 , topXy+capHeight, meterWidth, cheight);
        }
        context.closePath();
    }
}

最终自己添加一下CSS就可以了,我用的是:

#canvas {
    
    position: absolute;
    bottom: 51px;
    left: 0;
    right: 0;
    margin: auto;
    transform: translateX(50%);
    box-reflect: left -2px;
    -moz-box-reflect: left -2px;
    -webkit-box-reflect: left 2px;
    -ms-box-reflect: left 2px;
    -o-box-reflect: left 2px;
    -moz-transform: rotateY(180deg);
    -o-transform: rotateY(180deg);
    pointer-events: none;
}

效果如图:
示例

至于代码逻辑,可以看我前一篇文章的分析。
帮这位朋友加上效果还得到了一大笔打赏,实在是受宠若惊,这也是第一次通过博客内容收到打赏,坚定了我分享一些觉得还有用的东西的决心。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/twoByte/article/details/90266194

智能推荐

搭建个人博客的几种方案 •_CLiuso的博客-程序员秘密

1、Git+Github+Markdown+jekyll(免费) 2、Git+Github+Markdown+hexo(免费) 3、虚拟主机+插件+Wordpress(付费)个人有个不成熟的小建议:如果你不想付费,也不想备案,那你基本上就已经确定了前面两种方案了,免费版走起。如果你是高富帅,或者要求较高又不想浪费多余精力在搭建博客上面,那强力推荐采用第三个方案。轻松加愉快,爽的飞起...

Linux虚拟机ip总是变_言必行 行必果的博客-程序员秘密

进入目录:cd /etc/sysconfig/network-scripts/编辑文件:vi ifcfg-eth0,改第一个红框为static,第二红框为自己想设定的静态ip重启:reboot再查看ip是否已设定成功:ifconfig 回车...

计算机控制技术名词解释,计算机控制技术复习题-20210521081113.doc-原创力文档_清风余欢的博客-程序员秘密

第 PAGE 4 页 共 NUMPAGES 4 页《计算机控制技术》复习题一、填空题1.根据计算机参与的形式分类,计算机控制系统分为 开环 、 闭环 。2.常用位移检测传感器包括 电涡流位移传感器、磁致伸缩、光栅、磁栅、差动变压器3.常用的PC总线包括:ISA总线、MCA微通道体系结构、EISA总线、PCI局部总线4.模拟量输出通道由哪几部分组成:多路模拟...

python人脸融合_课内资源 - 基于Face++的人脸融合及换脸系统_weixin_39968640的博客-程序员秘密

1.项目介绍在本项目中,我们实现了对人脸图片数据的三种处理:人脸互换(face swap)、人脸融合(face morph)以及基于特征向量的人脸处理(eigen face)。1.1 人脸互换(face swap)人脸互换部分主要实现的功能是,给定任意两张人脸图片,通过一系列操作,使两个人的脸部交换,这部分需要的问题有:不同的人的脸部结构千差万别,同一个人也会因为角度、面部表情的不同而导致差别,即...

UVA10603 Fill_weixin_34043301的博客-程序员秘密

优秀的程序员一定是CV大师。能CV则CV的做法,可以省去许多编码和测试的时间。但是,如果出现小错误的话,找起来一样的费时。问题链接:UVA10603 Fill。题意简述:有三个壶,容量分别是a、b和c升,开始时候第1个和第2个壶是空的,第3个壶是满水的。可以把一个壶的水倒入另一个壶中,直到倒空或将另外一个壶倒满。输入a、b、c和d,计算最少的倒水量,使得其...

2018年100个让程序员崩溃的瞬间!看到哪一个你哭了?_运维派V的博客-程序员秘密

“不知不觉中,2018 马上已经接近尾声了。当初信誓旦旦给自己立下的 flag 如今都实现了吗?这一年我们有太多的收获、太多的感慨、有悲欢也有离合。随着 2019 越来越...

随便推点

7.1-spring 动态 AOP_spring动态aop_sql2008help的博客-程序员秘密

spring 动态 AOPAOP(Aspect Oriented Programming) 即面向切面编程 ,不同于OOP(Object Oriented Programming) 面向对象编程,AOP关注的方向是横向的,而OOP关注的方向是纵向的,spring AOP是spring关键组件之一,它是AOP概念的具体实现方案,是对spring IOC 的补充,但是spring IOC不依赖spring AOP。spring AOP 使用场景Authentication 权限Caching 缓存

墨者学院-PHP文件下载漏洞分析溯源_墨者学院 文件下载_JimWu95的博客-程序员秘密

PHP文件下载漏洞分析溯源难易程度:★★题目类型:WEB安全使用工具:FireFox浏览器、burpsuite1.打开靶场,根据题目,下载一张图片,发现不用付费,但没什么发现。2.打开burpsuite,下载一张图片,截包。3.看到url为/execdownload.php?filename=kb.png,再根据题目提示,key就藏在根目录的txt文件中。4.send to repe...

数据结构与算法之------判断最小生成树是否唯一_最小生成树唯一的充要条件_markconca的博客的博客-程序员秘密

判断最小生成树是否唯一原文链接:http://www.cnblogs.com/wkfvawl/p/9845689.html我们知道在构造最小生成树的时候有可能会选择不同的边,这样构造的最小生成树不相同,但是最小生成树的权是唯一的!毫无疑问,无向图中存在相同权值的边是最小生成树不唯一的必要条件(但不是充分条件)。正因为如此,如果无向图中各边的权值都不相同,那么在用Kruskal算法构造最...

Elasticsearch——》kibana操作数据:查询、分页、排序、高亮_kibana 排序_小仙。的博客-程序员秘密

请参考:总结——》【Elasticsearch】Elasticsearch——》kibana操作索引:增删改查Elasticsearch——》kibana操作数据:增删改查

[转]想成为嵌入式程序员应知道的16个基本问题_weixin_33860528的博客-程序员秘密

这是嵌入式C程序员的基本知识。作者在Embedded Systems Programming杂志上发表了很多嵌入式系统开发方面的文章。  C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法。这些年,我既参加也组织了许多这种测试,在这过程中我意识到这些测试能为面试者和被面试者提供许多有用信息,此外,撇开面试的压力不谈,这种测试也是相当有趣的。  从被面试者的角度来讲,你能了解许多关于出题者...

原 mysql使用group by查询报错SELECT list is not in GROUP BY clause and contains nonaggregated column...解决方案_Java架构师Array的博客-程序员秘密

2019年06月19日 17:45:26爱学习的狮王阅读数 266收起所属专栏:mysql学习版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/study_in/article/details/92625397MySQL5.7.5后only_full_group_by成...

推荐文章

热门文章

相关标签