@simba-dev/react-native-media-player

中文文档
3.0.0发布于 2026/11/02MITTypeScriptCommonJS

React Native视频和音频播放器,由libmpv - Picture-in-Picture, MediaSession,前台服务和可定制的TypeScript UI提供支持。为Android打造。设计为一个插入式替代反应原生视频/反应原生轨道播放器/博览会av

中文使用文档
文档目录29 节
  1. 目录
  2. 这是什么?
  3. 这不是什么
  4. 要求
  5. 安装
  6. 本地二进制文件
  7. 消费者设置
  8. 画中画
  9. 背景音频
  10. 快速启动
  11. 玩的东西
  12. 渲染图片
  13. 驱动它
  14. 可选适配器:简历位置
  15. 控制
  16. 配置
  17. 画中画
  18. 背景音频
  19. 主题
  20. API参考
  21. 组件
  22. 钩子
  23. 命令
  24. 桥
  25. 状态
  26. 故障排除
  27. 限制
  28. 贡献
  29. 许可证

@simba-dev / react-native-media-player

React Native video and audio playback for Android,由 libmpv. 一个引擎用于两个通道:音频的MediaSession和前台服务,视频的Picture-in-Picture。

该库呈现图片并公开状态和命令。它不绘制自己的控件-你的应用程序提供的chrome。

Simba Player hero image — Android video player UI mockup

npm version GitHub release License: MIT npm downloads GitHub tags Sponsor Buy Me a Coffee CI Release

释放  ·  更新日志  ·  npm包  ·  标签

目录

  1. 这是什么?
  2. 这不是什么
  3. 要求
  4. 安装
  5. 消费者设置
  6. 快速启动
  7. 控制
  8. 配置
  9. 画中画
  10. 背景音频
  11. 主题
  12. API参考
  13. 故障排除
  14. 限制
  15. 贡献
  16. 许可证

这是什么?

Android上的React Native播放引擎,由libmpv支持。一个引擎同时提供音频和音频 视频中,两条车道在同一座桥上相遇:

  • 一个活动。 标准库没有声明Activity。播放发生在启动器活动中 你的应用已经有;视频图片为 <SimbaVideo /> 在React树中。
  • 一个音频和视频引擎。 音频文件通过相同的libmpv实例播放,没有 表面连接,所以没有第二个播放器维护。
  • MediaSession和前台服务。 标题,艺术家和专辑到达锁定屏幕和 媒体通知;播放、暂停、停止、下一个、上一个和查找都被通知到会话,所以 耳机按钮和蓝牙控制。
  • 画中画。 手动输入的需求,和操作系统级别的自动输入休假从Android 12。
  • 类型的表面。 配置、状态、命令和钩子都是类型化的。

这不是什么

  • 不是现成的替代品 react-native-video, expo-av 或者 react-native-track-player. 它们暴露了您所提供的组件 source 出现。这个有一个不同的形状:提供者,一个 <SimbaVideo /> 照片, usePlayer() 用于状态和命令。没有 <Video source={…} /> 这里,没有适配器可以创建一个。
  • 不是一个控制面。 自2.0.0以来,库根本没有提供任何控件-参见 控制.
  • 不是iOS。 react-native.config.js 集合 ios: null;没有iOS实现。
  • 不是传统的桥式图书馆。 本机包是一个 TurboReactPackage所以新 建筑学是必需的(newArchEnabled=true)。
  • 而不是一个“克隆并构建它”的包。 预构建的libmpv二进制文件下载于 安装时间-见 安装.

要求

React Native>= 0.76.0 (同行依赖)
反应>= 18.0.0 (同行依赖)
安卓API 24+ (Android 7.0)。PiP输入调用 Activity.enterPictureInPictureMode(),这是在API 24中添加的。 compileSdk 和 targetSdk 是从你的应用程序继承的 rootProject.ext -图书馆没有固定它们。
JDK17. 图书馆的Kotlin jvmTarget 是17岁。
新架构必需的。 PlayerPackage 扩展 TurboReactPackage.

安装

npm install @simba-dev/react-native-media-player

自动链接处理其余的:发货 react-native.config.js 告诉React Native的CLI where Android模块还存在,所以 com.simba.player.PlayerPackage 登记在你的 MainApplication.kt 在下一个构建中。

