如何在React-Native中获取本地视频的FPS值?求最优解决方案
React-Native提取视频FPS值的最佳解决方案
方案一:使用Expo AV(适配Expo/裸RN项目)
Expo AV提供开箱即用的视频信息获取API,无需复杂配置,适合快速开发场景。
- 安装依赖:
npx expo install expo-av - 实现代码:
import { AV } from 'expo-av'; async function getVideoFPS(videoUri) { try { const videoInfo = await AV.getVideoInfoAsync(videoUri); return videoInfo.fps; // 直接返回视频帧率值 } catch (error) { console.error('获取视频FPS失败:', error); return null; } } - 注意事项:裸RN项目需先执行
npx expo prebuild完成Expo模块配置,确保视频URI为本地文件路径或合法网络地址。
方案二:使用react-native-ffmpeg(适配裸RN项目)
基于FFmpeg工具,支持几乎所有视频格式的帧率解析,兼容性极强。
- 安装依赖:
npm install react-native-ffmpeg # iOS需额外执行 cd ios && pod install && cd .. - 实现代码:
import RNFFmpeg from 'react-native-ffmpeg'; async function getVideoFPS(videoPath) { // FFprobe命令:提取视频流的帧率信息 const command = `-v error -select_streams v:0 -show_entries stream=r_frame_rate -of default=noprint_wrappers=1:nokey=1 ${videoPath}`; const result = await RNFFmpeg.execute(command); if (result.returnCode === 0) { // 解析帧率字符串(如30/1转为30.0) const [num, den] = result.output.trim().split('/'); return parseFloat(num) / parseFloat(den); } else { console.error('解析帧率失败:', result); return null; } } - 注意事项:需申请文件读取权限(Android配置
READ_EXTERNAL_STORAGE,iOS配置NSPhotoLibraryUsageDescription),视频路径需为本地绝对路径。
方案三:自定义原生模块(高度定制场景)
若上述库无法满足需求,可直接调用系统API获取帧率,性能最优。
iOS端(OC代码示例)
#import <AVFoundation/AVFoundation.h> #import <React/RCTBridgeModule.h> @interface VideoFPSModule : NSObject <RCTBridgeModule> @end @implementation VideoFPSModule RCT_EXPORT_MODULE(); RCT_EXPORT_METHOD(getVideoFPS:(NSString *)videoPath resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSURL *videoURL = [NSURL fileURLWithPath:videoPath]; AVAsset *asset = [AVAsset assetWithURL:videoURL]; AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] firstObject]; if (videoTrack) { resolve(@(videoTrack.nominalFrameRate)); } else { reject(@"NO_VIDEO_TRACK", @"未找到有效视频轨道", nil); } } @end
Android端(Java代码示例)
import android.media.MediaMetadataRetriever; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; public class VideoFPSModule extends ReactContextBaseJavaModule { public VideoFPSModule(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "VideoFPSModule"; } @ReactMethod public void getVideoFPS(String videoPath, Promise promise) { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(videoPath); String fpsStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CAPTURE_FRAMERATE); if (fpsStr != null) { promise.resolve(Float.parseFloat(fpsStr)); } else { promise.reject("NO_FPS_DATA", "无法提取帧率信息"); } } catch (Exception e) { promise.reject("ERROR", e.getMessage()); } finally { retriever.release(); } } }
RN端调用
import { NativeModules } from 'react-native'; const { VideoFPSModule } = NativeModules; async function getVideoFPS(videoPath) { try { return await VideoFPSModule.getVideoFPS(videoPath); } catch (error) { console.error('获取帧率失败:', error); return null; } }
方案推荐
- Expo项目优先选Expo AV,配置简单,API易用;
- 裸RN项目且需兼容多格式视频,选react-native-ffmpeg;
- 对性能要求极高或需定制化处理,选自定义原生模块。
内容的提问来源于stack exchange,提问作者Vijay Kahar
相关产品推荐
相关产品推荐

