gpt4 book ai didi

javascript - 如何生成HTML5视频音量水平图?

转载 作者:行者123 更新时间:2023-11-30 09:28:16 26 4
gpt4 key购买 nike

给定一个简单的网络视频,比如说30年代:

<video src="my-video.mp4"></video>

我如何生成其音量水平图?
volume|
level| ******
| * * **
| * * * **
|** * *** *
| ** * * * *
+---------------*-*-----************------+--- time
0 30s
video is and quiet
loud here here

注意:
  • 请使用纯JavaScript。没有图书馆。
  • 最佳答案

    有几种方法可以执行此操作,具体取决于用法。
    为了提高准确性,您可以使用常规音量和单位进行测量,例如RMS,LUFS / LKFS(K权重,响度),dBFS(满量程dB)等。
    一种简单的简单方法是仅绘制波形的峰值。您只会对正值感兴趣。要仅获取峰,您将检测到两个点之间的方向,并在方向从上到下变化(p0> p1)时记录第一个点。
    对于所有方法,您最终都可以应用某种形式的平滑方法,例如加权移动平均值(example)或通用的平滑算法,以消除小峰值和变化(在RMS,dB等情况下)。您可以使用可以与箱平滑(每个分段的平均值)。
    要进行绘图,您将获得当前样本的值,假设将其标准化,然后将其绘制为按绘图区域高度缩放的线或点到 Canvas 。
    关于加载源数据的小讨论
    解决评论中的一些问题;这些只是我脑海中的一些提示-
    由于Web Audio API无法单独进行流传输,因此您必须将整个文件加载到内存中,并将音频轨道解码到缓冲区中。

  • 优点:有效(分析部分),在最终准备好数据时进行快速分析,适用于较小的文件,如果缓存的URL可以使用而无需重新下载
  • 缺点:初始加载时间长/ UX不好,可能的内存占用/不适用于大文件,音频与视频同步“分离”,如果没有大文件和/或缓存,则强制URL *的重用将必须再次下载/流式传输,当前会导致某些浏览器/版本出现问题(请参见下面的示例)。

  • *:始终可以选择将下载的视频作为blob存储在IndexedDB中(及其含义),并使用带有该blob的Object-URL在视频元素中进行流式传输(可能要求MSE正常工作,请自己尝试一下) 。
    流式绘图:
  • 优点:内存/资源便宜
  • 缺点:在播放完整个文件之前,无法完整显示情节,用户可能会跳过/跳转部分,可能无法完成

  • 侧面加载低质量的单声道纯音频文件:
  • 优点:音频可以独立于视频文件加载到内存中,因此对于使用
  • 的级别而言,效果足够好
  • 缺点:可能会延迟视频的初始加载,可能在视频开始之前未及时准备好,将需要事先进行额外的处理

  • 服务器端绘图:
  • 优点:可以在上载时进行绘图,可以存储原始图数据,该数据在请求视频时作为元数据提供,低带宽,在视频开始时已准备好数据(假设数据代表了时间段内的平均值)。
  • 缺点:要求服务器上的基础结构可以分离,分析和生成绘图数据,这取决于数据的存储方式,可能需要修改数据库。

  • 我可能遗漏了或遗漏了一些要点,但是它应该给出总体思路...

    此示例测量每个样本给定窗口大小的常规dB。窗口大小越大,结果越平滑,但也需要更多时间来计算。
    注意,为简单起见,在此示例中,像素位置确定dB窗口范围。根据影响当前样本值的缓冲区大小,这可能会产生不均匀的间隙/重叠,但应能达到此处说明的目的。同样为了简单起见,我通过将dB读数除以40来缩放dB,在这里这是一个任意数字(ABS只是用于绘图以及我在深夜/清晨做这件事时大脑的工作方式(?):)) 。
    我在顶部添加了红色的bin / segment-smoothing,以便更好地显示与自动调平等事情有关的长期音频变化。
    我在这里使用音频源,但是您可以插入视频源,只要它包含可以解码的音轨格式(aac,mp3,ogg等)即可。
    除此之外,示例仅仅是一个示例。这不是生产代码,因此请考虑它的值(value)。根据需要进行调整。
    (由于某些原因,音频无法在Firefox v58beta中播放,但会进行绘图。音频在Chrome,FF58dev中播放)。

    var ctx = c.getContext("2d"), ref, audio;
    var actx = new (AudioContext || webkitAudioContext)();
    var url = "//dl.dropboxusercontent.com/s/a6s1qq4lnwj46uj/testaudiobyk3n_lo.mp3";
    ctx.font = "20px sans-serif";
    ctx.fillText("Loading and processing...", 10, 50);
    ctx.fillStyle = "#001730";

    // Load audio
    fetch(url, {mode: "cors"})
    .then(function(resp) {return resp.arrayBuffer()})
    .then(actx.decodeAudioData.bind(actx))
    .then(function(buffer) {

    // Get data from channel 0 (you will want to measure all/avg.)
    var channel = buffer.getChannelData(0);

    // dB per window + Plot
    var points = [0];
    ctx.clearRect(0, 0, c.width, c.height);
    ctx.moveTo(x, c.height);
    for(var x = 1, i, v; x < c.width; x++) {
    i = ((x / c.width) * channel.length)|0; // get index in buffer based on x
    v = Math.abs(dB(channel, i, 8820)) / 40; // 200ms window, normalize
    ctx.lineTo(x, c.height * v);
    points.push(v);
    }
    ctx.fill();

    // smooth using bins
    var bins = 40; // segments
    var range = (c.width / bins)|0;
    var sum;
    ctx.beginPath();
    ctx.moveTo(0,c.height);
    for(x = 0, v; x < points.length; x++) {
    for(v = 0, i = 0; i < range; i++) {
    v += points[x++];
    }
    sum = v / range;
    ctx.lineTo(x - (range>>1), sum * c.height); //-r/2 to compensate visually
    }
    ctx.lineWidth = 2;
    ctx.strokeStyle = "#c00";
    ctx.stroke();

    // for audio / progressbar only
    c.style.backgroundImage = "url(" + c.toDataURL() + ")";
    c.width = c.width;
    ctx.fillStyle = "#c00";
    audio = document.querySelector("audio");
    audio.onplay = start;
    audio.onended = stop;
    audio.style.display = "block";
    });

    // calculates RMS per window and returns dB
    function dB(buffer, pos, winSize) {
    for(var rms, sum = 0, v, i = pos - winSize; i <= pos; i++) {
    v = i < 0 ? 0 : buffer[i];
    sum += v * v;
    }
    rms = Math.sqrt(sum / winSize); // corrected!
    return 20 * Math.log10(rms);
    }

    // for progress bar (audio)
    function start() {if (!ref) ref = requestAnimationFrame(progress)}
    function stop() {cancelAnimationFrame(ref);ref=null}
    function progress() {
    var x = audio.currentTime / audio.duration * c.width;
    ctx.clearRect(0,0,c.width,c.height);
    ctx.fillRect(x-1,0,2,c.height);
    ref = requestAnimationFrame(progress)
    }
    body {background:#536375}
    #c {border:1px solid;background:#7b8ca0}
    <canvas id=c width=640 height=300></canvas><br>
    <audio style="display:none" src="//dl.dropboxusercontent.com/s/a6s1qq4lnwj46uj/testaudiobyk3n_lo.mp3" controls></audio>

    关于javascript - 如何生成HTML5视频音量水平图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48031793/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com