本地二进制文件

这个 postinstall 脚本(scripts/download-native.js)下载预构建的本机库 (libmpv和朋友)从匹配的GitHub版本,验证存档的SHA-256和提取 它变成 android/src/main/jniLibs/<abi>/ 在已安装的包中。发布了四项abi: arm64-v8a, armeabi-v7a, x86, x86_64.

这个脚本是幂等的——如果二进制文件已经存在,它会在没有网络调用的情况下退出; 所以重新运行 npm install 是安全的。集 SKIP_DOWNLOAD_NATIVE=1 完全跳过下载 (这就是发布工作流所做的,因为CI自己构建二进制文件)。

消费者设置

包自己的清单声明了一个前台服务和一个PiP操作接收器。它宣称没有 Activity:回放发生在你的应用已经拥有的Activity中。

画中画

你的启动器活动必须选择加入:

<!-- android/app/src/main/AndroidManifest.xml -->
<activity
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|navigation"
    android:launchMode="singleTask"
    android:supportsPictureInPicture="true"
    android:resizeableActivity="true"
    android:theme="@style/AppTheme"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

resizeableActivity="true" 不是可选的。未调整大小的活动无法进入 画中画。

背景音频

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

在Android 13+ (API 33)上,应用程序必须保持 POST_NOTIFICATIONS 之前的媒体通知是 显示。 commands.requestNotificationPermission() 要求得到它;在旧版本中,它什么也不做。

快速启动

积分是 1个导入+ 1个包装+最多1个可选适配器.

// App.tsx
import React from 'react';
import {SimbaPlayer} from '@simba-dev/react-native-media-player';

export default function App() {
  return (
    <SimbaPlayer config={{audio: {backgroundPlayback: true}}}>
      <RootNavigator />
    </SimbaPlayer>
  );
}

<SimbaPlayer> 组成 PlayerProvider (配置加上玩家状态)和 PlayerResumeProvider (查找简历)。它的道具是 config, resumePolicy 和 children.

玩的东西

import {usePlayerActivity} from '@simba-dev/react-native-media-player';

const {openPlayer} = usePlayerActivity();

await openPlayer({
  uri: 'https://example.com/movie.mkv',
  title: 'Movie',
  type: 'video',
});

type: 'audio' 启动前台媒体服务。 type: 'video' 装载到已安装的 <SimbaVideo /> 和解决 false 当没有安装表面时-检查 commands.isSurfaceMounted() 如果你期望它能起作用,但它没有。

渲染图片

import {SimbaVideo} from '@simba-dev/react-native-media-player';

<SimbaVideo style={{flex: 1}} resizeMode="contain" />;

resizeMode 是 'contain' | 'cover' | 'stretch' 默认为 'contain'.

驱动它

import {usePlayer, usePlayerProgress} from '@simba-dev/react-native-media-player';

function Controls() {
  const {state, commands} = usePlayer();
  const {positionMs, durationMs} = usePlayerProgress();

  return (
    <View>
      <Text>
        {Math.floor(positionMs / 1000)} / {Math.floor(durationMs / 1000)}
      </Text>
      <Button
        title={state.isPlaying ? 'Pause' : 'Play'}
        onPress={commands.togglePlayPause}
      />
    </View>
  );
}

usePlayer() 返回 {state, commands}. usePlayerProgress() 返回进度对象。 直接(positionMs, durationMs, isBuffering, isSeeking, seekable, cacheRanges, cacheFill)。

可选适配器:简历位置

<SimbaPlayer resumePolicy={(id) => bookmarks.byId[id]?.positionMs}>
  <RootNavigator />
</SimbaPlayer>

resumePolicy 接收 resumeId 你传给 useOpenWithResume() 并返回已保存的 位置以毫秒为单位,或者 undefined 当没有的时候。

控制

库不绘制控件。 这是自2.0.0以来的合约。

<DefaultControls> -该包用来发布的默认控制包是 删除在 2.0.0. 导出不再存在,并且 <PlayerRoot> 不再退回到它。如果你是 使用它,在你的应用中保留你自己的副本或渲染你自己的控件;图书馆不提供 他们。

