145 lines
4.2 KiB
Markdown
145 lines
4.2 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/
|