Kurs React Native · Moduł 6: Zdjęcia, kamera i dźwięk
expo-av - Audio i Video
W tej lekcji5
Odtwarzaj audio i video w swojej aplikacji!
Instalacja
npx expo install expo-avOdtwarzanie video
import { Video, ResizeMode } from 'expo-av';
import { useState, useRef } from 'react';
function VideoPlayer() {
const videoRef = useRef<Video>(null);
const [status, setStatus] = useState<any>({});
return (
<View style={styles.container}>
<Video
ref={videoRef}
style={styles.video}
source={{ uri: 'https://example.com/video.mp4' }}
useNativeControls
resizeMode={ResizeMode.CONTAIN}
isLooping
onPlaybackStatusUpdate={(status) => setStatus(() => status)}
/>
<View style={styles.controls}>
<Pressable
onPress={() =>
status.isPlaying
? videoRef.current?.pauseAsync()
: videoRef.current?.playAsync()
}
>
<Ionicons
name={status.isPlaying ? 'pause' : 'play'}
size={32}
/>
</Pressable>
</View>
</View>
);
}Odtwarzanie audio
import { Audio } from 'expo-av';
function AudioPlayer() {
const [sound, setSound] = useState<Audio.Sound>();
const [isPlaying, setIsPlaying] = useState(false);
const playSound = async () => {
const { sound } = await Audio.Sound.createAsync(
require('@/assets/audio/ocean.mp3')
);
setSound(sound);
await sound.playAsync();
setIsPlaying(true);
};
const pauseSound = async () => {
if (sound) {
await sound.pauseAsync();
setIsPlaying(false);
}
};
// Cleanup
useEffect(() => {
return sound
? () => {
sound.unloadAsync();
}
: undefined;
}, [sound]);
return (
<Pressable onPress={isPlaying ? pauseSound : playSound}>
<Ionicons name={isPlaying ? 'pause' : 'play'} size={48} />
</Pressable>
);
}Audio w tle
import { Audio } from 'expo-av';
async function setupAudio() {
await Audio.setAudioModeAsync({
playsInSilentModeIOS: true,
staysActiveInBackground: true,
shouldDuckAndroid: true,
});
}Nagrywanie audio
import { Audio } from 'expo-av';
function AudioRecorder() {
const [recording, setRecording] = useState<Audio.Recording>();
const [recordingUri, setRecordingUri] = useState<string>();
const startRecording = async () => {
try {
const permission = await Audio.requestPermissionsAsync();
if (!permission.granted) return;
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
});
const { recording } = await Audio.Recording.createAsync(
Audio.RecordingOptionsPresets.HIGH_QUALITY
);
setRecording(recording);
} catch (error) {
console.error('Błąd nagrywania:', error);
}
};
const stopRecording = async () => {
if (!recording) return;
await recording.stopAndUnloadAsync();
const uri = recording.getURI();
setRecordingUri(uri ?? undefined);
setRecording(undefined);
};
return (
<View>
<Pressable
onPress={recording ? stopRecording : startRecording}
style={[styles.recordButton, recording && styles.recording]}
>
<Ionicons name={recording ? 'stop' : 'mic'} size={32} color="white" />
</Pressable>
{recordingUri && <Text>Nagrano: {recordingUri}</Text>}
</View>
);
}expo-av obsługuje wszystkie potrzeby audio/video!
Kod do tej lekcji: App.tsx
import React, { useState, useEffect } from 'react';
import { View, Text, Pressable, StyleSheet } from 'react-native';
import { Audio } from 'expo-av';
export default function App() {
const [sound, setSound] = useState<Audio.Sound>();
const [isPlaying, setIsPlaying] = useState(false);
const playSound = async () => {
// TODO: utwórz dźwięk za pomocą Audio.Sound.createAsync(...)
// - przekaż { uri: 'https://example.com/ocean.mp3' } jako source
// - rozpakuj wynik: const { sound } = await Audio.Sound.createAsync(...)
// - zapisz go: setSound(sound)
// - uruchom odtwarzanie: await sound.playAsync()
// - ustaw setIsPlaying(true)
};
const pauseSound = async () => {
if (sound) {
await sound.pauseAsync();
setIsPlaying(false);
}
};
// Zwalnianie zasobu dźwięku przy odmontowaniu
useEffect(() => {
return sound ? () => { sound.unloadAsync(); } : undefined;
}, [sound]);
return (
<View style={styles.container}>
<Text style={styles.title}>Dźwięki Atlantydy</Text>
<Pressable
style={styles.button}
onPress={isPlaying ? pauseSound : playSound}
>
<Text style={styles.buttonText}>{isPlaying ? 'Pauza' : 'Odtwórz'}</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#1a5276' },
title: { color: '#aed6f1', fontSize: 20, marginBottom: 24 },
button: { backgroundColor: '#2980b9', paddingVertical: 14, paddingHorizontal: 40, borderRadius: 8 },
buttonText: { color: '#fff', fontSize: 16, fontWeight: '600' },
});Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Który prop włącza natywne kontrolki w komponencie Video?
Zadania praktyczne w grze
- Klikanie w kolejności
Kliknij elementy tworzenia dźwięku:
- Edytor kodu
Uzupełnij kod Audio.Sound z play/pause.