有两种方法来获得铬,你可以混合它们:

  1. 渲染你自己的组件 无论你想要什么,阅读吧 usePlayer(), usePlayerProgress() 和 useTheme(). 不需要其他任何东西。
  2. 使用 renderControls 槽 在 <PlayerProvider>. 函数返回要绘制的树 在图片上,和 <PlayerRoot> 将其放置在一个绝对定位的覆盖层中:
<PlayerProvider config={config} renderControls={() => <MyControls />}>
  <PlayerRoot />
</PlayerProvider>

renderControls 不带参数——从组件内部的钩子中读取你需要的内容。 槽位是JS-only:它永远不会发送到本机。 useRenderControls() 返回槽位, 或者 null 当没有的时候。

<PlayerRoot> 呈现 <PlayerSurface /> -透明的 flex: 1 布局占位符-加上 覆盖。图片本身是 <SimbaVideo />; <PlayerSurface> 不是视频面。

配置

config 是一个 PlayerConfig. 每个字段都是可选的,并与默认值by合并 resolvePlayerConfig.

部分字段默认的
themeaccent, background, text, textSecondary, surface, icon?#FFD700, #121216, #FFFFFF, rgba(255,255,255,0.6), rgba(255,255,255,0.1)
pipenabled, autoEnterOnLeavetrue, true
hardwareDecoding'auto' | 'mediacodec' | 'no''auto'
notificationsenabled, channelIdtrue, 'simba_player_media'
audiobackgroundPlayback, respectAudioFocustrue, true
subtitlepreferredLanguages, fontSize[], 16
debugverboseLoggingfalse
import {PlayerProvider} from '@simba-dev/react-native-media-player';

<PlayerProvider
  config={{
    theme: {accent: '#00FF88'},
    pip: {enabled: true, autoEnterOnLeave: true},
    audio: {backgroundPlayback: true, respectAudioFocus: true},
    hardwareDecoding: 'auto',
  }}>
  <App />
</PlayerProvider>;

解析后的配置将作为JSON推送到本机桥。原生端作用于PiP 段(驱动自动进入开关);其余部分是应用程序读取回的值 与 usePlayerConfig() 并适用于自己。 DEFAULT_PLAYER_CONFIG 和 DEFAULT_THEME 是 如果你想扩展和修补,可以导出。

画中画

人工输入:

commands.enterPip();          // chapter title and progress are optional arguments
commands.exitPip();
commands.exitPipAndFinish();

enterPip() 调用 enterPictureInPictureMode() 在当前Activity上,所以Activity必须 声明 android:supportsPictureInPicture="true" (见 消费者设置)。

休假时自动输入 是 config.pip.autoEnterOnLeave (默认 true). 它映射到 Android 12 / API 31平台特性 PictureInPictureParams.Builder.setAutoEnterEnabled: 当用户离开应用程序时,操作系统会为你进入Picture-in-Picture。 API 31下的平台 没有这样的功能 -操作系统不能在那里自动输入Picture-in-Picture,输入仍然是手动的 通过 commands.enterPip().

两个PiP标志结合在一起:自动输入需求 pip.enabled 和 pip.autoEnterOnLeave 都是 真实的。

Picture-in-Picture操作行有三个按钮: 播放/暂停, 扩大 和 关闭. 它们在JS中是 onPipPlayPause, onPipExpand 和 onPipClose 事件,在 onPipModeChanged.

媒体通知和锁定屏幕是一个单独的界面。它的MediaSession广告播放, 暂停,播放/暂停,停止,跳转到下一个,跳转到上一个和查找,与标题,艺术家和专辑 元数据。

背景音频

audio.backgroundPlayback 默认为 true:当应用程序处于后台时,音频继续播放, 通过前台媒体服务。相反,视频是“画中画”通道——它没有 继续在后台播放。

主题

import {useTheme} from '@simba-dev/react-native-media-player';

const theme = useTheme();
// {accent, background, text, textSecondary, surface, icon?}

API参考

组件

出口道具笔记
<SimbaPlayer>config?, resumePolicy?, children一个导入集成点。组成 PlayerProvider + PlayerResumeProvider. resumePolicy: (itemId: string) => number | undefined.
<PlayerProvider>config?, renderControls?, children解析配置,实时播放器状态和控制槽。
<PlayerRoot>launchParams?表面占位符加上控件覆盖。 launchParams 是一个 {uri, title, type, startPositionMs, requestId?} 有效载荷;它每加载一次 (uri, startPositionMs) 对。
<SimbaVideo>resizeMode? +标准视图道具这幅画。 resizeMode: 'contain' | 'cover' | 'stretch'、默认 'contain'.
<PlayerSurface>backgroundColor?一个透明的 flex: 1 布局占位符。不是视频表面。

