- Created a new PostCSS configuration file to integrate Tailwind CSS. - Added a skills lock file containing various Expo skills with their respective source and computed hashes.
133 lines
3.6 KiB
Markdown
133 lines
3.6 KiB
Markdown
# Migrating from expo-av to expo-audio
|
|
|
|
## Imports
|
|
|
|
```tsx
|
|
// Before
|
|
import { Audio } from 'expo-av';
|
|
|
|
// After
|
|
import { useAudioPlayer, useAudioRecorder, RecordingPresets, AudioModule, setAudioModeAsync } from 'expo-audio';
|
|
```
|
|
|
|
## Audio Playback
|
|
|
|
### Before (expo-av)
|
|
|
|
```tsx
|
|
const [sound, setSound] = useState<Audio.Sound>();
|
|
|
|
async function playSound() {
|
|
const { sound } = await Audio.Sound.createAsync(require('./audio.mp3'));
|
|
setSound(sound);
|
|
await sound.playAsync();
|
|
}
|
|
|
|
useEffect(() => {
|
|
return sound ? () => { sound.unloadAsync(); } : undefined;
|
|
}, [sound]);
|
|
```
|
|
|
|
### After (expo-audio)
|
|
|
|
```tsx
|
|
const player = useAudioPlayer(require('./audio.mp3'));
|
|
|
|
// Play
|
|
player.play();
|
|
```
|
|
|
|
## Audio Recording
|
|
|
|
### Before (expo-av)
|
|
|
|
```tsx
|
|
const [recording, setRecording] = useState<Audio.Recording>();
|
|
|
|
async function startRecording() {
|
|
await Audio.requestPermissionsAsync();
|
|
await Audio.setAudioModeAsync({ allowsRecordingIOS: true, playsInSilentModeIOS: true });
|
|
const { recording } = await Audio.Recording.createAsync(Audio.RecordingOptionsPresets.HIGH_QUALITY);
|
|
setRecording(recording);
|
|
}
|
|
|
|
async function stopRecording() {
|
|
await recording?.stopAndUnloadAsync();
|
|
const uri = recording?.getURI();
|
|
}
|
|
```
|
|
|
|
### After (expo-audio)
|
|
|
|
```tsx
|
|
const recorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
|
|
|
|
async function startRecording() {
|
|
await AudioModule.requestRecordingPermissionsAsync();
|
|
await recorder.prepareToRecordAsync();
|
|
recorder.record();
|
|
}
|
|
|
|
async function stopRecording() {
|
|
await recorder.stop();
|
|
const uri = recorder.uri;
|
|
}
|
|
```
|
|
|
|
## Audio Mode
|
|
|
|
### Before (expo-av)
|
|
|
|
```tsx
|
|
await Audio.setAudioModeAsync({
|
|
allowsRecordingIOS: true,
|
|
playsInSilentModeIOS: true,
|
|
staysActiveInBackground: true,
|
|
interruptionModeIOS: InterruptionModeIOS.DoNotMix,
|
|
});
|
|
```
|
|
|
|
### After (expo-audio)
|
|
|
|
```tsx
|
|
await setAudioModeAsync({
|
|
playsInSilentMode: true,
|
|
shouldPlayInBackground: true,
|
|
interruptionMode: 'doNotMix',
|
|
});
|
|
```
|
|
|
|
## API Mapping
|
|
|
|
| expo-av | expo-audio |
|
|
|---------|------------|
|
|
| `Audio.Sound.createAsync()` | `useAudioPlayer(source)` |
|
|
| `sound.playAsync()` | `player.play()` |
|
|
| `sound.pauseAsync()` | `player.pause()` |
|
|
| `sound.setPositionAsync(ms)` | `player.seekTo(seconds)` |
|
|
| `sound.setVolumeAsync(vol)` | `player.volume = vol` |
|
|
| `sound.setRateAsync(rate)` | `player.playbackRate = rate` |
|
|
| `sound.setIsLoopingAsync(loop)` | `player.loop = loop` |
|
|
| `sound.unloadAsync()` | Automatic via hook |
|
|
| `playbackStatus.positionMillis` | `player.currentTime` (seconds) |
|
|
| `playbackStatus.durationMillis` | `player.duration` (seconds) |
|
|
| `playbackStatus.isPlaying` | `player.playing` |
|
|
| `Audio.Recording.createAsync()` | `useAudioRecorder(preset)` |
|
|
| `Audio.RecordingOptionsPresets.*` | `RecordingPresets.*` |
|
|
| `recording.stopAndUnloadAsync()` | `recorder.stop()` |
|
|
| `recording.getURI()` | `recorder.uri` |
|
|
| `Audio.requestPermissionsAsync()` | `AudioModule.requestRecordingPermissionsAsync()` |
|
|
|
|
## Key Differences
|
|
|
|
- **No auto-reset on finish**: After `play()` completes, the player stays paused at the end. To replay, call `player.seekTo(0)` then `play()`
|
|
- **Time in seconds**: expo-audio uses seconds, not milliseconds (matching web standards)
|
|
- **Immediate loading**: Audio loads immediately when the hook mounts—no explicit preloading needed
|
|
- **Automatic cleanup**: No need to call `unloadAsync()`, hooks handle resource cleanup on unmount
|
|
- **Multiple players**: Create multiple `useAudioPlayer` instances and store them—all load immediately
|
|
- **Direct property access**: Set volume, rate, loop directly on the player object (`player.volume = 0.5`)
|
|
|
|
## API Reference
|
|
|
|
https://docs.expo.dev/versions/latest/sdk/audio/
|