ngx-audio-wave

June 11, 2026 ยท View on GitHub

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

Audio Wave Demo

Quick Start

Installation

npm install ngx-audio-wave

Angular 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

KeyAction
Space or EnterPlay/Pause audio
Arrow LeftSkip backward (configurable with skip)
Arrow RightSkip forward (configurable with skip)
HomeJump to beginning
EndJump 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

PropertyTypeDefaultDescription
audioSrcstring | SafeUrlRequiredURL or SafeUrl of the audio file to play
colorstring'#1e90ff'Color of the audio wave bars
heightnumber25Height of the wave visualization in pixels
gapnumber5Gap between wave bars in pixels
samplesnumber50Number of waveform bars
roundedbooleantrueWhether to round the corners of wave bars
hideBtnbooleanfalseHide the play/pause button
skipnumber5Seconds to skip when using arrow keys
volumenumber1Initial volume level (0-1)
playbackRatenumber1Initial playback speed (0.25-4)
loopbooleanfalseWhether to loop the audio
ariaLabelstring'Audio player'Main ARIA label for the component
playButtonLabelstring'Play audio'ARIA label for the play button
pauseButtonLabelstring'Pause audio'ARIA label for the pause button
progressBarLabelstring'Audio progress bar'ARIA label for the progress bar

Output Properties (Signals)

PropertyTypeDescription
isPausedSignal<boolean>Whether the audio is currently paused
isLoadingSignal<boolean>Whether the audio is currently loading
hasErrorSignal<boolean>Whether there was an error loading the audio
currentVolumeSignal<number>Current volume level (0-1)
currentPlaybackRateSignal<number>Current playback speed (0.25-4)
isLoopingSignal<boolean>Whether the audio is currently looping
exactCurrentTimeSignal<number>Current playback time in seconds (exact)
exactDurationSignal<number>Total duration in seconds (exact)
exactPlayedPercentSignal<number>Playback progress as percentage (exact)
progressTextSignal<string>Human-readable progress text for screen readers
statusTextSignal<string>Current status text for screen readers

Methods

MethodParametersDescription
play(time?: number)time?: numberPlay the audio, optionally from a specific time
pause()-Pause the audio
stop()-Stop the audio and reset to beginning
setVolume(volume)volume: numberSet 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: numberSet 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: booleanEnable 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, and playedPercent.
  • Use exactCurrentTime, exactDuration, and exactPlayedPercent instead.
  • Deprecated convenience methods remain available in v22 and are scheduled for removal in v23: mute(), unmute(), toggleMute(), resetPlaybackRate(), increasePlaybackRate(), decreasePlaybackRate(), enableLoop(), disableLoop(), and toggleLoop().

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


Made with โค๏ธ by Joldibaev Nurlan