钩子

出口返回
usePlayer(){state, commands}
usePlayerProgress()PlayerProgress - - - - - - positionMs, durationMs, isBuffering, isSeeking, seekable, cacheRanges, cacheFill
usePlayerConfig()解析后的 ResolvedPlayerConfig. 抛出一个 <PlayerProvider>.
useTheme()解析后的 PlayerTheme.
useRenderControls()这个 renderControls 槽,或 null.
usePlayerActivity(){openPlayer(opts)} → Promise<boolean>
useOpenWithResume()(opts & {resumeId?}) => Promise<boolean> -通过最近的地址解析简历位置 <SimbaPlayer>的 resumePolicy.
usePlayItem()({id, uri, title}, {type}) => Promise<boolean>
useOpenFromUrl()(uri: string) => Promise<boolean> - - - - - -接受 content:// 和 file:// uri,派生标题,对类型进行分类并打开它。
useOpenPlaylist(){openPlaylist(entries, opts?)} → Promise<boolean>
useLaunchPlayback()(launchParams) -每次加载一次有效载荷 (uri, startPositionMs) 对。
useQueue() / useQueueLength() / useQueueItems() / useQueueItemsAs()队列存储和便利选择器。
usePlaybackHistory() / usePlaybackHistoryAs()回放历史记录。
useQueueSelection() / useQueueSelectedIndices()选择存储。

openPlayer 接受 {uri, title, type, startPositionMs?, artworkPath?, artist?, album?}。这个 艺术作品,艺术家和专辑字段只适用于音频通道。

队列存储的操作如下 addToQueue, prependToQueue, removeFromQueue, removeFromQueueByIndex, reorderQueue, clearQueue, shuffleQueue, addToPlaybackHistory 和 clearPlaybackHistory.

captureFrame(uri, positionMs, options?) 返回一个 Promise<string | null> -一个JPEG为 档案中的那个位置。默认值为640×360,质量为80,导出为 DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT 和 DEFAULT_FRAME_QUALITY.

命令

commands 是一个稳定的物体;每个方法都在调用时解析桥。

集团方法
运输play, pause, togglePlayPause, stop, stopPlayback, next, previous
寻求seek(positionMs), seekBy(deltaMs), skipForward(seconds), skipBackward(seconds), seekToChapter(index)
音量和速度setVolume(0..100), setMuted(boolean), toggleMute(), setSpeed(number), setLoopMode('none' | 'file' | 'playlist')
播放列表loadFile(uri, title?), loadPlaylist(uris, startIndex?), playlistRemove(index), shuffle(), clear(), setShuffle(boolean)
跟踪cycleTrack(type), setTrack(type, trackId)
画中画enterPip(chapterTitle?, progressPct?), exitPip(), exitPipAndFinish()
屏幕setKeepScreenOn(boolean), setOrientation(mode), setImmersive(boolean), setScreenBrightness(0..1), getScreenBrightness()
表面setVideoBounds(x, y, width, height), fillVideoBounds(), setSurfaceVisible(boolean), isSurfaceMounted()
过滤器setAudioFilter(name, enabled), setVideoFilter(name, enabled)
通知requestNotificationPermission()
商务性质getProperty(name), setProperty(name, value), observeProperty(name), unobserveProperty(name)
内容urigrantPersistablePermission(uri), verifyContentUri(uri)

桥

getMpvPlayerModule() 返回本机模块,或者在本机端为时返回无操作的替身 没有连线(玩笑,网页预览),所以消费者代码保持可渲染。 subscribePlayerEvent(name, handler) 订阅26个命名事件之一并返回一个 退订功能; removeAllListeners(), setDebugLogging() 和 dumpObservedProperties() 也被导出。事件名称的类型为 PlayerEventName.

状态

state 携带 isPlaying, isLoading, title, artist, album, positionMs, durationMs, isBuffering, isSeeking, seekable, volume, isMuted, speed, loopMode, playlist, currentIndex, tracks, chapters, currentChapter, videoParams, error 和 shuffle.

