React Native Camera可拍照无法录视频的函数式实现问题咨询
问题修复方案
核心问题点
- 状态类型错误:
isRecording初始值为字符串"false",而非布尔值false。非空字符串在布尔判断中为真值,因此!isRecording永远返回false,takeVideo内部逻辑完全不会执行,自然没有任何日志输出。 - 权限缺失:录制视频需要同时获取相机、麦克风权限,当前仅申请了照片存储权限,缺少麦克风权限会直接导致录制失败。
- 交互逻辑不全:仅实现了开始录制逻辑,没有手动停止录制的触发入口,虽然配置了10秒自动停止,但实际使用需要支持手动控制。
修改后代码
import { useState, useRef, useEffect } from 'react'; import { View, TouchableOpacity, Text, StyleSheet, PermissionsAndroid, Platform } from 'react-native'; import { RNCamera } from "react-native-camera"; const App = () => { let [flash, setFlash] = useState("off"); let [zoom, setZoom] = useState(0); let [autoFocus, setAutoFocus] = useState("on"); let [depth, setDepth] = useState(0); let [type, setType] = useState("back"); let [permission, setPermission] = useState("undetermined"); // 修正为布尔值初始值 let [isRecording, setIsRecording] = useState(false); let [recordingOptions, setRecordingOptions] = useState({ mute: false, maxDuration: 10, quality: RNCamera.Constants.VideoQuality["360p"], }); let cameraRef = useRef(null); // 申请必要权限:相机+麦克风+存储 const requestPermissions = async () => { if (Platform.OS === 'android') { const granted = await PermissionsAndroid.requestMultiple([ PermissionsAndroid.PERMISSIONS.CAMERA, PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE ]); const allGranted = Object.values(granted).every(status => status === PermissionsAndroid.RESULTS.GRANTED); setPermission(allGranted ? 'authorized' : 'denied'); } else { // iOS权限申请逻辑可根据实际使用的权限库调整 const cameraPermission = await Permissions.check('camera'); const micPermission = await Permissions.check('microphone'); setPermission(cameraPermission === 'authorized' && micPermission === 'authorized' ? 'authorized' : 'denied'); } }; useEffect(() => { requestPermissions(); }, []); const toggleFlash = () => { const flashModeOrder = { off: 'on', on: 'off' }; setFlash(flashModeOrder[flash]); }; const zoomOut = () => { setZoom(zoom - 0.1 < 0 ? 0 : zoom - 0.1); }; const zoomIn = () => { setZoom(zoom + 0.1 > 1 ? 1 : zoom + 0.1); }; const takePicture = async () => { if (cameraRef.current) { const options = { quality: 0.5, base64: true }; const data = await cameraRef.current.takePictureAsync(options); console.log('拍照结果:', data.uri); } }; const takeVideo = async () => { if (cameraRef.current && !isRecording) { try { const recordoptions = { mute: false, maxDuration: 10, quality: RNCamera.Constants.VideoQuality["360p"], }; const promise = cameraRef.current.recordAsync(recordoptions); if (promise) { setIsRecording(true); const data = await promise; console.log("录制结果:", data.uri); // 录制结束(自动到时长/手动停止)后重置状态 setIsRecording(false); } } catch (e) { console.error('录制错误:', e); setIsRecording(false); } } }; // 新增停止录制逻辑 const stopVideo = () => { if (cameraRef.current && isRecording) { cameraRef.current.stopRecording(); setIsRecording(false); } }; // 权限未授权时展示提示 if (permission !== 'authorized') { return <View style={styles.container}><Text style={{color:'#fff', fontSize:16}}>请授予相机和麦克风权限后使用</Text></View>; } return ( <View style={styles.container}> <RNCamera ref={cameraRef} style={styles.preview} type={type} flashMode={flash} zoom={zoom} autoFocus={autoFocus} /> <View style={{ flex: 0, flexDirection: "row", justifyContent: "center", marginBottom: 10 }}> <TouchableOpacity onPress={takePicture} style={styles.capture}> <Text style={{ fontSize: 14 }}> TAKE PICTURE </Text> </TouchableOpacity> </View> <View style={{ flex: 0, flexDirection: "row", justifyContent: "center" }}> {/* 按钮根据录制状态切换功能和文字 */} <TouchableOpacity onPress={isRecording ? stopVideo : takeVideo} style={styles.capture}> <Text style={{ fontSize: 14 }}> {isRecording ? "STOP VIDEO" : "TAKE VIDEO"} </Text> </TouchableOpacity> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'column', backgroundColor: 'black', justifyContent:'center', alignItems:'center' }, preview: { flex: 1, justifyContent: 'flex-end', alignItems: 'center', width:'100%' }, capture: { flex: 0, backgroundColor: '#fff', borderRadius: 5, padding: 15, paddingHorizontal: 20, alignSelf: 'center', margin: 20, } }); export default App;
补充说明
修改后点击录制按钮会开始录制,按钮文字变为停止录制,点击即可手动结束,10秒到了也会自动结束,录制完成后会打印视频本地路径。
内容的提问来源于stack exchange,提问作者newcoder
相关产品推荐
相关产品推荐

