Play a moving waveform for wav audio file in html

前端 未结 1 1213
生来不讨喜
生来不讨喜 2020-12-31 13:04

How to create a moving waveform for a audio file/tag in HTML? When play button is clicked,the audio HTML element must be played and a corresponding moving waveform for the s

相关标签:
1条回答
  • 2020-12-31 13:16

    Same as below but then with canvasjs:

    Demo: http://seapip.com/canvas/visualizer4/

    /*
    Speed has to be bigger then refresh!!!
    */
    
    //Speed to move from right to left, also the visible amount of time on the x axis (in milliseconds)
    var speed = 10000;
    
    //Time in milliseconds to redraw chart
    var refresh = 30;
    
    //Without var to make it a global variable accessable by the html onclick attribute 
    audioElement = document.getElementById('audioElement');
    var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    var audioSrc = audioCtx.createMediaElementSource(audioElement);
    var analyser = audioCtx.createAnalyser();
    
    // Bind our analyser to the media element source.
    audioSrc.connect(analyser);
    audioSrc.connect(audioCtx.destination);
    
    //Get frequency data
    var frequencyData = new Uint8Array(analyser.frequencyBinCount);
    
    //The animation reference
    var animation;
    
    //Create chart
    var dps = []; // dataPoints
    var chart = new CanvasJS.Chart("chart", {
        interactivityEnabled: false,
        width: 500,
        height: 200,
        axisX: {
            title: "Time",
            valueFormatString: "mm:ss"
        },
        axisY: {
            title: "dB"
        },
        data: [{
            type: "line",
            dataPoints: dps
        }]
    });
    chart.render();
    
    //On play
    audioElement.onplay = function() {
        //Start drawing
        animation = setInterval(function() {
            drawWave();
        }, refresh);
    };
    
    //On pause
    audioElement.onpause = function() {
        //Stop drawing
        clearInterval(animation);
    };
    
    //On ended
    audioElement.onended = function() {
        //Stop drawing
        clearInterval(animation);
    
        //Reset time
        time = 0;
    
        //Reset dataPoints
        dps = [];
    
        //Prevent audio from looping (you can remove this if you want it to loop)
        audioElement.pause();
    };
    
    //Max dB
    var max = analyser.maxDecibels;
    
    //Min dB
    var min = analyser.minDecibels;
    
    //Time
    var time = 0;
    
    //Our drawing method
    function drawWave() {
    
        // Copy frequency data to frequencyData array.
        analyser.getByteFrequencyData(frequencyData);
    
        //Total loudness of all frequencies in frequencyData
        var totalLoudness = 0;
        for(var i = 0; i < frequencyData.length; i++) {
            totalLoudness += frequencyData[i];
        }
    
        //Average loudness of all frequencies in frequencyData on scale from 0 to 255
        var averageLoudness = totalLoudness / frequencyData.length / 255;
    
        //Decibels
        var decibels = min + averageLoudness * Math.abs(min - max);
    
        //Increase time
        time += refresh;
    
        //Add to chart
        dps.push({
            x: new Date(time),
            y: decibels
        });
    
        //Maximum x values to draw based on speed ad refresh
        if(dps.length > speed / refresh) {
            dps.shift();
        }
    
        //Draw new chart
        chart.render(); 
    }
    


    <audio id="audioElement" src="audio/Odesza - Above The Middle.mp3"></audio>
    <div id="chart"></div>
    <div>
      <button onclick="audioElement.play()">Play the Audio</button>
      <button onclick="audioElement.pause()">Pause the Audio</button>
      <button onclick="audioElement.volume+=0.1">Increase Volume</button>
      <button onclick="audioElement.volume-=0.1">Decrease Volume</button>
    </div>
    

    Keep in mind that #chart is a div instead of a canvas element, it took me a few minutes to find out why the chart wasn't showing at first :P




    Same as below but with plotting from right to left. The stepSize variable sets both the animation speed and the size of the steps, if you want bigger steps to be drawn in then it needs to move faster and if you want smaller steps to be drawn it needs to move slower.

    Demo: http://seapip.com/canvas/visualizer3

    //Step size (pixels per 20ms)
    var stepSize = 0.5;
    
    //Without var to make it a global variable accessable by the html onclick attribute 
    audioElement = document.getElementById('audioElement');
    var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    var audioSrc = audioCtx.createMediaElementSource(audioElement);
    var analyser = audioCtx.createAnalyser();
    
    // Bind our analyser to the media element source.
    audioSrc.connect(analyser);
    audioSrc.connect(audioCtx.destination);
    
    //Get frequency data (800 = max frequency)
    var frequencyData = new Uint8Array(400);
    //Use below to show all frequencies
    //var frequencyData = new Uint8Array(analyser.frequencyBinCount);
    
    //Create canvas
    var canvas = document.getElementById("wave");
    canvas.style.width = "500px";
    canvas.style.height = "100px";
    
    //High dpi stuff
    canvas.width = parseInt(canvas.style.width) * 2;
    canvas.height = parseInt(canvas.style.height) * 2;
    
    //Get canvas context
    var ctx = canvas.getContext("2d");
    
    //Stroke color
    ctx.strokeStyle = "#ffff00";
    
    //Draw thicker lines due to high dpi scaling
    ctx.lineWidth = 2;
    
    //Store y values
    var drawY = [canvas.height];
    
    //The animation reference
    var animation;
    
    //On play
    audioElement.onplay = function() {
        //Start drawing
        animation = setInterval(function() {
            drawWave();
        }, 20);
    };
    
    //On pause
    audioElement.onpause = function() {
        //Stop drawing
        clearInterval(animation);
    };
    
    //On ended
    audioElement.onended = function() {
        //Stop drawing
        clearInterval(animation);
    
        //Clear previous y values
        drawY = [canvas.height];
    
        //Prevent audio from looping (you can remove this if you want it to loop)
        audioElement.pause();
    };
    
    //Our drawing method
    function drawWave() {
    
        // Copy frequency data to frequencyData array.
        analyser.getByteFrequencyData(frequencyData);
    
        //Total loudness of all frequencies in frequencyData
        var totalLoudness = 0;
        for(var i = 0; i < frequencyData.length; i++) {
            totalLoudness += frequencyData[i];
        }
    
        //Average loudness of all frequencies in frequencyData
        var averageLoudness = totalLoudness / frequencyData.length;
    
        //Scale of average loudness from (0 to 1), frequency loudness scale is (0 to 255)
        var y = averageLoudness / 255;
        //Multiply with canvas height to get scale from (0 to canvas height)
        y *= canvas.height;
        //Since a canvas y axis is inverted from a normal y axis we have to flip it to get a normal y axis value
        y = canvas.height - y;
    
        //Store new y value
        drawY.push(y);
    
        //Clear previous drawing
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        //Draw line
        for(var i = drawY.length; i > 0; i--) {
    
            //calculate x values
            var x1 = canvas.width - (drawY.length - i - 1) * stepSize;
            var x2 = canvas.width - (drawY.length - i) * stepSize;
    
            //Stop drawing y values if the x value is outside the canvas
            if(!x2) {
                break;
            }
            ctx.beginPath();
            ctx.moveTo(x1, drawY[i - 1]);
            ctx.lineTo(x2, drawY[i]);
            ctx.stroke();
        }
    }
    


    <audio id="audioElement" src="audio/Odesza - Above The Middle.mp3"></audio>
    <canvas id="wave"></canvas>
    <div>
      <button onclick="audioElement.play()">Play the Audio</button>
      <button onclick="audioElement.pause()">Pause the Audio</button>
      <button onclick="audioElement.volume+=0.1">Increase Volume</button>
      <button onclick="audioElement.volume-=0.1">Decrease Volume</button>
    </div>
    




    Here's what I think you probably wanted, x axis is the time and y axis is the average loudness of all frequencies. Keep in mind that browsers like chrome don't draw the graph properly in a background tab because it limits the refresh interval and audio analyzer output.

    Demo: http://seapip.com/canvas/visualizer2

    //Without var to make it a global variable accessable by the html onclick attribute 
    audioElement = document.getElementById('audioElement');
    var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    var audioSrc = audioCtx.createMediaElementSource(audioElement);
    var analyser = audioCtx.createAnalyser();
    
    // Bind our analyser to the media element source.
    audioSrc.connect(analyser);
    audioSrc.connect(audioCtx.destination);
    
    //Get frequency data (800 = max frequency)
    var frequencyData = new Uint8Array(400);
    //Use below to show all frequencies
    //var frequencyData = new Uint8Array(analyser.frequencyBinCount);
    
    //Create canvas
    var canvas = document.getElementById("wave");
    canvas.style.width = "1000px";
    canvas.style.height = "100px";
    
    //High dpi stuff
    canvas.width = parseInt(canvas.style.width) * 2;
    canvas.height = parseInt(canvas.style.height) * 2;
    
    //Get canvas context
    var ctx = canvas.getContext("2d");
    
    //Set stroke color to yellow
    ctx.strokeStyle = "#ffff00";
    
    //Draw twice as thick lines due to high dpi scaling
    ctx.lineWidth = 2;
    
    //Save x and y from the previous drawing
    var drawX = 0;
    var drawY = 0;
    
    //Total duration (Seconds)
    var duration;
    
    //The animation reference
    var animation;
    
    //Audio is loaded
    audioElement.oncanplaythrough = function() {
    
        //Get duration
        duration = audioElement.duration;
    
        //On play
        audioElement.onplay = function() {
            //Start drawing
            drawWave();
        };
    
        //On pause
        audioElement.onpause = function() {
            //Stop drawing
            cancelAnimationFrame(animation);
        };
    
        //On ended
        audioElement.onended = function() {
            //Stop drawing
            cancelAnimationFrame(animation);
    
            //Clear previous drawing
            ctx.clearRect(0, 0, canvas.width, canvas.height);
    
            //Clear previous x and y values
            drawX = 0;
            drawY = 0;
    
            //Prevent audio from looping (you can remove this if you want it to loop)
            audioElement.pause();
        };
    };
    
    //Our drawing method
    function drawWave() {
    
        //Current time (seconds)
        var currentTime = audioElement.currentTime;
    
        // Copy frequency data to frequencyData array.
        analyser.getByteFrequencyData(frequencyData);
    
        //Total loudness of all frequencies in frequencyData
        var totalLoudness = 0;
        for(var i = 0; i < frequencyData.length; i++) {
            totalLoudness += frequencyData[i];
        }
    
        //Average loudness of all frequencies in frequencyData
        var averageLoudness = totalLoudness / frequencyData.length;
    
        //Get the previous x axis value
        var previousDrawX = drawX;
    
        //Scale of progress in song (from 0 to 1)
        drawX =  currentTime / duration;
        //Multiply with canvas width to get x axis value
        drawX *= canvas.width;
    
        //Get the previous y axis value
        var previousDrawY = drawY;
    
        //Scale of average loudness from (0 to 1), frequency loudness scale is (0 to 255)
        drawY = averageLoudness / 255;
        //Multiply with canvas height to get scale from (0 to canvas height)
        drawY *= canvas.height;
        //Since a canvas y axis is inverted from a normal y axis we have to flip it to get a normal y axis value
        drawY = canvas.height - drawY;
    
        //Draw line
        ctx.beginPath();
        ctx.moveTo(previousDrawX, previousDrawY);
        ctx.lineTo(drawX, drawY);
        ctx.stroke();
    
        //Animate
        animation = requestAnimationFrame(drawWave);
    }
    


    <audio id="audioElement" src="audio/Odesza - Above The Middle.mp3"></audio>
    <canvas id="wave"></canvas>
    <div>
      <button onclick="audioElement.play()">Play the Audio</button>
      <button onclick="audioElement.pause()">Pause the Audio</button>
      <button onclick="audioElement.volume+=0.1">Increase Volume</button>
      <button onclick="audioElement.volume-=0.1">Decrease Volume</button>
    </div>
    




    Canvas visualizer example

    Demo: http://seapip.com/canvas/visualizer/

    //Without var to make it a global variable accessable by the html onclick attribute 
    audioElement = document.getElementById('audioElement');
    var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    var audioSrc = audioCtx.createMediaElementSource(audioElement);
    var analyser = audioCtx.createAnalyser();
    
    // Bind our analyser to the media element source.
    audioSrc.connect(analyser);
    audioSrc.connect(audioCtx.destination);
    
    //Get frequency data (400 = max frequency)
    var frequencyData = new Uint8Array(400);
    //Use below to show all frequencies
    //var frequencyData = new Uint8Array(analyser.frequencyBinCount);
    
    //Create canvas
    var canvas = document.getElementById("wave");
    canvas.style.width = "500px";
    canvas.style.height = "100px";
    
    //High dpi stuff
    canvas.width = parseInt(canvas.style.width) * 2;
    canvas.height = parseInt(canvas.style.height) * 2;
    
    //Get canvas context
    var ctx = canvas.getContext("2d");
    
    //Set stroke color
    ctx.strokeStyle = "#ffff00"
    
    //Draw twice as thick lines due to high dpi scaling
    ctx.lineWidth = 2;
    
    //Animation reference
    var animation;
    
    //On play
    audioElement.onplay = funtion() {
        drawWave();
    };
    
    //On pause
    audioElement.onpause = funtion() {
        cancelAnimationFrame(animation);
    };
    
    //On ended
    audioElement.onended = funtion() {
        cancelAnimationFrame(animation);
    };
    
    //Our drawing method
    function drawWave() {
        // Copy frequency data to frequencyData array.
        analyser.getByteFrequencyData(frequencyData);
    
        //Draw the wave
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        for(var i = 1; i < frequencyData.length; i++) {
            var x1 = canvas.width / (frequencyData.length - 1) * (i - 1);
            var x2 = canvas.width / (frequencyData.length - 1) * i;
            var y1 = canvas.height - frequencyData[i - 1] / 255 * canvas.height;
            var y2 = canvas.height - frequencyData[i] / 255 * canvas.height;
            if(x1 && y1 && x2 && y2) {
                ctx.beginPath();
                ctx.moveTo(x1, y1);
                ctx.lineTo(x2, y2);
                ctx.stroke();
            }
        }
    
        //Animate
        animation = requestAnimationFrame(drawWave);
    }
    


    <audio id="audioElement" src="audio/Odesza - Above The Middle.mp3"></audio>
    <canvas id="wave"></canvas>
    <div>
      <button onclick="document.getElementById('audioElement').play()">Play the Audio</button>
      <button onclick="document.getElementById('audioElement').pause()">Pause the Audio</button>
      <button onclick="document.getElementById('audioElement').volume+=0.1">Increase Volume</button>
      <button onclick="document.getElementById('audioElement').volume-=0.1">Decrease Volume</button>
    </div>
    




    Plugins and tutorials about audio visualization:

    https://wavesurfer-js.org/

    http://waveformjs.org/#weird

    https://www.bignerdranch.com/blog/music-visualization-with-d3-js/

    https://github.com/wayou/HTML5_Audio_Visualizer

    https://www.patrick-wied.at/blog/how-to-create-audio-visualizations-with-javascript-html

    https://p5js.org/examples/examples/Sound_Frequency_Spectrum.php

    0 讨论(0)
提交回复
热议问题