threejs实现音频可视化效果

音频分析
创建AudioAnalyser对象, 使用 AnalyserNode 去分析音频数据。将声波的波动转化为图形线条的起伏变化,从而表现出声音的音高、音量等信息。
核心代码
function createAudio() {
const fftSize = 1024;
if (!audio) {
const listener = new THREE.AudioListener();
audio = new THREE.Audio(listener);
const file = '/assets/video.mp4'; // 音视频都可以
mediaElement = new Audio(file);
mediaElement.play();
audio.setMediaElementSource(mediaElement);
}
analyser = new THREE.AudioAnalyser(audio, fftSize);
bufferLength = analyser.analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
analyser.getFrequencyData(dataArray);
dataArray = analyser.data
// 获取 ID 为 "oscilloscope" 的画布
canvas = document.getElementById("oscilloscope");
canvasCtx = canvas.getContext("2d");
var canvasTexture = new THREE.CanvasTexture(canvas);
// 创建平面
var geometry = new THREE.PlaneGeometry(18, 2);
var material = new THREE.MeshPhongMaterial({
map: canvasTexture, // 设置纹理贴图
transparent: true,
});
// 创建一个矩形平面网模型,Canvas画布作为矩形网格模型的纹理贴图
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 绘制一个当前音频源的示波器
function draw() {
drawVisual = requestAnimationFrame(draw);
canvasTexture.needsUpdate = true;
analyser.getFrequencyData(dataArray);
dataArray = analyser.data
// 绘制柱形
// canvase背景色透明
canvasCtx.fillStyle = 'rgba(255, 255, 255, 0)';
canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
var barWidth = canvas.width / bufferLength * 4
var barHeight;
var x = 0;
for (var i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
canvasCtx.fillStyle = 'rgb(' + barHeight + 100 + ',200,130)';
canvasCtx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
x += barWidth + 1;
}
// 绘制波形
// canvasCtx.lineWidth = 2;
// canvasCtx.strokeStyle = "rgb(0, 0, 0)";
// canvasCtx.beginPath();
// var sliceWidth = (canvas.width * 1.0) / bufferLength;
// var x = 0;
// for (var i = 0; i < bufferLength; i++) {
// var v = dataArray[i] / 128.0;
// var y = (v * canvas.height) / 2;
// if (i === 0) {
// canvasCtx.moveTo(x, y);
// } else {
// canvasCtx.lineTo(x, y);
// }
// x += sliceWidth;
// }
canvasCtx.lineTo(canvas.width, canvas.height / 2);
canvasCtx.stroke();
}
draw();
}