audio Stable WINMACLNX
Play audio files from disk via the OS audio stack (rodio + symphonia). Supports MP3, FLAC, OGG Vorbis, and WAV.
Capability
veloxkit.config.json
{
"capabilities": ["audio"]
}Import
import { audio } from 'veloxkit'audio.play(src, opts?)
Starts playback and returns a player handle for all subsequent control.
const player = await audio.play('/path/to/track.mp3', {
volume: 0.8, // 0.0 – 1.0, default 1.0
onEnded: () => { // optional: fires when playback finishes naturally
console.log('done')
},
})Player handle
| Method | Returns | Description |
|---|---|---|
player.pause() | void | Pause playback |
player.resume() | void | Resume from pause |
player.play() | void | Alias for resume() |
player.stop() | void | Stop and release the sink |
player.setVolume(v) | void | Set volume 0.0 – 1.0 |
player.getVolume() | number | Current volume |
player.getTime() | number | Playback position in seconds |
player.getDuration() | Promise<number> | Total duration in seconds; -1 if unknown |
player.seek(secs) | Promise<void> | Jump to position |
player.onEnded(cb) | void | Register an additional end callback |
Supported formats
| Format | Extensions |
|---|---|
| MP3 | .mp3 |
| FLAC | .flac |
| OGG Vorbis | .ogg |
| WAV / PCM | .wav |
Examples
Basic play / stop
import { audio } from 'veloxkit'
import { View, Pressable, Text } from 'veloxkit'
import { useRef } from 'react'
function SoundButton() {
const playerRef = useRef(null)
return (
<View style={{ flexDirection: 'row', gap: 8 }}>
<Pressable
onPress={async () => {
playerRef.current = await audio.play('/assets/sounds/click.wav', { volume: 0.6 })
}}
style={{ padding: 12, backgroundColor: '#3a3a5e', borderRadius: 8 }}
>
<Text>Play</Text>
</Pressable>
<Pressable
onPress={() => playerRef.current?.stop()}
style={{ padding: 12, backgroundColor: '#3a3a5e', borderRadius: 8 }}
>
<Text>Stop</Text>
</Pressable>
</View>
)
}Music player with live progress
import { audio } from 'veloxkit'
import { useState, useRef, useEffect } from 'react'
function MusicPlayer({ src }: { src: string }) {
const playerRef = useRef(null)
const [playing, setPlaying] = useState(false)
const [position, setPosition] = useState(0)
const [duration, setDuration] = useState(0)
const handlePlay = async () => {
const p = await audio.play(src, {
onEnded: () => { setPlaying(false); setPosition(0) },
})
playerRef.current = p
setPlaying(true)
setDuration(await p.getDuration())
}
// Poll position every 250 ms while playing
useEffect(() => {
if (!playing) return
const id = setInterval(() => {
setPosition(playerRef.current?.getTime() ?? 0)
}, 250)
return () => clearInterval(id)
}, [playing])
return (
<View style={{ gap: 12, padding: 16 }}>
<Text>
{playing ? `${position.toFixed(1)} / ${duration.toFixed(1)} s` : 'Stopped'}
</Text>
<Pressable
onPress={playing ? () => playerRef.current?.pause() : handlePlay}
style={{ padding: 12, backgroundColor: '#4a4a7e', borderRadius: 8 }}
>
<Text>{playing ? 'Pause' : 'Play'}</Text>
</Pressable>
</View>
)
}Auto-advance playlist
function playPlaylist(tracks: string[], index = 0) {
if (index >= tracks.length) return
audio.play(tracks[index], {
onEnded: () => playPlaylist(tracks, index + 1),
})
}
playPlaylist(['/music/intro.mp3', '/music/loop.mp3', '/music/outro.mp3'])Fade out before stopping
async function fadeOut(player, durationMs = 1000) {
const steps = 20
const stepMs = durationMs / steps
const start = player.getVolume()
for (let i = steps; i >= 0; i--) {
player.setVolume((start * i) / steps)
await new Promise(r => setTimeout(r, stepMs))
}
player.stop()
}The audio device is opened lazily on the first audio.play() call. If no audio output is available the Promise rejects with a descriptive error.
⚠️
File paths must be absolute. The audio subsystem reads the file directly without the fs capability — but the file must exist at the given path.