Uma waveform de áudio visualiza amplitude ao longo do tempo. Seja imagem estática para capa de podcast, equalizador animado para clipe musical, ou array de dados para game engine, o método depende do meio de saída e conforto técnico.
Similar: Visualize waveform → Botão direito → **Exportar Imagem** ou Screenshot (monitor 4K + zoom).
Melhor para processamento em lote, dimensões exatas, controle de estilo, integração em pipelines.
# waveform.py import librosa, librosa.display, matplotlib.pyplot as plt, numpy as np, sys input_file = sys.argv[1] if len(sys.argv) > 1 else "audio.wav" output_file = sys.argv[2] if len(sys.argv) > 2 else "waveform.png" y, sr = librosa.load(input_file, sr=None, mono=True) # preserva sr nativo duration = len(y) / sr # Config estilo FIG_W, FIG_H = 1920, 600 # pixels @ 100 DPI DPI = 100 BG_COLOR = '#0a0a0a' WAVE_COLOR = '#00ff88' LINE_WIDTH = 0.6 plt.figure(figsize=(FIG_W/DPI, FIG_H/DPI), dpi=DPI, facecolor=BG_COLOR) ax = plt.gca() ax.set_facecolor(BG_COLOR) librosa.display.waveshow(y, sr=sr, ax=ax, color=WAVE_COLOR, alpha=0.9, linewidth=LINE_WIDTH) ax.axis('off') plt.subplots_adjust(left=0, right=1, top=1, bottom=0) plt.savefig(output_file, dpi=DPI, facecolor=BG_COLOR, bbox_inches='tight', pad_inches=0) plt.close() print(f"Salvo {output_file} ({FIG_W}x{FIG_H})")
Execute: `python waveform.py input.wav output.png`
Instale: `pip install librosa matplotlib numpy`
Para sites, componentes React, ou fontes de navegador OBS.
// waveform-visualizer.js (Vanilla Canvas - sem deps) const canvas = document.getElementById('waveform'); const ctx = canvas.getContext('2d'); const audioCtx = new AudioContext(); let analyser, dataArray, bufferLength, source; async function init(audioUrl) { const resp = await fetch(audioUrl); const arrayBuffer = await resp.arrayBuffer(); const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer); // Desenha waveform estático do buffer decodificado const channelData = audioBuffer.getChannelData(0); // Float32Array [-1,1] const step = Math.ceil(channelData.length / canvas.width); ctx.fillStyle = '#000'; ctx.fillRect(0,0,canvas.width,canvas.height); ctx.strokeStyle = '#00ff88'; ctx.lineWidth = 1; ctx.beginPath(); for (let x = 0; x < canvas.width; x++) { let min = 1, max = -1; for (let i = 0; i < step; i++) { const val = channelData[x * step + i] || 0; if (val < min) min = val; if (val > max) max = val; } const yMin = (1 + min) * canvas.height / 2; const yMax = (1 + max) * canvas.height / 2; ctx.moveTo(x, yMin); ctx.lineTo(x, yMax); } ctx.stroke(); } init('audio.mp3');
| Necessidade | Ferramenta | Saída |
|---|---|---|
| Capa de podcast única | Audacity / Canva | PNG/SVG |
| Lote de 1000 episódios | Python (librosa/matplotlib) | PNG/WebP |
| Animação hero do site | p5.js / Canvas API / WebGL | JS Interativo |
| Videoclipe / Lyric video | After Effects (Audio Spectrum) | MP4/MOV |
| UI de jogo / VJing | Unity/Unreal/Godot + FFT | Tempo real GPU |
Tecnologia Eletrônica © [www.351231.com]