shank-wavesurfer
v0.1.2
Published
A browser audio waveform and spectrogram player library built with TypeScript.
Maintainers
Readme
ShankWavesurfer
ShankWavesurfer is a Vite + vanilla TypeScript audio player library that mounts into one root element and ships with an integrated dark instrument style UI, waveform view, spectrogram view, local file support, remote URL loading, zoomable timeline navigation, drag selection, and region playback controls.
Quick Start
import { ShankWavesurfer } from "shank-wavesurfer";
const player = new ShankWavesurfer("player-root");
await player.load("http://127.0.0.1:8080/a.mp3");You can also load a local file object:
const player = new ShankWavesurfer(document.getElementById("player-root") as HTMLElement);
const file = new File([], "demo.mp3");
await player.load(file);Implemented Features
- Single call mount API with
constructor(root: string | HTMLElement). - Public methods:
load,play,pause,stop,destroy. - Integrated Chinese UI. Consumers only provide a root div.
- Local audio through file picker and drag and drop.
- Remote URL loading through the hidden
<audio>element. - Web Audio graph based on
AudioContext,MediaElementAudioSourceNode,ChannelSplitterNode,ChannelMergerNode, andAnalyserNode. - Bottom transport controls for play, pause, stop, current time, total time, volume, visualization mode, and channel mode.
- Waveform and spectrogram canvas rendering.
- Stereo, left, and right channel display modes.
- Shared timeline when both channels are shown.
- Click to seek and immediately play.
- Mouse wheel zoom on the main chart and timeline.
- Full overview timeline with current zoom window overlay.
- Drag selection with custom right click menu containing
播放循环播放取消选中. - IndexedDB overview cache.
- PCM 解码后统一生成波形与 STFT 时频谱数据。
- 已加入大文件分析基础设施:
ffmpeg.wasm运行时封装 + 远程文件大小探测工具。 - Worker driven overview/STFT matrix generation.
- Responsive canvas sizing with
ResizeObserver.
Demo
The demo entrypoint is index.html and mounts the player into #player-root through src/main.ts.
Architecture Notes
- src/lib/ShankWavesurfer.ts contains the public class, DOM mounting, interaction model, render loop, timeline logic, and audio graph wiring.
- src/lib/overview.worker.ts consumes decoded PCM and generates waveform peaks plus STFT spectrogram data off the main thread.
- src/lib/cache.ts stores and restores overview data from IndexedDB.
- src/lib/style.ts injects the instrument styled CSS directly into the document.
Large File Strategy And Tradeoffs
This project now uses a real PCM-based visualization pipeline:
- Playback still uses the browser
<audio>element for native streaming. - Visualization generation fetches/reads the source as an
ArrayBuffer, decodes it to PCM, then sends the channel data to a worker. - The worker computes both waveform peaks and STFT spectrogram data from the same PCM source.
- IndexedDB stores the resulting overview so repeat loads can skip recomputation.
Tradeoffs and browser constraints:
- True waveform + STFT generation requires full decode access to the audio source.
- For very large files, browser memory usage can become substantial because PCM must exist at least transiently during decode and worker transfer.
- Remote URLs require CORS access that permits fetching the file body, not only media-element playback.
- The library no longer fakes spectrogram data when decode succeeds; if decode/fetch is blocked, visualization generation will fail honestly instead of drawing a fake heatmap.
This is more accurate than the earlier byte-statistics approach, but less forgiving on huge files because real PCM analysis is fundamentally more expensive.
Large File Roadmap (in progress)
A more aggressive large-file path is now being introduced:
src/lib/large-file-analysis.tsprovides anffmpeg.wasmruntime wrapper.- It is intended for future segmented local-file and HTTP Range based analysis workflows.
- The current player still uses the direct decode path for rendering, but the project now contains the required runtime layer for migrating toward segmented analysis of files larger than ~50MB.
Build
npm install
npm run buildBuild outputs:
- Demo build:
dist/demo - Library build:
dist/lib
Notes
- Remote visualization depends on the target server exposing the audio with compatible CORS headers.
- The library injects its own CSS and hidden audio element, so no extra markup is required beyond the root container.
