CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-h5-audio-player

A customizable React audio player component with TypeScript support, mobile compatibility, and comprehensive accessibility features

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

advanced-features-mse.mddocs/

Advanced Features & MSE

Media Source Extensions (MSE), Encrypted Media Extensions (EME) support, utility functions, and advanced audio features for streaming and encrypted content.

Capabilities

Media Source Extensions (MSE) Support

Support for Media Source Extensions allowing for advanced streaming capabilities and custom media handling.

interface MSEPropsObject {
  /** Custom seek handler for MSE streams */
  onSeek: OnSeek;
  /** Handler for encrypted media events */
  onEcrypted?: (e: unknown) => void;
  /** Total duration of the source in seconds (required for MSE) */
  srcDuration: number;
}

type OnSeek = (audio: HTMLAudioElement, time: number) => Promise<void>;

When MSE configuration is provided:

  • The onSeek function handles all seeking operations instead of standard currentTime setting
  • srcDuration is used to display total duration instead of audio.duration
  • onEcrypted handles Encrypted Media Extensions (EME) events
  • Progress bar and duration display adapt to work with MSE streams

Component Instance Access

Access to the underlying HTML audio element and component methods for advanced control.

Component Instance Methods

Methods available on the H5AudioPlayer component instance for programmatic control.

class H5AudioPlayer extends Component<PlayerProps> {
  /** Toggle between play and pause states */
  togglePlay(e: React.SyntheticEvent): void;
  
  /** Safely play audio with promise-based error handling */
  playAudioPromise(): void;
  
  /** Check if audio is currently playing */
  isPlaying(): boolean;
  
  /** Reference to the underlying HTML audio element */
  audio: React.RefObject<HTMLAudioElement>;
  
  /** Reference to the progress bar container */
  progressBar: React.RefObject<HTMLDivElement>;
  
  /** Reference to the main player container */
  container: React.RefObject<HTMLDivElement>;
}

Error Handling

Advanced error handling for playback and seeking operations.

interface ErrorHandlers {
  /** Called when audio.play() promise is rejected */
  onPlayError?: (err: Error) => void;
  
  /** Called when currentTime change operations fail */
  onChangeCurrentTimeError?: (err: Error) => void;
}

Common error scenarios:

  • Browser autoplay policy violations
  • Network connectivity issues during streaming
  • Codec compatibility problems
  • MSE/EME setup failures

Performance Configuration

Fine-tune performance and responsiveness through various timing configurations.

interface PerformanceConfig {
  /** Frequency of progress bar updates in milliseconds */
  progressUpdateInterval?: number;
  
  /** Frequency of onListen event firing in milliseconds */
  listenInterval?: number;
  
  /** Jump distance for keyboard/button controls in milliseconds */
  progressJumpStep?: number;
  
  /** Separate jump distances for backward/forward */
  progressJumpSteps?: {
    backward?: number;
    forward?: number;
  };
  
  /** Volume increment for volume controls */
  volumeJumpStep?: number;
}

Performance Recommendations:

  • Lower progressUpdateInterval (10-50ms) for smoother progress bars
  • Higher listenInterval (500-2000ms) for less frequent position tracking
  • Adjust jump steps based on content type (music vs podcasts vs audiobooks)

Usage Examples

MSE Configuration for Streaming:

import AudioPlayer from 'react-h5-audio-player';

const streamingPlayer = () => {
  const handleMSESeek = async (audio: HTMLAudioElement, time: number) => {
    // Custom seek implementation for MSE
    try {
      await myStreamingService.seekTo(time);
      // Update UI to reflect new position
      console.log(`Seeking to ${time} seconds`);
    } catch (error) {
      console.error('Seek failed:', error);
    }
  };

  const handleEncrypted = (e: unknown) => {
    // Handle EME for encrypted content
    console.log('Encrypted media detected', e);
    // Setup MediaKeys, licenses, etc.
  };

  return (
    <AudioPlayer
      src="blob:https://example.com/stream"
      mse={{
        onSeek: handleMSESeek,
        onEcrypted: handleEncrypted,
        srcDuration: 3600 // 1 hour in seconds
      }}
      onError={(e) => console.error('Streaming error:', e)}
    />
  );
};

