mcpField
R
react-native-moq

react-native-moq

github.com/software-mansion-labs开发296414 次安装2 周前更新
代码仓库

关于 react-native-moq

react-native-moq 是基于 moq-kit 的 React Native MoQ 绑定,供需要在移动应用中发布或播放实时媒体的开发者使用。它通过 React hooks 和命令式接口处理视频、音频及数据轨道,并连接 MoQ 中继。

主要功能

  1. 01连接 MoQ 中继并发现广播
  2. 02播放视频和音频广播
  3. 03通过摄像头与麦克风发布媒体
  4. 04发布和接收数据轨道
  5. 05提供 hooks 与命令式接口

适用场景

  1. 01在 React Native 应用中观看实时广播
  2. 02从移动设备发布摄像头和麦克风媒体
  3. 03在客户端之间传递数据消息

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/software-mansion-labs/skills --skill react-native-moq

安装后在 Claude Code 中输入/react-native-moq确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
custom-tracks.md
imperative.md
playback.md
publishing.md

详细介绍

react-native-moq

Media over QUIC(MoQ)的 React Native 绑定:通过 MoQ 中继发布和接收实时视频、音频和数据轨道,延迟低于 1 秒。基于 Software Mansion 的 moq-kit 原生库构建。

**要求:**React Native 新架构(Fabric + TurboModules)、iOS 16+、Android API 30+。

npm install react-native-moq
cd ios && pod install

可选播放器界面(全屏模态框、控件、音量滑块):

npm install react-native-moq-ui @react-native-vector-icons/material-icons

iOS 还需要在 Info.plist 的 UIAppFonts 下添加 MaterialIcons.ttf,然后再次运行 pod install。如果你要在 <VideoView> 上自行组合播放器 UI,可以跳过此软件包。

心智模型

  • Session 是与 MoQ 中继的一个连接(useSession(url))。它不会自动连接——需要自行调用 session.connect()。一个 session 可同时用于订阅和发布。
  • 订阅:useBroadcasts(session, prefix) 会列出路径前缀下的实时广播 → 选择一个 BroadcastInfo → useVideoPlayer / useAudioPlayer → 使用 <VideoView player={player}> 渲染。原始媒体的替代方案:useAudioChunks(将编码数据或 PCM 传至 JS)和 useDataMessages(字符串载荷)。
  • 发布:采集钩子会生成轨道(useCamera、useMicrophone、useMultiCamera),也可以自行生成轨道(useDataTrack、useAudioSource、useVideoSource)→ 使用 usePublisher(session).publish({ path, tracks })。屏幕共享(useScreenBroadcast)独立运行,不在进程内。
  • 每个钩子都有不使用钩子的对应 API——有状态对象使用 create*(返回对象和 destroy()),订阅钩子使用 subscribe*(返回 start() / stop())——详见 references/imperative.md。
  • 对象会公开响应式状态(session.state、publisher.state、player.isPlaying 等);状态变更时钩子会触发重新渲染。可以使用 addListener 或 useEvent / useEventListener 辅助函数手动订阅。

快速入门 — 观看

function Watch() {
  const session = useSession('https://relay.example.com', (s) => s.connect());
  const broadcasts = useBroadcasts(session, ''); // '' = all paths
  return broadcasts.map((b) => <BroadcastPlayer key={b.path} broadcast={b} />);
}

function BroadcastPlayer({ broadcast }: { broadcast: BroadcastInfo }) {
  const player = useVideoPlayer(broadcast, (p) => p.play());
  return <VideoView player={player} style={{ width: '100%', aspectRatio: 16 / 9 }} />;
}

useVideoPlayer / useAudioPlayer 需要非空广播——请在仅当广播存在时才渲染的子组件中挂载它们。

快速入门 — 开始直播

const session = useSession(url, (s) => s.connect());
const camera = useCamera();
const microphone = useMicrophone();
const publisher = usePublisher(session);

<PublisherView camera={camera} style={styles.preview} />
// when session.state === 'connected':
publisher.publish({ path: 'live/test', tracks: [camera, microphone] });

重要规则

  1. **错误是字符串,不是异常。**状态是类似 'connected' | 'error:...' 的联合类型;请检查 state.startsWith('error:')。媒体故障不会抛出异常。Session 仅在状态字符串中携带错误消息(state.slice(6));采集轨道和发布器还会公开 lastError 字段。播放器完全没有错误状态——应改为关注 session 和发布器状态。
  2. publish() 要求 session.state === 'connected',否则发布器会直接进入 error:session is not connected 状态。请根据 session 状态控制开始直播按钮。
  3. **使用 getSupportedVideoCodecs() / getSupportedAudioCodecs() 检查编解码器支持情况。**在 Android 上,不受支持的编码器(通常是 h265)会导致发布开始后悄然停止,且没有错误提示。默认使用 h264 / opus。
  4. 权限由宿主应用负责处理——在 Android 上请求 CAMERA/RECORD_AUDIO 权限,在 iOS 上添加 NSCameraUsageDescription/NSMicrophoneUsageDescription。预览画面为黑色通常是因为缺少权限。
  5. <VideoView> 不接受子元素(Android 原生视图不是 ViewGroup)。请将叠加层渲染为采用绝对定位的同级元素。
  6. 采集钩子使用引用计数的设备单例——所有使用者共享同一个物理摄像头/麦克风;flip() 会影响所有使用者。挂载期间若要关闭硬件,请使用 enabled: false,不要有条件地调用钩子。
  7. 广播路径相对于订阅前缀(在前缀 'live' 下,广播 live/test 会显示为 path: 'test')。使用 '' 订阅即可查看完整路径。列出的广播无法播放(中继错误 code=13 NotFound)表示路径与前缀不匹配。
  8. 数据轨道不会出现在目录中——发布端和订阅端必须通过其他方式约定轨道名称(默认为 'data')。
  9. iOS 上闲置的麦克风采集会使音频会话保持在 playAndRecord 状态,并可能阻塞其他音频库(insufficientPriority)。不发布时,请禁用麦克风(enabled: false)。

参考资料

任务阅读
会话、广播发现、视频/音频播放、<VideoView>、统计信息、轨道切换、事件、react-native-moq-uireferences/playback.md
摄像头、多摄像头、麦克风、发布者生命周期、屏幕广播、编解码器查询references/publishing.md
数据轨道与消息、将音频块传至 JS、自行推送音频(PCM)和视频(帧缓冲区)references/custom-tracks.md
不使用 React:create* 句柄、subscribe* 函数、清理references/imperative.md

评论

支持 Markdown