Just add data attributes to any div. Auto-initialization, responsive design, and stunning waveforms out of the box.
Include the files, add data attributes, done.
<!-- 1. Include the files --> <link rel="stylesheet" href="https://unpkg.com/@arraypress/waveform-player@latest/dist/waveform-player.css"> <script src="https://unpkg.com/@arraypress/waveform-player@latest/dist/waveform-player.js"></script> <!-- 2. Add a player --> <div data-waveform-player data-url="your-audio.mp3" data-title="Song Title" data-artwork="cover.jpg"> </div>
No initialization. No configuration. It just works.
Everything you need for a complete audio experience
Shows on lock screens, media keys work, bluetooth controls supported
Try it: Click player then use Space (play), โโ (seek), โโ (volume), M (mute), 0-9 (position)
Perfect for podcasts and audiobooks. Click the speed button to adjust.
Everything you need, nothing you don't
Works with just HTML data attributes. Perfect for WordPress, static sites, or any CMS.
Control every color, dimension, and style through simple data attributes.
Media Session API support for lock screens, hardware keys, and bluetooth controls.
Just ~8KB gzipped. No jQuery, no dependencies, pure vanilla JavaScript.
Bars, mirror, line, blocks, dots, and seekbar. Each optimized for clarity.
Canvas rendering, RequestAnimationFrame, and optimized resampling.
Different styles for different vibes
See how to programmatically control players and track events
const player = WaveformPlayer.getInstance('player-id'); player.play(); player.pause(); player.seekToPercent(0.5); player.setVolume(0.5);
new WaveformPlayer('#player', { onPlay: (player) => trackEvent('play'), onPause: (player) => trackEvent('pause'), onEnd: (player) => trackEvent('complete'), onTimeUpdate: (current, total) => updateProgress(current) });
Customize every aspect and copy the code
<div data-waveform-player data-url="audio.mp3" data-waveform-style="bars" data-bar-width="2" data-bar-spacing="0"> </div>
Advanced capabilities for power users
Note: BPM detection works best with rhythmic content like drums or electronic music. Detection accuracy may vary with complex patterns or live recordings.
// HTML with data attribute
<div data-waveform-player
data-url="audio.mp3"
data-markers='[
{"time": 2, "label": "Verse", "color": "#4ade80"},
{"time": 5, "label": "Chorus", "color": "#f59e0b"},
{"time": 8, "label": "Bridge", "color": "#ef4444"}
]'>
</div>
// Or via JavaScript
new WaveformPlayer('#player', {
url: 'audio.mp3',
markers: [
{time: 2, label: 'Verse', color: '#4ade80'},
{time: 5, label: 'Chorus', color: '#f59e0b'},
{time: 8, label: 'Bridge', color: '#ef4444'}
]
});
// Get player instance
const player = WaveformPlayer.getInstance('switcher-player');
// Load a new track with all options
await player.loadTrack(
'new-song.mp3', // URL
'Song Title', // Title
'Artist Name', // Subtitle
{ // Additional options
markers: [
{time: 30, label: 'Verse 1'},
{time: 60, label: 'Chorus'},
{time: 90, label: 'Bridge'}
],
waveformStyle: 'mirror',
showBPM: true,
artwork: 'cover.jpg'
}
);
// Simple track change
await player.loadTrack('another-song.mp3', 'Another Song');
// Waveform data will appear here...
// Generate once
const waveformData = await WaveformPlayer.generateWaveformData(
'audio/song.mp3',
200 // samples
);
// Save to your database/API
await saveToDatabase(waveformData);
// Later, use the cached data
new WaveformPlayer('#player', {
url: 'audio/song.mp3',
waveform: waveformData, // Use pre-generated data
title: 'Optimized Player'
});
Extend WaveformPlayer with playlist support and chapter navigation using our companion library
WaveformPlaylist uses simple HTML markup. Just nest your tracks and chapters as divs with data attributes:
<!-- The container becomes the playlist -->
<div data-waveform-playlist <!-- Activates playlist -->
data-continuous="true" <!-- Auto-play next track -->
data-waveform-style="mirror"> <!-- Inherits all player options -->
<!-- Each track is a div with data-track -->
<div data-track
data-url="episode1.mp3"
data-title="Episode 1: Getting Started"
data-subtitle="with John Doe"
data-artwork="cover1.jpg">
<!-- Chapters are nested divs with timestamps -->
<div data-chapter data-time="0:00">Introduction</div>
<div data-chapter data-time="5:30">Main Topic</div>
<div data-chapter data-time="25:00">Q&A Session</div>
</div>
<!-- Add more tracks -->
<div data-track
data-url="episode2.mp3"
data-title="Episode 2: Advanced Topics">
<div data-chapter data-time="0:00">Recap</div>
<div data-chapter data-time="3:00">Deep Dive</div>
</div>
</div>
<!-- That's it! The library handles everything else -->
data-waveform-playlist
creates the playlistdata-track
div becomes a track in the listdata-chapter
divs become clickable timestamps<div data-waveform-playlist
data-waveform-style="mirror"
data-height="80">
<div data-track
data-url="podcast.mp3"
data-title="Episode 42: The Future of Web Audio"
data-subtitle="with Sarah Chen"
data-artwork="cover.svg">
<div data-chapter data-time="0:00">Introduction</div>
<div data-chapter data-time="0:02">Background</div>
<div data-chapter data-time="0:04">Deep Dive</div>
<div data-chapter data-time="0:06">Future</div>
<div data-chapter data-time="0:08">Q&A</div>
</div>
</div>
<div data-waveform-playlist
data-continuous="true"
data-show-play-state="true">
<div data-track
data-url="song1.mp3"
data-title="Wings"
data-subtitle="Ambient Dreams"
data-artwork="cover1.svg"
data-duration="0:10"></div>
<div data-track
data-url="song2.mp3"
data-title="Desire"
data-subtitle="Electronic Vibes"
data-artwork="cover2.svg"
data-duration="0:10"></div>
<div data-track
data-url="song3.mp3"
data-title="Lovely"
data-subtitle="Chill Beats"
data-artwork="cover3.svg"
data-duration="0:10"></div>
</div>
Just 4KB gzipped. Works with any WaveformPlayer configuration.
All available data attributes
Attribute | Default | Description |
---|---|---|
data-url |
- | Audio file URL (required) |
data-waveform-style |
bars | Visual style: bars, mirror, line, blocks, dots, seekbar |
data-bar-width |
2 | Width of bars in pixels |
data-bar-spacing |
0 | Space between bars |
data-samples |
200 | Waveform detail level (100-400) |
data-height |
60 | Canvas height in pixels |
data-waveform-color |
- | Inactive waveform color |
data-progress-color |
- | Active waveform color |
data-button-color |
- | Play button color |
data-title |
Filename | Track title |
data-subtitle |
- | Track subtitle/artist |
data-album |
- | Album name for Media Session |
data-artwork |
- | Album artwork URL (shows in player and system controls) |
data-enable-media-session |
true | Enable system media controls |
data-show-bpm |
false | Show BPM detection |
data-show-playback-speed |
false | Show speed control menu |
data-playback-rate |
1 | Initial playback speed (0.5-2) |
data-autoplay |
false | Auto-start playback |
data-show-time |
true | Show time display |
data-markers |
- | JSON array of marker objects with time, label, and color |
WaveSurfer is a solid, battle-tested library. But it's 40KB+ minified, requires configuration, and can be complex for simple use cases. WaveformPlayer is just ~8KB, works with zero JavaScript, and is perfect for WordPress, Shopify, or any CMS where you just want to add audio players without touching code.
Amplitude is great for building full music players with playlists. WaveformPlayer focuses on one thing: beautiful waveform visualization with minimal overhead. If you need playlists and complex controls, use Amplitude. If you want drop-in waveforms, this is for you.
Absolutely! Just enqueue the CSS and JS files in your theme, then use data attributes in your content. Works perfectly with Gutenberg blocks, shortcodes, or any page builder. A dedicated WordPress plugin is coming soon.
Yes! Upload the files to your theme's assets folder, include them in theme.liquid, then add players anywhere using data attributes. Perfect for music previews, podcast episodes, or audio samples.
The vanilla version works perfectly in any framework. Just include the script and use data attributes in your JSX/templates. For React, you can also use the programmatic API in useEffect/componentDidMount.
100% real! We decode your audio file using the Web Audio API and generate actual waveform data. Every peak and valley represents the true amplitude of your audio.
Every color is customizable via data attributes. Set waveform color, progress color, button color, text color, and more. Or use the light/dark presets and tweak from there.
All modern browsers from the last 2-3 years. Chrome 88+, Firefox 85+, Safari 14+, Edge 88+. We use standard Web Audio API and Canvas, no experimental features.
Yes! Generate waveform data server-side or cache it, then pass it via data-waveform attribute. This gives instant visualization without waiting for audio decode.
Files up to 100MB work fine. The waveform generates progressively, so users see something immediately. For huge files (podcasts, audiobooks), consider using streaming or chunked loading.
Full keyboard navigation (space, arrows, etc), ARIA labels, focus indicators, and screen reader announcements. The player is WCAG 2.1 AA compliant.
The player inherits your site's fonts automatically. Just set your font-family in CSS and the player will use it for titles and time displays.
No! Everything is free and open source. We believe audio players should be accessible to everyone. If you love it, star us on GitHub or buy us a coffee.
Use the JavaScript API to hook into play, pause, and progress events. Send these to Google Analytics, Mixpanel, or your custom analytics. Check the Playground section for examples.
Yes! MIT license means you can use it for anything - commercial projects, client work, SaaS products. No attribution required (but appreciated).
The player gracefully falls back to a styled container with title/subtitle visible. You could also include a standard HTML5 audio element as fallback content.
Free, open-source, and ready to use in your next project