ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

expo-video 演进全览:Expo 跨平台视频播放器的能力图谱与升级指南

expo-video 演进全览:Expo 跨平台视频播放器的能力图谱与升级指南 expo-video 演进全览Expo 跨平台视频播放器的能力图谱与升级指南【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo本文以 packages/expo-video/CHANGELOG.md 为脉络主线结合packages/expo-video包内的 TypeScript 类型定义、AndroidKotlin/ExoPlayer与 iOSSwift/AVFoundation原生实现、config plugin 源码系统梳理 Expo 官方视频组件expo-video从 2023 年 10 月首发至今的完整能力演进。读者将掌握该组件当前支持的全部核心特性多轨选择、DRM、缓存、画中画、全屏、Seek/Scrubbing 优化、背景播放等、各版本破坏性变更带来的升级注意事项以及这些能力在仓库源码中的落地位置可直接用于选型评估与迁移升级。一、expo-video 是什么定位与版本演进脉络expo-video是 Expo 生态中面向 React Native 与 Web 的跨平台、高性能视频组件见 packages/expo-video/package.json 中 A cross-platform, performant video component for React Native and Expo with Web support 的描述支持 Android、iOS 与 Web 三端底层分别基于 AndroidX Media3 / ExoPlayerAndroid、AVFoundation / AVPlayeriOS与 HTML5 VideoWeb。从 CHANGELOG.md 的版本序列可以清晰看到该项目的发展轨迹2023-10-300.1.0iOS 首发2023-11~2024-060.2.x → 1.2.xAndroid 首发、事件系统、DRM、背景播放、画中画PiP、全屏等能力密集落地2024-10~2025-082.0.0-preview → 3.0.x事件 API 重构useEvent支持、音轨/字幕轨、缓存、缩略图生成等大特性合入2026-01 起55.0.0 → 57.0.2版本号与 Expo SDK 版本序列对齐从 3.0.15 直接跳至 55.0.0可推断为跟随 SDK 版本策略并持续引入 Seek 容差、Scrubbing 模式、自适应码率上限等进阶能力。截至 2026-07-22仓库当前版本为57.0.2Unpublished 段还记录着若干待发布变更controllerAutoShow、maxResolution、videoChangeFrameRateStrategy等说明该组件仍在活跃迭代中。二、核心能力图谱从 CHANGELOG 提炼的功能版图将 CHANGELOG 中所有 New features 条目按能力域归类可以得到expo-video的完整功能版图。以下每项能力都可在仓库源码中找到对应落地。2.1 播放控制基础能力能力引入版本说明播放/暂停/循环/倍速/当前时间1.1.0loop、playbackRate、preservesPitch、currentTime属性音量与静音1.1.0Web/ 1.2.xvolume、muted事件系统在 2.0.0-preview.0 拆分为volumeChange与mutedChange时长与直播信息1.1.9 / 1.2.0全平台duration、isLive1.2.6 增加currentLiveTimestamp、currentOffsetFromLive等直播进阶配置替换源2.1.7replaceAsync异步加载不阻塞主线程直接创建实例2.0.0-preview.1支持new VideoPlayer()直接实例化这些属性、方法与默认值的完整定义见 src/VideoPlayer.types.ts例如loop默认false、volume默认1.0、playbackRate取值0~16.0、timeUpdateEventInterval默认0为 0 时不触发timeUpdate。注意volume与muted相互独立——静音不改变音量值设置音量也不会自动取消静音。2.2 事件系统从首次支持到useEvent友好事件是 expo-video 交互的核心。CHANGELOG 中事件相关演进包括1.1.0Android/iOS 事件支持1.2.3Web 事件支持2.0.0-preview.0破坏性变更所有播放器事件返回类型统一为单个对象以更好支持useEventhook同时将volumeChange拆分为volumeChange和mutedChange2.1.0新增sourceLoad事件源元数据加载完成、VideoView的onFirstFrameRender事件首帧渲染回调可用于隐藏封面图1.2.6新增timeUpdate事件及配套timeUpdateEventInterval属性。完整事件清单见 src/VideoPlayerEvents.types.ts包括statusChange、playingChange、playbackRateChange、volumeChange、mutedChange、playToEnd、timeUpdate、sourceChange、sourceLoad、videoTrackChange/audioTrackChange/subtitleTrackChange及对应的available*TracksChangeiOS 独有isExternalPlaybackActiveChangeAirPlay 状态变更。sourceLoad的 payload 同时携带duration与三组可用轨道数组availableVideoTracks/availableSubtitleTracks/availableAudioTracks是构建清晰度/字幕/音轨切换面板的数据基础。2.3 多轨支持音轨、字幕与视频轨含 HLS 细节这是 expo-video 区别于轻量视频库的关键能力2.0.0-preview.2支持列出与选择字幕轨closed captions2.2.0支持音轨——player.audioTrack设置当前音轨、player.availableAudioTracks列出可用音轨2.1.0支持列出可用视频轨与当前播放视频轨55.0.0视频轨新增averageBitrate/peakBitrate原bitrate标记为 deprecated、urlHLS 轨 URL、videoRangeSDR/HLG/PQ55.0.7HLS 视频轨增加url字段AudioTrack/SubtitleTrack增加name、isDefault、autoSelect字段。在源码层面轨道相关类型定义于 src/VideoPlayer.types.tsVideoTrack包含id、url、size、mimeType、isSupportedAndroid、bitrate/averageBitrate/peakBitrate、frameRate、videoRangeAudioTrack与SubtitleTrack均含language、label等字段。使用时有两点平台注意源码 JSDoc 明确标注iOS 上使用 HLS 源时URL 需含.m3u8扩展名或将VideoSource.contentType显式设为hls否则视频轨不可用CHANGELOG 55.0.16 修复了 HLS 多音轨场景下availableVideoTracks的重复问题55.0.7 起 iOS 26 的 HLS 视频轨获取逻辑已更新。2.4 缓存能力与缓存管理 API2.1.0引入缓存功能。缓存相关约束CHANGELOG 与类型定义双重确认iOS 上 HLS 源无法使用缓存平台限制Android/iOS 均不支持对 DRM 保护视频使用缓存缓存时会考虑 Authorization 等鉴权请求头Unpublished 段修复项。配套的缓存管理 API 定义在 src/VideoModule.tssetVideoCacheSizeAsync(sizeBytes)设置缓存上限字节默认 1GB持久生效缓存按 LRU最近最少使用淘汰实际占用可能略超设定值clearVideoCacheAsync()清空全部视频缓存getCurrentVideoCacheSize()查询当前缓存占用字节数。两个写入类 API 都要求当前不存在任何VideoPlayer实例时方可调用。缓存机制的 iOS 原生实现位于 ios/Cache 目录VideoCacheManager、CachableRequest、MediaFileHandle等Unpublished 段还修复了两个缓存崩溃缓存裁剪期间 open-file 注册表的数据竞争iOS、写入缓存时磁盘写满导致NSFileHandleOperationException崩溃iOS改用可捕获的 Swift 抛错 API。2.5 DRMClearKey / PlayReady / Widevine / FairPlay1.1.0引入 Android/iOS DRM 支持1.2.0增加 iOS FairPlay base64 证书支持。DRM 类型与选项定义在 src/VideoPlayer.types.tsexport type DRMType clearkey | fairplay | playready | widevine; // Android: ClearKey、PlayReady、WidevineiOS: FairPlay export type DRMOptions { type: DRMType; licenseServer: string; // 许可服务器 URL headers?: Recordstring, string; // 许可请求头 multiKey?: boolean; // Android 多密钥 DRM contentId?: string; // iOS certificateUrl?: string; // iOS FairPlay 证书 URL base64CertificateData?: string; // iOS base64 证书设置后忽略 certificateUrl };DRM 选项挂在VideoSourceObject.drm字段上鉴权头请用DRMOptions.headers而非VideoSourceObject.headers后者仅用于视频请求本身。iOS 原生实现见 ios/ContentKeyManager.swift 与 ios/ContentKeyDelegate.swift。2.6 画中画PiP与全屏PiP 演进0.3.0iOS→1.1.0Android→1.2.3起 PiP 必须通过 config plugin 开启 →1.2.6Web→ 2.2.2 修复非 16:9 源自动进入 PiP 时的窗口宽高比。全屏演进1.1.0Android 全屏→1.2.6全屏进入/退出事件 →3.0.0全屏方向与自动退出功能 →3.0.5Android 全屏模式始终启用原生控件对齐 iOS→55.0.0移除allowsFullscreenprop改用fullscreenOptions.enable。相关类型定义在 src/VideoView.types.tsexport type FullscreenOptions { enable: boolean; // 是否提供全屏入口默认 true orientation?: FullscreenOrientation; // default/portrait/landscape 等 7 种 autoExitOnRotate?: boolean; // 旋转到非指定方向时自动退出全屏默认 false keepFullscreenOnPiPStop?: KeepFullscreenOnPiPStopBehavior; // iOSalways|autoEnter|never };VideoView的 PiP 相关 props 包括allowsPictureInPicture、startsPictureInPictureAutomaticallyAndroid 12 / iOS默认false、onPictureInPictureStart/onPictureInPictureStop回调模块级还有isPictureInPictureSupported()能力探测函数见 src/VideoModule.ts。CHANGELOG 中 PiP 相关的 bug fix 非常多55.0.10 修复 PiP 从全屏自动进入后立即退出的问题等可见这是多端适配的高频风险区。2.7 背景播放与 Now Playing 通知1.1.0背景播放支持1.1.5 / 1.1.6iOS / Android 自定义 Now Playing 通知1.2.6破坏性变更showNowPlayingNotification默认值改为false3.0.9破坏性变更Android 上要显示 Now Playing 通知config plugin 的supportsBackgroundPlayback必须为true56.1.4修复与 expo-audio 混用后锁屏控件失效的问题。相关播放器属性showNowPlayingNotification默认false、staysActiveInBackground默认false、keepScreenOnWhilePlaying默认trueAndroid 上仅当VideoView可见时生效。注意 iOS 上 Now Playing 通知依赖音频模式——当audioMixingMode不是doNotMix或auto时该功能不可用见AudioMixingMode类型 JSDoc。背景播放与 PiP 的清单级配置由 config plugin 完成实现见 plugin/src/withExpoVideo.tsexport type WithExpoVideoOptions { supportsBackgroundPlayback?: boolean; // 是否启用背景播放 supportsPictureInPicture?: boolean; // 是否启用 Android/iOS 画中画 };该插件会向 iOSInfo.plist的UIBackgroundModes写入/移除audio在 Android 上设置主 Activity 的android:supportsPictureInPicture开启背景播放时注入FOREGROUND_SERVICE与FOREGROUND_SERVICE_MEDIA_PLAYBACK权限并注册ExpoVideoPlaybackService前台服务android:foregroundServiceTypemediaPlayback绑定MediaSessionServiceintent-filter。2.8 Seek 精度与 Scrubbing 模式55.0.0 起的新进阶能力55.0.0 引入了面向精细拖动进度条场景的两组配置export type SeekTolerance { toleranceBefore?: number; // 实际 seek 位置可提前的最大秒数默认 0 toleranceAfter?: number; // 实际 seek 位置可延后的最大秒数默认 0 };容差越大通常 seek 越快它影响currentTime赋值、seekBy()的精度Android 上还影响默认原生控件进度条的拖动精度。export type ScrubbingModeOptions { scrubbingModeEnabled?: boolean; // 总开关默认 falseAndroid 开启后播放会被抑制 increaseCodecOperatingRate?: boolean; // 是否提升编解码器工作频率默认 true enableDynamicScheduling?: boolean; // ExoPlayer 动态调度默认 true useDecodeOnlyFlag?: boolean; // API 34 使用 MediaCodec.BUFFER_FLAG_DECODE_ONLY 加速 seek allowSkippingMediaCodecFlush?: boolean; // 允许跳过解码器 flush默认 true };scrubbingModeOptions建议在用户拖拽进度条的短时段内开启、结束时关闭Android 上开启后播放被抑制务必在交互结束后恢复。配合增大seekTolerance可获得最佳拖动体验。2.9 自适应流控制maxResolution 与视频刷新率策略Unpublished 新特性Unpublished 段即尚未发布、已在 main 分支记录了两项值得关注的 Android 新能力maxResolution播放器选项为自适应视频轨选择设置上限——播放器会选择不超过该分辨率的最高质量轨。Android 上是硬约束若无满足条件的轨则回退到最低分辨率轨iOS 上是软提示首选上限且 iOS 仅对 HLS 源生效。对应属性maxResolution: VideoSize | nullnull表示不设限见 src/VideoPlayer.types.ts。videoChangeFrameRateStrategyplayer builder 选项控制 ExoPlayer 是否允许修改显示刷新率以匹配视频帧率。默认onlyIfSeamless仅在无缝切换时匹配设为off可避免自适应刷新率屏如 Pixel 9/10 系列在播放 30fps 视频时将整个 App UI含滚动与动画压制到 30Hz。帧率匹配主要利好电视类大屏垂直视频流等场景建议off。这两个选项分别落在VideoPlayer.maxResolution属性与PlayerBuilderOptions.videoChangeFrameRateStrategy字段上。后者在 Android 侧由 android/src/main/java/expo/modules/video/records/PlayerBuilderOptions.kt 声明含seekBackwardIncrement/seekForwardIncrement取值会被钳制在 0.001~999 秒之间枚举定义在 android/src/main/java/expo/modules/video/enums/VideoChangeFrameRateStrategy.kt。2.10 其他实用能力缩略图生成2.0.0-preview.0 引入2.1.0 增加maxWidth/maxHeight限制generateThumbnailsAsync(times, options)返回原生图片引用SharedRefimage可直接作为expo-image的Image源。相关实现见 ios/Thumbnails 与 Android 侧代码类型见 src/VideoPlayer.types.ts 的VideoThumbnailOptions。缓冲控制2.0.0-preview.0 引入BufferOptions——preferredForwardBufferDurationAndroid 默认 20siOS 默认 0 即自动、waitsToMinimizeStallingiOS、minBufferForPlaybackAndroid 默认 2s、maxBufferBytesAndroid 默认 0 即自动、prioritizeTimeOverSizeThresholdAndroid。音频混合模式2.0.0-preview.1 引入audioMixingMode取值为mixWithOthers/duckOthers/auto/doNotMix。多播放器并发时按doNotMix auto duckOthers mixWithOthers取最高优先级。Unpublished 段修复了 iOS 默认值——按文档改为auto原为doNotMix。Web 专项1.2.6 支持 Web PiP1.2.3 修复AudioContext提前创建问题2.1.5 增加playsInline2.1.9/3.0.0/3.0.1 围绕crossOrigin反复调整3.0.0 默认改为anonymous后又回退为undefined3.0.4 增加实验性useAudioNodePlayback多实例同时播放时不叠加音量已知可能破坏部分源的音频3.0.11 提供nativeRef访问底层HTMLVideoElement55.0.0 修复旧版 Safari 崩溃。AirPlayiOS3.0.0 完整支持含设备选择按钮组件VideoAirPlayButton见 src/VideoAirPlayButton.ios.tsx、isExternalPlaybackActive属性及监听2.0.0-preview.0 增加allowsExternalPlayback控制。PHAsset 支持iOS3.0.11 支持播放PHAssetURI但只能通过replaceAsync()或默认构造函数加载。Surface 类型Android2.1.6 起可通过surfaceType: surfaceView | textureView选择渲染表面默认surfaceView功耗更低、性能更好多视频重叠等场景改用textureView。三、VideoView视图层能力与控件配置VideoView是承载播放器的视图组件核心 props 见 src/VideoView.types.tsplayer可传null55.0.0 起支持、nativeControls默认true全屏模式下因平台限制始终启用、contentFitcontain/cover/fill默认contain、showsTimecodesiOS、requiresLinearPlayback、surfaceType、contentPositioniOS、allowsVideoFrameAnalysisiOS 16默认true等。Android 专属的buttonOptions即 CHANGELOG 55.0.6 新增的buttonConfiguration现已重命名提供细粒度控件可见性控制export type ButtonOptions { showNext?: boolean; // 默认 false55.0.6 起隐藏 showPrevious?: boolean; // 默认 false showSeekForward?: boolean; // 默认 true showSeekBackward?: boolean;// 默认 true showSubtitles?: boolean | null; // undefined有字幕时显示 showSettings?: boolean; // 默认 true showPlayPause?: boolean; // 默认 true showBottomBar?: boolean; // 默认 true全屏下始终可见 };Unpublished 段新增的controllerAutoShowAndroid默认true控制原生控件是否在播放开始/暂停/结束时自动显示设为false后控件不再自动弹出但仍可点击视图唤起——适合程序化驱动的自动连播列表避免每次播放时控件闪现。另外55.0.6 的PlayerBuilderOptionsseekBackwardIncrement/seekForwardIncrement会直接作用于原生控件上的快进/快退按钮步长。四、Hooks 与生命周期useVideoPlayer / createVideoPlayer两种创建播放器的方式定义在 src/VideoPlayer.tsxuseVideoPlayer(source, setup?, playerBuilderOptions?)推荐用法组件卸载时自动释放播放器。实现细节值得注意——当source变化时复用现有播放器调用replaceAsync而非重建对应 CHANGELOG Unpublished 段的 When source changes use replaceAsync instead of re-creating the player仅当 builder options 变化或replaceAsync失败时才重建实例。createVideoPlayer(source, playerBuilderOptions?)创建不自动释放的直接实例需手动管理生命周期。useVideoPlayer的第三个参数playerBuilderOptions对应 Android 原生PlayerBuilderOptionsseek 步长、videoChangeFrameRateStrategy类型定义见 src/VideoPlayer.types.ts。注意VideoPlayer.replace()在 iOS 上会同步在主线程加载资源并可能长时间阻塞 UI源码中 JS 层在调用前会打印弃用警告应优先使用replaceAsync()。五、测试与 Mockjest-expo 下的可测试性CHANGELOG Unpublished 段记录了一次重要的测试基础设施修复修复jest-expo预设下导入expo-video抛TypeError: Cannot read properties of undefined (reading prototype)的问题——原因是VideoPlayer.tsx在模块加载时对NativeVideoModule.VideoPlayer.prototype.replace打补丁而自动生成的 mock 表无法表示 SharedObject 类。修复方案是手写 mockmocks/ExpoVideo.ts。该文件由jest-expo预设注入到requireNativeModule(ExpoVideo)实现了带内存状态的VideoPlayerplay/pause/seek/replace 可真实触发状态与事件与VideoThumbnail并保持与公共类型定义一致的默认值如audioMixingMode: auto、bufferOptions的跨平台默认值。文件头注释明确要求不要用expo-modules-test-core重新生成以免覆盖手写行为。配套的组件测试可参考 src/tests。六、破坏性变更速查升级前必读汇总 CHANGELOG 中全部 Breaking changes按版本排序版本破坏性变更应对建议2.0.0-preview.0事件返回类型改为单对象volumeChange拆分为volumeChangemutedChangeiOS/tvOS 最低版本升至 15.1升级useEvent消费方与事件参数解构1.2.6showNowPlayingNotification默认改为false需要时显式置true1.2.3PiP 必须通过 config plugin 开启配置supportsPictureInPicture2.1.9 / 3.0.0 / 3.0.1WebcrossOrigin默认值两次调整最终为undefined不启用 CORS需要 CORS 时显式设置crossOriginanonymous3.0.5Android 全屏模式始终启用原生控件无需处理行为对齐 iOS3.0.9Android Now Playing 通知依赖supportsBackgroundPlayback: true配置 config plugin55.0.0移除allowsFullscreenprop改用fullscreenOptions.enable55.0.6Android 原生控件默认隐藏上一首/下一首按钮用buttonOptions.showNext/showPrevious重新开启56.0.0最低版本提升iOS/tvOS 16.4、macOS 13.4确认工程最低系统版本满足要求0.2.0AndroidcompileSdkVersion/targetSdkVersion升至 34保持 Gradle 配置同步依赖层面Android 侧 media3 依赖持续升级1.4.0 → 1.8.0 → 1.9.0 → 1.9.1对应 1.2.6 / 3.0.6 / 56.0.0 / Unpublished 段的版本记录升级时如遇到 ExoPlayer 相关异常可优先检查依赖版本一致性。七、结语从变更日志看 expo-video 的设计取向回看整个 CHANGELOGexpo-video的演进呈现出三条清晰主线一是性能与体验打磨——replaceAsync异步加载、iOS 主线程减负、缓存并发与磁盘写满崩溃修复、Seek/Scrubbing 优化均指向流畅、不卡主线程的工程目标二是企业级媒体能力补齐——DRM、多轨选择、HLS 细节字段、缓存管理 API使其足以支撑点播/直播类生产应用三是多端一致性收敛——Android 全屏控件、PiP 行为、audioMixingMode默认值等不断向 iOS 与官方文档对齐。对开发者而言升级expo-video前建议对照本文第六节速查表核查破坏性变更背景播放与 PiP 功能务必确认 config plugin 配置plugin/src/withExpoVideo.ts涉及轨道信息的业务优先消费sourceLoad事件与available*Tracks属性如需精细的进度条拖动体验从SeekTolerance与ScrubbingModeOptions组合调优入手。【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表