Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get video element's current level of loudness

I do know how to set or get the volume in common sense. Like you set the upper total volume. So if sounds were loud and you lower the volume the volume of the whole clip is shrunk, so loud sounds become quieter and already quite sounds go even below.

I am trying to make animation where, canvas, circle's size changes depending on a volume of video, audio, or microphone, and not based on total volume. I am not making a volume meter.

so basically a sound visualizer for video element.

However, i can't find a property of video element. It's like i can't find the right words, current loudness?!

Links that are helpful:

http://jcla1.com/blog/2012/03/11/web-audio-api-overview-part1/

https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AnalyserNode-section

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays

http://www.html5rocks.com/en/tutorials/webaudio/intro/

http://chimera.labs.oreilly.com/books/1234000001552/index.html

http://webaudioapi.com/samples/

After lots of tries and help form links i have made this...however loudness seem to be at full most of the time not sure if that is true.

http://jsfiddle.net/d4Xqm/10/

http://jsfiddle.net/techsin/d4Xqm/19/

http://jsfiddle.net/techsin/d4Xqm/18/

var v= document.getElementById('v'),
    ctx= new webkitAudioContext(),
    src= ctx.createMediaElementSource(v),
    alyz= ctx.createAnalyser(),
    arr= null, l=0, i=0,
    t=true, p=$('.l');


v.addEventListener('play',update);
v.addEventListener('ended',function(){t=false;});

src.connect(alyz);
alyz.connect(ctx.destination);
arr= new Uint8Array(alyz.frequencyBinCount);

function update(){
    if(t) requestAnimationFrame(update);
    alyz.getByteFrequencyData(arr);
    l=0;
    for(i=0; i<arr.length;i++) { l= (l<arr[i])?arr[i]:l; }
    p.text(l);
}
like image 214
Muhammad Umer Avatar asked Dec 25 '13 05:12

Muhammad Umer


1 Answers

What I understand is that you want to make a vu meter, but with circles instead of bars. What you would first need to do is get the average volume of all frequencys from the analyser. Then just use that value as the radius to draw a circle.

I made a jsfiddle for you with the code and explaining comments. To get the average:

var array = new Uint8Array(analyser.fftSize);
analyser.getByteTimeDomainData(array);
var average = 0;
var max = 0;
for (var a of array) {
    a = Math.abs(a - 128);
    average += a;
    max = Math.max(max, a);
}

average /= array.length;

Hope this helps!

like image 187
MarijnS95 Avatar answered Nov 16 '22 19:11

MarijnS95