expo-camera的recordAsync无返回结果,视频录制功能异常
Expo-Camera 视频录制无反应问题修复
我正在用expo-camera开发视频录制功能,界面包含CameraView视图和操作按钮,预期点击按钮启动录制,再次点击停止录制。权限已成功授予,但调用recordAsync后无任何反应,相关代码如下:
import { Divider, ThemedButton, ThemedText, ThemedView } from "@/components"; import ScreenNameWithBack from "@/components/atoms/ScreenNameWithBack"; import { Colors } from "@/constants/Colors"; import { CameraView, useCameraPermissions } from "expo-camera"; import { useRef, useState } from "react"; import { Button, StyleSheet, Text, View } from "react-native"; export default function VerificationStep() { const [isRecording, setIsRecording] = useState(false); const [permission, requestPermission] = useCameraPermissions(); const [video, setVideo] = useState<any>(); const cameraRef = useRef<any>(null); if (!permission) { // Camera permissions are still loading. return <View />; } if (!permission.granted) { // Camera permissions are not granted yet. return ( <View style={styles.container}> <Text style={styles.message}> We need your permission to show the camera </Text> <Button onPress={requestPermission} title="grant permission" /> </View> ); } const recordVideo = async () => { console.log("mmmm"); setIsRecording(true); let options = { quality: "480p", maxDuration: 120, mute: false, }; console.log("nnn"); try { cameraRef?.current?.recordAsync(options)?.then((ss: any) => { setVideo(ss); }); } catch (error) { console.log({ error }); } }; const stopRecording = () => { console.log("---"); setIsRecording(false); cameraRef.current.stopRecording(); console.log("+++"); }; console.log({ video }); return ( <View style={styles.container}> <CameraView style={styles.camera} mode="video" ref={cameraRef} onCameraReady={() => console.log("ready")} /> <ThemedButton title={isRecording ? "Stop Recording" : "Record Video"} onPress={isRecording ? stopRecording : recordVideo} /> </View> ); }
问题分析
代码存在几个核心问题导致录制无响应:
recordAsync是异步Promise方法,当前用then链式调用但未正确等待结果,且外层try/catch无法捕获then中的错误- 启动/停止录制的逻辑拆分导致状态不同步,
stopRecording调用后未关联recordAsync的结果捕获 - 未处理录制过程中可能的异常状态重置
修复后的代码
import { Divider, ThemedButton, ThemedText, ThemedView } from "@/components"; import ScreenNameWithBack from "@/components/atoms/ScreenNameWithBack"; import { Colors } from "@/constants/Colors"; import { CameraView, useCameraPermissions } from "expo-camera"; import { useRef, useState } from "react"; import { Button, StyleSheet, Text, View } from "react-native"; export default function VerificationStep() { const [isRecording, setIsRecording] = useState(false); const [permission, requestPermission] = useCameraPermissions(); const [video, setVideo] = useState(null); const cameraRef = useRef(null); if (!permission) { return <View />; } if (!permission.granted) { return ( <View style={styles.container}> <Text style={styles.message}> 需要获取相机权限才能使用 </Text> <Button onPress={requestPermission} title="授予权限" /> </View> ); } const toggleRecording = async () => { if (isRecording) { cameraRef.current?.stopRecording(); setIsRecording(false); } else { setIsRecording(true); const options = { quality: "480p", maxDuration: 120, mute: false, }; try { // recordAsync会在停止录制时自动返回视频数据 const videoData = await cameraRef.current?.recordAsync(options); setVideo(videoData); setIsRecording(false); } catch (error) { console.error("录制出错:", error); setIsRecording(false); } } }; console.log({ video }); return ( <View style={styles.container}> <CameraView style={styles.camera} mode="video" ref={cameraRef} onCameraReady={() => console.log("相机已准备好")} /> <ThemedButton title={isRecording ? "停止录制" : "开始录制"} onPress={toggleRecording} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", }, camera: { flex: 1, width: "100%", }, message: { fontSize: 16, marginBottom: 20, }, });
关键修复点
- 将启动/停止录制合并为单个
toggleRecording函数,避免状态不同步 - 使用
await正确处理recordAsync的Promise,确保捕获录制完成后的视频数据 - 统一错误处理逻辑,录制失败时自动重置状态
- 简化代码结构,移除不必要的可选链嵌套
内容的提问来源于stack exchange,提问作者BeginnerProgrammer
相关产品推荐
相关产品推荐

