Skip to main content
Helios supports multiple audio tracks with individual volume and mute controls.

AudioTrackMetadata

Interface describing an audio track.
interface AudioTrackMetadata {
  id: string;
  src: string;
  startTime: number;         // seconds
  duration: number;          // seconds
  fadeInDuration?: number;   // seconds
  fadeOutDuration?: number;  // seconds
  fadeEasing?: string;
}

AudioTrackState

Interface for audio track playback state.
interface AudioTrackState {
  volume: number;  // 0.0 to 1.0
  muted: boolean;
}

Setting up audio tracks

Via constructor

import { Helios } from '@heliosvideo/core';

const helios = new Helios({
  duration: 30,
  fps: 30,
  audioTracks: {
    'music': { volume: 0.7, muted: false },
    'voiceover': { volume: 1.0, muted: false },
  },
  availableAudioTracks: [
    {
      id: 'music',
      src: '/audio/background-music.mp3',
      startTime: 0,
      duration: 30,
      fadeInDuration: 2,
      fadeOutDuration: 2,
    },
    {
      id: 'voiceover',
      src: '/audio/narration.mp3',
      startTime: 3,
      duration: 25,
    },
  ],
});

Headless environments

In headless environments (like server-side rendering), manually set available tracks:
helios.setAvailableAudioTracks([
  {
    id: 'track-1',
    src: '/audio/track1.mp3',
    startTime: 0,
    duration: 30,
  },
]);

Controlling audio tracks

Master volume and mute

// Set master volume
helios.setAudioVolume(0.8);

// Mute all audio
helios.setAudioMuted(true);

// Unmute
helios.setAudioMuted(false);

Per-track volume and mute

// Set track volume
helios.setAudioTrackVolume('music', 0.5);
helios.setAudioTrackVolume('voiceover', 1.0);

// Mute specific track
helios.setAudioTrackMuted('music', true);

// Unmute specific track
helios.setAudioTrackMuted('music', false);

Accessing audio tracks

Get available tracks

// Get all available tracks
const tracks = helios.availableAudioTracks.value;

// Subscribe to track changes
helios.availableAudioTracks.subscribe((tracks) => {
  console.log('Available tracks:', tracks);
});

Get track state

// Get all track states
const trackStates = helios.audioTracks.value;

// Get specific track state
const musicState = trackStates['music'];
console.log(`Music volume: ${musicState.volume}, muted: ${musicState.muted}`);

// Subscribe to state changes
helios.audioTracks.subscribe((states) => {
  Object.entries(states).forEach(([id, state]) => {
    console.log(`Track ${id}: volume=${state.volume}, muted=${state.muted}`);
  });
});

Audio context and nodes

Get audio context

const audioContext = await helios.getAudioContext();

if (audioContext) {
  // Use for audio visualization, processing, etc.
  const analyser = audioContext.createAnalyser();
  analyser.fftSize = 2048;
}

Get audio source node

const sourceNode = await helios.getAudioSourceNode('music');

if (sourceNode && audioContext) {
  // Connect to analyser for visualization
  const analyser = audioContext.createAnalyser();
  sourceNode.connect(analyser);
  
  // Get frequency data
  const bufferLength = analyser.frequencyBinCount;
  const dataArray = new Uint8Array(bufferLength);
  analyser.getByteFrequencyData(dataArray);
}

Complete example

import { Helios } from '@heliosvideo/core';

const helios = new Helios({
  duration: 60,
  fps: 30,
  audioTracks: {
    'background-music': { volume: 0.6, muted: false },
    'sound-effects': { volume: 0.8, muted: false },
    'voiceover': { volume: 1.0, muted: false },
  },
  availableAudioTracks: [
    {
      id: 'background-music',
      src: '/audio/music.mp3',
      startTime: 0,
      duration: 60,
      fadeInDuration: 3,
      fadeOutDuration: 3,
    },
    {
      id: 'sound-effects',
      src: '/audio/effects.mp3',
      startTime: 0,
      duration: 60,
    },
    {
      id: 'voiceover',
      src: '/audio/narration.mp3',
      startTime: 5,
      duration: 50,
    },
  ],
});

// Create audio mixer UI
function createAudioMixer() {
  const tracks = helios.availableAudioTracks.value;
  
  tracks.forEach((track) => {
    const state = helios.audioTracks.value[track.id];
    
    createTrackControl({
      id: track.id,
      label: track.id,
      volume: state?.volume ?? 1.0,
      muted: state?.muted ?? false,
      onVolumeChange: (volume) => {
        helios.setAudioTrackVolume(track.id, volume);
      },
      onMuteToggle: (muted) => {
        helios.setAudioTrackMuted(track.id, muted);
      },
    });
  });
}

// Ducking: Lower music volume when voiceover plays
helios.subscribe((state) => {
  const currentTime = state.currentTime;
  const voiceoverTrack = state.availableAudioTracks.find(
    (t) => t.id === 'voiceover'
  );
  
  if (voiceoverTrack) {
    const voiceoverActive =
      currentTime >= voiceoverTrack.startTime &&
      currentTime < voiceoverTrack.startTime + voiceoverTrack.duration;
    
    // Duck background music when voiceover is active
    const musicVolume = voiceoverActive ? 0.3 : 0.6;
    helios.setAudioTrackVolume('background-music', musicVolume);
  }
});

// Audio visualization
async function setupVisualization() {
  const audioContext = await helios.getAudioContext();
  const musicNode = await helios.getAudioSourceNode('background-music');
  
  if (audioContext && musicNode) {
    const analyser = audioContext.createAnalyser();
    analyser.fftSize = 256;
    musicNode.connect(analyser);
    
    const bufferLength = analyser.frequencyBinCount;
    const dataArray = new Uint8Array(bufferLength);
    
    function draw() {
      analyser.getByteFrequencyData(dataArray);
      renderVisualization(dataArray);
      requestAnimationFrame(draw);
    }
    
    draw();
  }
}

Audio fades

Audio tracks support automatic fade-in and fade-out:
const helios = new Helios({
  duration: 30,
  fps: 30,
  availableAudioTracks: [
    {
      id: 'music',
      src: '/audio/track.mp3',
      startTime: 0,
      duration: 30,
      fadeInDuration: 2,    // 2 second fade in
      fadeOutDuration: 3,   // 3 second fade out
      fadeEasing: 'linear', // Optional easing
    },
  ],
});
Fades are handled automatically by the DomDriver when using the browser runtime.

Build docs developers (and LLMs) love