Track Management
Control individual tracks with mute, solo, volume, and pan controls.
Track Controls Component​
Enable the built-in track controls panel:
<WaveformPlaylistProvider
tracks={tracks}
controls={{ show: true, width: 200 }}
>
<Waveform />
</WaveformPlaylistProvider>
The controls panel displays:
- Track name
- Mute button
- Solo button
- Volume slider
- Pan slider
Programmatic Track Controls​
Use usePlaylistControls() and usePlaylistData() for custom track control UI:
import { usePlaylistControls, usePlaylistData } from '@waveform-playlist/browser';
function CustomTrackControls({ trackIndex }: { trackIndex: number }) {
const { setTrackMute, setTrackSolo, setTrackVolume, setTrackPan } = usePlaylistControls();
const { trackStates } = usePlaylistData();
const state = trackStates[trackIndex];
if (!state) return null;
return (
<div>
<button onClick={() => setTrackMute(trackIndex, !state.muted)}>
{state.muted ? 'Unmute' : 'Mute'}
</button>
<button onClick={() => setTrackSolo(trackIndex, !state.soloed)}>
{state.soloed ? 'Unsolo' : 'Solo'}
</button>
<input
type="range"
min="0"
max="1"
step="0.01"
value={state.volume}
onChange={(e) => setTrackVolume(trackIndex, parseFloat(e.target.value))}
/>
<input
type="range"
min="-1"
max="1"
step="0.01"
value={state.pan}
onChange={(e) => setTrackPan(trackIndex, parseFloat(e.target.value))}
/>
</div>
);
}
Mute and Solo​
Mute​
Muting a track silences it completely:
const { setTrackMute } = usePlaylistControls();
const { trackStates } = usePlaylistData();
// Toggle mute
setTrackMute(trackIndex, !trackStates[trackIndex].muted);
// Mute track
setTrackMute(trackIndex, true);
// Unmute track
setTrackMute(trackIndex, false);
Solo​
Soloing a track mutes all other non-soloed tracks:
const { setTrackSolo } = usePlaylistControls();
const { trackStates } = usePlaylistData();
// Toggle solo
setTrackSolo(trackIndex, !trackStates[trackIndex].soloed);
When multiple tracks are soloed, only those tracks are audible.
Volume Control​
Volume ranges from 0 (silent) to 1 (full volume):
const { setTrackVolume } = usePlaylistControls();
// Set to 50% volume
setTrackVolume(trackIndex, 0.5);
Pan Control​
Pan ranges from -1 (full left) to 1 (full right):
const { setTrackPan } = usePlaylistControls();
// Pan fully left
setTrackPan(trackIndex, -1);
// Center
setTrackPan(trackIndex, 0);
// Pan fully right
setTrackPan(trackIndex, 1);
Track Selection​
Select tracks for operations like deletion or effects:
import { usePlaylistState, usePlaylistControls, usePlaylistData } from '@waveform-playlist/browser';
function TrackSelector() {
const { tracks } = usePlaylistData();
const { selectedTrackId } = usePlaylistState();
const { setSelectedTrackId } = usePlaylistControls();
return (
<ul>
{tracks.map((track) => (
<li
key={track.id}
onClick={() => setSelectedTrackId(track.id)}
style={{
background: selectedTrackId === track.id ? '#e0e0ff' : 'transparent',
}}
>
{track.name}
</li>
))}
</ul>
);
}
Adding and Removing Tracks​
Track management (adding, removing, reordering) is handled by updating the tracks prop passed to WaveformPlaylistProvider. The provider does not have built-in addTrack / removeTrack / moveTrack methods — you manage tracks in your own state:
import { WaveformPlaylistProvider, Waveform, useAudioTracks } from '@waveform-playlist/browser';
function TrackManagementExample() {
const { tracks: initialTracks, loading } = useAudioTracks([
{ src: '/audio/drums.mp3', name: 'Drums' },
{ src: '/audio/bass.mp3', name: 'Bass' },
]);
const [tracks, setTracks] = useState(initialTracks);
// Update tracks when initial load completes
useEffect(() => {
if (!loading) setTracks(initialTracks);
}, [initialTracks, loading]);
const removeTrack = (index: number) => {
setTracks((prev) => prev.filter((_, i) => i !== index));
};
const moveTrack = (fromIndex: number, toIndex: number) => {
setTracks((prev) => {
const next = [...prev];
const [moved] = next.splice(fromIndex, 1);
next.splice(toIndex, 0, moved);
return next;
});
};
if (loading) return <div>Loading...</div>;
return (
<WaveformPlaylistProvider tracks={tracks}>
<Waveform />
</WaveformPlaylistProvider>
);
}
Initial Track Configuration​
Set initial track states when loading:
const { tracks, loading } = useAudioTracks([
{
src: '/audio/drums.mp3',
name: 'Drums',
volume: 0.8, // 80% volume
muted: false,
soloed: false,
pan: 0, // Center
},
{
src: '/audio/bass.mp3',
name: 'Bass',
volume: 1.0, // Full volume
muted: false,
soloed: false,
pan: -0.3, // Slightly left
},
{
src: '/audio/keys.mp3',
name: 'Keys',
volume: 0.7,
muted: true, // Start muted
soloed: false,
pan: 0.3, // Slightly right
},
]);
Complete Example​
import {
WaveformPlaylistProvider,
Waveform,
useAudioTracks,
usePlaylistControls,
usePlaylistData,
} from '@waveform-playlist/browser';
function TrackControlRow({ trackIndex }: { trackIndex: number }) {
const { trackStates } = usePlaylistData();
const { setTrackMute, setTrackSolo, setTrackVolume, setTrackPan } = usePlaylistControls();
const state = trackStates[trackIndex];
if (!state) return null;
return (
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center', padding: '0.5rem' }}>
<span style={{ width: '100px' }}>{state.name}</span>
<button
onClick={() => setTrackMute(trackIndex, !state.muted)}
style={{ background: state.muted ? '#ff6b6b' : '#e0e0e0' }}
>
M
</button>
<button
onClick={() => setTrackSolo(trackIndex, !state.soloed)}
style={{ background: state.soloed ? '#ffd93d' : '#e0e0e0' }}
>
S
</button>
<label>
Vol
<input
type="range"
min="0"
max="1"
step="0.01"
value={state.volume}
onChange={(e) => setTrackVolume(trackIndex, parseFloat(e.target.value))}
/>
</label>
<label>
Pan
<input
type="range"
min="-1"
max="1"
step="0.01"
value={state.pan}
onChange={(e) => setTrackPan(trackIndex, parseFloat(e.target.value))}
/>
</label>
</div>
);
}
function TrackManagementExample() {
const { tracks, loading } = useAudioTracks([
{ src: '/audio/drums.mp3', name: 'Drums' },
{ src: '/audio/bass.mp3', name: 'Bass' },
{ src: '/audio/vocals.mp3', name: 'Vocals' },
]);
if (loading) return <div>Loading...</div>;
return (
<WaveformPlaylistProvider tracks={tracks} timescale>
<div>
{tracks.map((_, index) => (
<TrackControlRow key={index} trackIndex={index} />
))}
</div>
<Waveform />
</WaveformPlaylistProvider>
);
}
Next Steps​
- Annotations - Add time-synchronized annotations
- Audio Effects - Apply effects to tracks