【问题标题】:How to write a web-based music visualizer?如何编写基于 Web 的音乐可视化工具?
【发布时间】:2011-03-06 16:46:32
【问题描述】:
我正在尝试找到构建音乐可视化器以在网络浏览器中运行的最佳方法。 Unity 是一个选项,但我需要构建一个自定义音频导入/分析插件来获取最终用户的声音输出。 Quartz 可以满足我的需要,但只能在 Mac/Safari 上运行。 WebGL 似乎还没有准备好。 Raphael 主要是 2D,还有获取用户声音的问题......有什么想法吗?以前有人做过吗?
【问题讨论】:
标签:
unity3d
webgl
raphael
visualization
quartz-graphics
【解决方案1】:
制作音频反应非常简单。 Here's an open source site with lots audio reactive examples.
至于如何做到这一点,您基本上使用 Web Audio API 来流式传输音乐并使用其 AnalyserNode 来获取音频数据。
"use strict";
const ctx = document.querySelector("canvas").getContext("2d");
ctx.fillText("click to start", 100, 75);
ctx.canvas.addEventListener('click', start);
function start() {
ctx.canvas.removeEventListener('click', start);
// make a Web Audio Context
const context = new AudioContext();
const analyser = context.createAnalyser();
// Make a buffer to receive the audio data
const numPoints = analyser.frequencyBinCount;
const audioDataArray = new Uint8Array(numPoints);
function render() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// get the current audio data
analyser.getByteFrequencyData(audioDataArray);
const width = ctx.canvas.width;
const height = ctx.canvas.height;
const size = 5;
// draw a point every size pixels
for (let x = 0; x < width; x += size) {
// compute the audio data for this point
const ndx = x * numPoints / width | 0;
// get the audio data and make it go from 0 to 1
const audioValue = audioDataArray[ndx] / 255;
// draw a rect size by size big
const y = audioValue * height;
ctx.fillRect(x, y, size, size);
}
requestAnimationFrame(render);
}
requestAnimationFrame(render);
// Make a audio node
const audio = new Audio();
audio.loop = true;
audio.autoplay = true;
// this line is only needed if the music you are trying to play is on a
// different server than the page trying to play it.
// It asks the server for permission to use the music. If the server says "no"
// then you will not be able to play the music
// Note if you are using music from the same domain
// **YOU MUST REMOVE THIS LINE** or your server must give permission.
audio.crossOrigin = "anonymous";
// call `handleCanplay` when it music can be played
audio.addEventListener('canplay', handleCanplay);
audio.src = "https://twgljs.org/examples/sounds/DOCTOR%20VOX%20-%20Level%20Up.mp3";
audio.load();
function handleCanplay() {
// connect the audio element to the analyser node and the analyser node
// to the main Web Audio context
const source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
}
}
canvas { border: 1px solid black; display: block; }
<canvas></canvas>
那么你就可以画出一些有创意的东西了。
注意一些你可能会遇到的麻烦。
此时 (2017/1/3) Android Chrome 和 iOS Safari 都不支持分析流式音频数据。相反,您必须加载整首歌曲。 Here'a a library that tries to abstract that a little
在移动设备上您无法自动播放音频。您必须根据 'click' 或 'touchstart' 等用户输入在输入事件中启动音频。
-
如示例中所指出的,您只能在源来自同一域或您请求 CORS 许可且服务器授予许可的情况下分析音频。 AFAIK 只有 Soundcloud 给予许可,并且是基于每首歌曲的。是否允许对特定歌曲进行音频分析取决于各个艺术家的歌曲设置。
尝试解释这部分
默认是您有权访问同一域中的所有数据,但无权访问其他域。
添加时
audio.crossOrigin = "anonymous";
这基本上是说“向服务器请求用户'匿名'的许可”。服务器可以给予或不给予许可。这取决于服务器。这甚至包括询问同一域中的服务器,这意味着如果您要请求同一域中的歌曲,您需要 (a) 删除上面的行或 (b) 配置您的服务器以授予 CORS 权限。大多数服务器默认不授予 CORS 权限,因此如果添加该行,即使服务器是同一个域,如果它没有授予 CORS 权限,那么尝试分析音频将失败。
音乐:DOCTOR VOX - Level Up
【解决方案4】:
根据您可能有兴趣尝试 Processing (http://www.processing.org) 的复杂程度,它具有制作基于 Web 的应用程序的非常简单的工具,并且它具有获取 FFT 和波形的工具音频文件。