Custom Error Handling:

<AudioPlayer
  src="audio.mp3"
  onPlayError={(err) => {
    console.error('Playback failed:', err);
    // Show user-friendly error message
    if (err.message.includes('NotAllowedError')) {
      alert('Please click play to start audio (browser autoplay policy)');
    }
  }}
  onChangeCurrentTimeError={(err) => {
    console.error('Seek failed:', err);
    // Handle seek failures gracefully
  }}
  onError={(e) => {
    const audio = e.target as HTMLAudioElement;
    if (audio.error) {
      switch (audio.error.code) {
        case MediaError.MEDIA_ERR_NETWORK:
          console.error('Network error loading audio');
          break;
        case MediaError.MEDIA_ERR_DECODE:
          console.error('Audio decoding error');
          break;
        case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
          console.error('Audio format not supported');
          break;
        default:
          console.error('Unknown audio error');
      }
    }
  }}
/>

Performance Tuning:

<AudioPlayer
  src="audio.mp3" 
  progressUpdateInterval={20}  // Smooth 50fps progress updates
  listenInterval={250}         // Position tracking 4x per second
  progressJumpStep={10000}     // 10 second jumps
  progressJumpSteps={{
    backward: 15000,           // 15 second rewind
    forward: 30000             // 30 second skip forward
  }}
  volumeJumpStep={0.1}         // 10% volume increments
/>

Programmatic Control:

import React, { useRef, useEffect } from 'react';
import AudioPlayer from 'react-h5-audio-player';

const ControlledPlayer = () => {
  const playerRef = useRef<AudioPlayer>(null);

  useEffect(() => {
    // Example: Auto-play after 3 seconds
    const timer = setTimeout(() => {
      if (playerRef.current) {
        playerRef.current.playAudioPromise();
      }
    }, 3000);

    return () => clearTimeout(timer);
  }, []);

  const handleExternalPlay = () => {
    if (playerRef.current) {
      playerRef.current.togglePlay({} as React.SyntheticEvent);
    }
  };

  const checkPlayingStatus = () => {
    if (playerRef.current) {
      const isPlaying = playerRef.current.isPlaying();
      console.log('Currently playing:', isPlaying);
    }
  };

  return (
    <div>
      <AudioPlayer
        ref={playerRef}
        src="audio.mp3"
      />
      <button onClick={handleExternalPlay}>
        External Play/Pause
      </button>
      <button onClick={checkPlayingStatus}>
        Check Status
      </button>
    </div>
  );
};

Custom Time Display:

// The utility functions are internal to the component and not exported
// Time formatting is handled automatically by the component based on timeFormat prop

<AudioPlayer
  src="audio.mp3"
  timeFormat="mm:ss"  // or "hh:mm:ss" or "auto"
  onListen={(e) => {
    const audio = e.target as HTMLAudioElement;
    console.log('Position update:', audio.currentTime);
    // Custom logic for position tracking
  }}
/>

Advanced Accessibility:

<AudioPlayer
  src="podcast.mp3"
  i18nAriaLabels={{
    player: 'Podcast Player',
    progressControl: 'Playback progress, use arrow keys to seek',
    volumeControl: 'Volume control, use arrow keys to adjust',
    play: 'Play podcast',
    pause: 'Pause podcast',
    rewind: 'Rewind 15 seconds',
    forward: 'Skip forward 30 seconds'
  }}
  progressJumpSteps={{
    backward: 15000,  // 15s rewind for podcasts
    forward: 30000    // 30s skip for podcasts
  }}
/>

Install with Tessl CLI

npx tessl i tessl/npm-react-h5-audio-player

docs

advanced-features-mse.md

component-props-events.md

index.md

ui-customization-layout.md

tile.json