Audio tracks

A menu to switch between a source's audio languages and descriptions.

import { audioTracks } from "react-video-kit/audio-tracks";

Adds 945 B to a player1.7 KB on its ownSource

Adds an Audio row to the settings menu when a source has more than one audio track. The demo plays an HLS stream with English and Spanish audio. Press play, open the settings menu, and switch. The Spanish track is the same music at a higher pitch, so you'll hear the change.

0:00−0:000:00

Usage

audioTracks() takes no options, and it isn't in defaultPlugins(), so add it yourself:

tsx
import { audioTracks } from "react-video-kit/audio-tracks";import { hls } from "react-video-kit/hls";import { defaultPlugins, VideoPlayer } from "react-video-kit/player";const plugins = [hls(), audioTracks(), ...defaultPlugins()];<VideoPlayer src="/video.m3u8" plugins={plugins} />;

What provides tracks

The plugin doesn't add tracks. It lists what the playing source reports, and the row needs at least two.

  • HLS through hls.js: each TYPE=AUDIO entry in the master playlist is a track. NAME is its label and LANGUAGE its language.
  • DASH through dash.js: each audio track in the manifest. Its first label is the name, or else its language.
  • The browser: with no engine playing, the plugin reads the video element's audioTracks list, which is how Safari's native tracks reach the menu. Where the element has no such list, there's nothing to show.

The demo's playlist has these two lines:

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English",LANGUAGE="en",DEFAULT=YES,AUTOSELECT=YES,URI="audio-en.m3u8"#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="Español",LANGUAGE="es",DEFAULT=NO,AUTOSELECT=YES,URI="audio-es.m3u8"

Build your own control

Tracks are part of the player's media state, so read them with useVideoState, and change them with the plugin's select.

tsx
"use client";import { useCommands, useVideoState } from "react-video-kit";import { audioTracks } from "react-video-kit/audio-tracks";function AudioButtons() {  const tracks = useVideoState((media) => media.audioTracks);  const active = useVideoState((media) => media.audioTrack);  const { select } = useCommands(audioTracks);  return tracks.map((track) => (    <button key={track.id} aria-pressed={track.id === active} onClick={() => select(track.id)}>      {track.label || track.language || track.id}    </button>  ));}

Place the menu yourself

AudioMenu is the row that appears in the settings menu. When you compose your own layout, put it in any menu:

tsx
import * as Video from "react-video-kit";import { AudioMenu } from "react-video-kit/audio-tracks";<Video.Menu>  <Video.MenuTrigger aria-label="Audio">Audio</Video.MenuTrigger>  <Video.MenuContent>    <AudioMenu />  </Video.MenuContent></Video.Menu>;

Behaviour

  • AudioMenu renders nothing with fewer than two tracks.
  • The menu names each track by its label, then its language, then its ID.
  • With an engine, media.audioTrack changes when the engine reports the switch, not when the viewer picks. With the browser's own tracks, it changes straight away.
  • Switching through hls.js keeps playing.
  • The list resets with each new source. The persistence plugin doesn't remember the choice.
  • Subtitles in the same manifest go to the captions menu.

API

Options

This plugin takes no options.

State

This plugin has no state of its own.

Commands

Call them with useCommands(audioTracks).

CommandTypeDescription
select(id: string) => voidSwitches to the audio track with this id.

Parts

PartDescription
AudioMenuRenders nothing unless there's a choice of audio.