故障排除

openPlayer 解决了 false 看视频。 没有安装表面。渲染 <SimbaVideo /> 启动前,检查 commands.isSurfaceMounted().

Picture-in-Picture不会启动。 活动缺失 android:supportsPictureInPicture="true" 或者 android:resizeableActivity="true". Auto-enter上 另留需API 31+ -低于此,自行输入PiP与 commands.enterPip().

Gradle失败了 libmpv.so not found at android/src/main/jniLibs/…. 的postinstall 下载未运行。重新运行 npm install 在app中,或者手动运行脚本; SKIP_DOWNLOAD_NATIVE=1 设置在您的环境或CI中的某个位置。

NativeModules.MpvPlayerModule 是 undefined 在运行时。 新架构是必需的。 检查 newArchEnabled=true 在应用程序中 android/gradle.properties,并且该应用程序是React 本机Gradle插件运行 autolinkLibrariesWithApp() -应用库自己的构建文件 com.facebook.react 对于管道。

Android 13+上没有媒体通知。 该应用程序尚未获得批准 POST_NOTIFICATIONS. 呼叫 commands.requestNotificationPermission().

限制

  • Android。 没有iOS实现。
  • 没有控制。 图书馆没有船;看到 控制.
  • 自动输入图中图需要Android 12 (API 31)或更新版本。 低于这个值操作系统就不能 这样做,进入是手动的。
  • 大多数配置部分都是在JavaScript中使用的。 本地端接收解析后的 配置为JSON并作用于PiP自动输入开关;其余的是应用程序读取回的值 通过 usePlayerConfig().
  • notifications.channelId 不是天生的。 前台服务创建自己的服务 通知渠道, simba_player_media_playback.
  • 捆绑的本机二进制文件有自己的许可证。 它们是由mpv-android制造的 libmpv的默认版本是GPLv2+),所以将它们链接到 你的应用是你自己的授权决定。库自己的JavaScript和Kotlin代码是MIT。

贡献

从存储库根目录:

npm install        # postinstall downloads the native binaries
npm run typecheck  # tsc --noEmit
npm test           # jest
npm run build      # tsc
npm run lint       # placeholder — no linter is configured yet

有一个 example/ 应用程序与 npm run android, npm start 和 npm run typecheck. 它的 源代码仍然以2.0.0之前的API为目标(它们导入已删除的 DefaultControls 和演示 屏幕不再存在),所以它目前不进行类型检查——它是一个正在进行的工作,而不是 参考实现。

释放是由 release.yml 工作流:它从固定库构建本地库 mpv-android release,将它们附加到GitHub release,并发布到npm。请勿发表于 的手。

许可证

MIT -见 许可证. 预构建的本机二进制文件是第三方构建的mpv和 携带自己的许可条款;看到 限制.

版本与发布记录

@simba-dev/react-native-media-player 共发布 63 个版本,首次发布于 2026/09/03;过去 12 个月发布了 63 个版本。

版本发布日期距今
3.0.0latest2026/11/021 天前
2.1.02026/10/304 天前
2.0.12026/10/304 天前
2.0.02026/10/294 天前
1.23.02026/10/276 天前
1.22.02026/10/2112 天前

其他发布通道:staging → 1.5.3。

关于 @simba-dev/react-native-media-player 的常见问题

@simba-dev/react-native-media-player 是什么?

React Native视频和音频播放器,由libmpv - Picture-in-Picture, MediaSession,前台服务和可定制的TypeScript UI提供支持。为Android打造。设计为一个插入式替代反应原生视频/反应原生轨道播放器/博览会av

如何安装 @simba-dev/react-native-media-player?

在项目目录运行 npm install @simba-dev/react-native-media-player,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=18.0.0)、react-native(>=0.76.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@simba-dev/react-native-media-player 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@simba-dev/react-native-media-player 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@simba-dev/react-native-media-player 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@simba-dev/react-native-media-player 可以商用吗?

@simba-dev/react-native-media-player 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@simba-dev/react-native-media-player 还在维护吗?

最新版本 3.0.0 发布于 2026/11/02(1 天前);至今共发布 63 个版本,其中过去 12 个月发布了 63 个;首次发布于 2026/09/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。