Skip to content

Instantly share code, notes, and snippets.

@ajsmth
Created April 29, 2021 21:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ajsmth/299d3530d55f95c65c59ecc4277b8c3e to your computer and use it in GitHub Desktop.
Save ajsmth/299d3530d55f95c65c59ecc4277b8c3e to your computer and use it in GitHub Desktop.
Expo Camera Codec
import { Camera } from 'expo-camera';
import React, { useState, useEffect, useRef } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
SafeAreaView,
Alert,
ScrollView,
} from 'react-native';
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [type] = useState(Camera.Constants.Type.back);
const camera = useRef<Camera | null>(null);
const [isRecording, setIsRecording] = useState(false);
const [selectedCodec, setSelectedCodec] = useState();
const [availableCodecs, setAvilableCodecs] = useState([]);
useEffect(() => {
(async () => {
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === 'granted');
const codecs = await Camera.getAvailableVideoCodecsAsync();
setAvilableCodecs(codecs);
console.log({ codecs });
})();
}, []);
async function onRecordPress() {
if (isRecording) {
camera.current?.stopRecording();
} else {
setIsRecording(true);
camera.current
?.recordAsync({ codec: selectedCodec })
.then(recording => {
setIsRecording(false);
Alert.alert(JSON.stringify(recording, null, '\t'));
})
.catch(error => {
setIsRecording(false);
console.log({ error });
Alert.alert(`${error.message}\nAvailable codes: ${availableCodecs}`);
});
}
}
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<SafeAreaView style={styles.container}>
<ScrollView style={{ flex: 1 }}>
<Camera style={styles.camera} type={type} ref={camera} />
<View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
<SelectCodec
text="H264"
isActive={selectedCodec === Camera.Constants.VideoCodec.H264}
onSelect={() => setSelectedCodec(Camera.Constants.VideoCodec.H264)}
/>
<SelectCodec
text="HEVC"
isActive={selectedCodec === Camera.Constants.VideoCodec.HEVC}
onSelect={() => setSelectedCodec(Camera.Constants.VideoCodec.HEVC)}
/>
<SelectCodec
text="JPEG"
isActive={selectedCodec === Camera.Constants.VideoCodec.JPEG}
onSelect={() => setSelectedCodec(Camera.Constants.VideoCodec.JPEG)}
/>
<SelectCodec
text="AppleProRes422"
isActive={selectedCodec === Camera.Constants.VideoCodec.AppleProRes422}
onSelect={() => setSelectedCodec(Camera.Constants.VideoCodec.AppleProRes422)}
/>
<SelectCodec
text="AppleProRes4444"
isActive={selectedCodec === Camera.Constants.VideoCodec.AppleProRes4444}
onSelect={() => setSelectedCodec(Camera.Constants.VideoCodec.AppleProRes4444)}
/>
</View>
<View style={{ height: 60, marginVertical: 12 }}>
<TouchableOpacity style={styles.button} onPress={onRecordPress}>
<Text style={styles.text}> {isRecording ? 'Stop' : 'Start'} Recording </Text>
</TouchableOpacity>
</View>
</ScrollView>
</SafeAreaView>
);
}
function SelectCodec({ text, onSelect, isActive }) {
return (
<TouchableOpacity
style={{
margin: 4,
padding: 4,
borderWidth: isActive ? 0 : 1,
flex: 1,
height: 50,
minWidth: '33%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: isActive ? 'coral' : 'white',
}}
onPress={onSelect}>
<Text
style={{
textAlign: 'center',
color: isActive ? 'white' : 'black',
fontWeight: '600',
fontSize: 16,
}}>
{text}
</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
camera: {
height: 400,
marginBottom: 16,
},
button: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
borderWidth: 1,
},
text: {
fontSize: 16,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment