ngx-audio-wave
v22.0.0
Published
A modern, accessible audio wave visualization component for Angular 22+ with comprehensive keyboard navigation and screen reader support.
Maintainers
Readme
ngx-audio-wave
A modern, accessible audio wave visualization component for Angular 22+ with comprehensive keyboard navigation and screen reader support.
Features
- 🎵 Audio Wave Visualization - Beautiful SVG-based audio wave display
- ⌨️ Full Keyboard Support - Complete keyboard navigation (Space, Enter, Arrow keys, Home, End)
- ♿ Accessibility First - WCAG 2.1 compliant with ARIA support
- 🎨 Highly Customizable - Colors, dimensions, gaps, and styling options
- 📱 Responsive Design - Works on all screen sizes
- 🚀 Modern Angular - Built with Angular 22+ signals and standalone components
- 🎯 TypeScript - Full type safety and IntelliSense support
Demo
🎮 Live Demo - Try the interactive demo

Quick Start
Installation
npm install ngx-audio-waveAngular 22+ (Standalone Components)
import { NgxAudioWave } from 'ngx-audio-wave';
@Component({
selector: 'app-root',
standalone: true,
imports: [NgxAudioWave],
template: `
<ngx-audio-wave
ariaLabel="My audio player"
audioSrc="path/to/your/audio.mp3"
>
</ngx-audio-wave>
`,
})
export class AppComponent {}If your app does not already provide Angular HTTP services, add provideHttpClient() to your app config.
Remote audio files must allow browser CORS access because the component downloads the file to generate waveform data.
Basic Usage
<ngx-audio-wave
ariaLabel="My podcast episode"
audioSrc="https://example.com/audio.mp3"
>
</ngx-audio-wave>With Progress Information
<ngx-audio-wave #player audioSrc="assets/audio.mp3"></ngx-audio-wave>
<div class="audio-info">
<p>Progress: {{ player.exactPlayedPercent() | number:'1.1-1' }}%</p>
<p>
Time: {{ player.exactCurrentTime() | number:'1.1-1' }}s / {{
player.exactDuration() | number:'1.1-1' }}s
</p>
<p>Status: {{ player.statusText() }}</p>
</div>Examples
Custom Styling
<ngx-audio-wave
[gap]="3"
[height]="50"
[rounded]="false"
audioSrc="assets/audio.mp3"
color="#ff6b6b"
>
</ngx-audio-wave>With Custom Accessibility Labels
<ngx-audio-wave
ariaLabel="Weekly Tech Podcast Episode 42"
audioSrc="assets/podcast.mp3"
pauseButtonLabel="Pause podcast"
playButtonLabel="Start podcast"
progressBarLabel="Podcast progress - use arrow keys to navigate"
>
</ngx-audio-wave>Hide Default Button
<ngx-audio-wave [hideBtn]="true" #audioPlayer audioSrc="assets/audio.mp3">
</ngx-audio-wave>
<button (click)="audioPlayer.play()">▶️ Play</button>
<button (click)="audioPlayer.pause()">⏸️ Pause</button>
<button (click)="audioPlayer.stop()">⏹️ Stop</button>Volume Control
<ngx-audio-wave #player audioSrc="assets/audio.mp3"></ngx-audio-wave>
<div class="volume-controls">
<button (click)="player.setVolume(0)">🔇 Mute</button>
<button (click)="player.setVolume(0.5)">50% Volume</button>
<button (click)="player.setVolume(1)">100% Volume</button>
<button (click)="player.setVolume(player.currentVolume() === 0 ? 1 : 0)">
Toggle
</button>
</div>
<p>Current volume: {{ player.currentVolume() | percent }}</p>Playback Speed Control
<ngx-audio-wave #player audioSrc="assets/audio.mp3"></ngx-audio-wave>
<div class="speed-controls">
<button (click)="player.setPlaybackRate(player.currentPlaybackRate() - 0.25)">
⏪ Slower
</button>
<button (click)="player.setPlaybackRate(1)">1x Normal</button>
<button (click)="player.setPlaybackRate(player.currentPlaybackRate() + 0.25)">
⏩ Faster
</button>
<button (click)="player.setPlaybackRate(0.5)">0.5x</button>
<button (click)="player.setPlaybackRate(1.5)">1.5x</button>
<button (click)="player.setPlaybackRate(2)">2x</button>
</div>
<p>Current speed: {{ player.currentPlaybackRate() }}x</p>Loop Control
<ngx-audio-wave #player audioSrc="assets/audio.mp3"></ngx-audio-wave>
<div class="loop-controls">
<button (click)="player.setLoop(true)">🔄 Enable Loop</button>
<button (click)="player.setLoop(false)">⏹️ Disable Loop</button>
<button (click)="player.setLoop(!player.isLooping())">
🔄/⏹️ Toggle Loop
</button>
</div>
<p>Looping: {{ player.isLooping() ? 'Enabled' : 'Disabled' }}</p>
<!-- Auto-loop example -->
<ngx-audio-wave
[loop]="true"
ariaLabel="Background music with auto-loop"
audioSrc="assets/background-music.mp3"
>
</ngx-audio-wave>Different Heights and Gaps
<!-- Different heights -->
<ngx-audio-wave [height]="25" audioSrc="assets/audio.mp3"></ngx-audio-wave>
<ngx-audio-wave [height]="50" audioSrc="assets/audio.mp3"></ngx-audio-wave>
<ngx-audio-wave [height]="100" audioSrc="assets/audio.mp3"></ngx-audio-wave>
<!-- Different gaps -->
<ngx-audio-wave [gap]="1" audioSrc="assets/audio.mp3"></ngx-audio-wave>
<ngx-audio-wave [gap]="5" audioSrc="assets/audio.mp3"></ngx-audio-wave>
<ngx-audio-wave [gap]="10" audioSrc="assets/audio.mp3"></ngx-audio-wave>Accessibility Features
This component is built with accessibility as a core feature, ensuring it works seamlessly with assistive technologies and keyboard navigation.
Keyboard Navigation
| Key | Action |
| ------------------ | ---------------------------------------- |
| Space or Enter | Play/Pause audio |
| Arrow Left | Skip backward (configurable with skip) |
| Arrow Right | Skip forward (configurable with skip) |
| Home | Jump to beginning |
| End | Jump to end |
Screen Reader Support
- ARIA Labels: All interactive elements have descriptive labels
- Live Regions: Status changes are announced automatically
- Progress Information: Detailed progress text with time and percentage
- Semantic Roles: Proper ARIA roles for all components
- Focus Management: Logical tab order and focus indicators
Screen Reader Testing
Recommended manual test matrix before release:
- NVDA (Windows)
- JAWS (Windows)
- VoiceOver (macOS/iOS)
- TalkBack (Android)
API Reference
Input Properties
| Property | Type | Default | Description |
| ------------------ | ------------------- | ---------------------- | ------------------------------------------ |
| audioSrc | string \| SafeUrl | Required | URL or SafeUrl of the audio file to play |
| color | string | '#1e90ff' | Color of the audio wave bars |
| height | number | 25 | Height of the wave visualization in pixels |
| gap | number | 5 | Gap between wave bars in pixels |
| samples | number | 50 | Number of waveform bars |
| rounded | boolean | true | Whether to round the corners of wave bars |
| hideBtn | boolean | false | Hide the play/pause button |
| skip | number | 5 | Seconds to skip when using arrow keys |
| volume | number | 1 | Initial volume level (0-1) |
| playbackRate | number | 1 | Initial playback speed (0.25-4) |
| loop | boolean | false | Whether to loop the audio |
| ariaLabel | string | 'Audio player' | Main ARIA label for the component |
| playButtonLabel | string | 'Play audio' | ARIA label for the play button |
| pauseButtonLabel | string | 'Pause audio' | ARIA label for the pause button |
| progressBarLabel | string | 'Audio progress bar' | ARIA label for the progress bar |
Output Properties (Signals)
| Property | Type | Description |
| --------------------- | ----------------- | ----------------------------------------------- |
| isPaused | Signal<boolean> | Whether the audio is currently paused |
| isLoading | Signal<boolean> | Whether the audio is currently loading |
| hasError | Signal<boolean> | Whether there was an error loading the audio |
| currentVolume | Signal<number> | Current volume level (0-1) |
| currentPlaybackRate | Signal<number> | Current playback speed (0.25-4) |
| isLooping | Signal<boolean> | Whether the audio is currently looping |
| exactCurrentTime | Signal<number> | Current playback time in seconds (exact) |
| exactDuration | Signal<number> | Total duration in seconds (exact) |
| exactPlayedPercent | Signal<number> | Playback progress as percentage (exact) |
| progressText | Signal<string> | Human-readable progress text for screen readers |
| statusText | Signal<string> | Current status text for screen readers |
Methods
| Method | Parameters | Description |
| ------------------------ | ---------------- | -------------------------------------------------------------------- |
| play(time?: number) | time?: number | Play the audio, optionally from a specific time |
| pause() | - | Pause the audio |
| stop() | - | Stop the audio and reset to beginning |
| setVolume(volume) | volume: number | Set volume level (0-1) |
| mute() | - | Deprecated - Use setVolume(0) |
| unmute() | - | Deprecated - Use setVolume(value) |
| toggleMute() | - | Deprecated - Use setVolume(currentVolume() === 0 ? value : 0) |
| setPlaybackRate(rate) | rate: number | Set playback speed (0.25-4) |
| resetPlaybackRate() | - | Deprecated - Use setPlaybackRate(1) |
| increasePlaybackRate() | - | Deprecated - Use setPlaybackRate(currentPlaybackRate() + 0.25) |
| decreasePlaybackRate() | - | Deprecated - Use setPlaybackRate(currentPlaybackRate() - 0.25) |
| setLoop(loop) | loop: boolean | Enable or disable audio looping |
| enableLoop() | - | Deprecated - Use setLoop(true) |
| disableLoop() | - | Deprecated - Use setLoop(false) |
| toggleLoop() | - | Deprecated - Use setLoop(!isLooping()) |
Breaking Changes in v22
- Removed deprecated rounded state aliases:
currentTime,duration, andplayedPercent. - Use
exactCurrentTime,exactDuration, andexactPlayedPercentinstead. - Deprecated convenience methods remain available in v22 and are scheduled for
removal in v23:
mute(),unmute(),toggleMute(),resetPlaybackRate(),increasePlaybackRate(),decreasePlaybackRate(),enableLoop(),disableLoop(), andtoggleLoop().
Compatibility Notes
- Angular:
>=22.0.0 <23.0.0 - Node.js:
^22.22.3 || ^24.15.0 || >=26.0.0 provideHttpClient()is required by the current waveform loader.- Large audio files are downloaded and decoded in the browser for waveform generation. Prefer smaller preview files for long podcasts or many players on one page.
Contributing
We welcome contributions! Please feel free to submit issues and pull requests.
License
MIT License - see LICENSE file for details.
Support
- 📧 Email: [email protected]
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
Made with ❤️ by Joldibaev Nurlan
