You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用p5.js实现歌曲时间线可视化:按网格分段获取音频电平

解决方向与实现步骤

核心思路

你需要预分析整首音频的频谱数据,将音频时长按网格元素数量分割成对应分段,提前计算每个分段的bass/treble/mid电平(取平均或峰值),最后用这些预计算的数据绘制网格,而非实时读取播放中的电平。

具体步骤

1. 预加载并分析音频

首先要加载完整音频,然后逐段遍历音频的时间轴,用FFT分析每个时间段的能量值并存储:

  • 用loadSound加载音频文件,确保音频加载完成后再开始分析
  • 计算每个分段的时长:segmentDuration = 总音频时长 / 网格总元素数(比如10×10网格就是100段)
  • 遍历每个分段,跳到对应时间点,用FFT分析该段的频谱能量,将bass/treble/mid值存入数组

2. 存储分段数据

创建二维数组(对应网格的x/y坐标)来存储每个分段的电平数据,比如:

// 假设是10×10网格
let segmentData = Array(10).fill().map(() => Array(10).fill({bass:0, treble:0, mid:0}));

遍历过程中把每个分段计算出的电平值填充到这个数组里。

3. 修改绘制逻辑

把原来draw函数里实时获取FFT数据的部分,替换成读取预存的segmentData,直接用对应网格位置的数值来绘制图形。

代码示例(修改版)

let sound;
let fft;
let gridCols = 10;
let gridRows = 10;
let segmentData = [];
let isAnalyzed = false;

function preload() {
  sound = loadSound('your-song.mp3'); // 替换成你的音频路径
}

function setup() {
  createCanvas(600, 600);
  fft = new p5.FFT();
  sound.play();
  sound.pause(); // 先暂停,完成预分析再播放(可选)
  
  // 开始预分析
  analyzeAudioSegments();
}

function analyzeAudioSegments() {
  const totalSegments = gridCols * gridRows;
  const totalDuration = sound.duration();
  const segmentLength = totalDuration / totalSegments;
  
  // 初始化数据数组
  segmentData = Array(gridRows).fill().map(() => Array(gridCols).fill({bass:0, treble:0, mid:0}));
  
  // 遍历每个分段
  for (let i = 0; i < totalSegments; i++) {
    const time = i * segmentLength;
    sound.jump(time); // 跳到该分段的起始时间
    fft.analyze(); // 触发FFT分析
    
    // 获取该时间点的能量值(可以取该分段内多个点的平均值,这里简化为取起始点)
    const bass = fft.getEnergy("bass");
    const treble = fft.getEnergy("treble");
    const mid = fft.getEnergy("mid");
    
    // 计算对应的网格坐标
    const row = floor(i / gridCols);
    const col = i % gridCols;
    segmentData[row][col] = {bass, treble, mid};
  }
  
  isAnalyzed = true;
  // 分析完成后可以选择播放音频
  // sound.play();
}

function draw() {
  background(0);
  if (!isAnalyzed) return; // 未分析完成时不绘制
  
  const cellWidth = width / gridCols;
  const cellHeight = height / gridRows;
  
  for (let y = 0; y < gridRows; y++) {
    for (let x = 0; x < gridCols; x++) {
      const data = segmentData[y][x];
      
      // 绘制BASS矩形
      let bassAmp = map(data.bass, 0, 512, 0, cellWidth);
      noFill();
      stroke(0, 255, 0); // 用绿色区分bass
      rect(x*cellWidth, y*cellHeight, bassAmp, bassAmp);
      
      // 绘制TREBLE矩形
      let trebleAmp = map(data.treble, 0, 512, 0, cellWidth);
      stroke(255, 0, 0); // 红色区分treble
      rect(x*cellWidth, y*cellHeight, trebleAmp, trebleAmp);
      
      // 绘制MID矩形
      let midAmp = map(data.mid, 0, 512, 0, cellWidth);
      stroke(0, 0, 255); // 蓝色区分mid
      rect(x*cellWidth, y*cellHeight, midAmp, midAmp);
    }
  }
}

搜索关键词参考

  • p5.js 音频预分析
  • p5.js FFT 离线分析
  • p5.js SoundFile 逐帧处理
  • p5.js 音频分段频谱提取

内容的提问来源于stack exchange,提问作者Irrlicht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:53:17