npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-webrtc-capture

v1.0.1

Published

Fork of react-native-webrtc with VideoFrame Hook - AI Analysis, Screenshot, Encoding

Readme

react-native-webrtc (增强版 - 支持截图)

📸 基于官方 react-native-webrtc 增强版本,新增 VideoFrame 截图功能(仅支持 Android)

npm npm Platform


📖 项目简介

本项目源自 react-native-webrtc,由于原项目没有提供截图功能,我们使用 MinimaxQwen AI 助手修改了源码,增加了实时视频帧截图功能。

当前状态:

  • ✅ Android 截图功能已实现
  • ❌ iOS 截图功能(待实现)

🚀 快速开始

1. 安装依赖

cd examples/GumTestApp
npm install

2. 启动开发服务器

# 启动 Metro Bundler
npm start

# 或者在新终端中
npx react-native start

3. 运行应用

# Android
npm run android

# 或者
npx react-native run-android

📸 截图功能使用指南

API 说明

VideoFrameCaptureModule.captureFrame(trackId)

捕获指定视频轨道的当前帧。

参数:

  • trackId (string): 视频轨道的 ID

返回值:

  • Promise<{ success: boolean, data?: string, error?: string }>
    • success: 是否成功
    • data: Base64 编码的 JPEG 图片(成功时)
    • error: 错误信息(失败时)

使用示例

import { mediaDevices, VideoFrameCaptureModule } from 'react-native-webrtc';

async function takeSnapshot() {
  try {
    // 获取本地视频流
    const stream = await mediaDevices.getUserMedia({
      video: {
        facingMode: 'user',
        width: { ideal: 1280 },
        height: { ideal: 720 }
      }
    });

    // 获取视频轨道 ID
    const videoTrack = stream.getVideoTracks()[0];
    const trackId = videoTrack.id;

    console.log('Track ID:', trackId);

    // 调用截图功能
    const result = await VideoFrameCaptureModule.captureFrame(trackId);

    if (result.success) {
      console.log('截图成功!');
      // result.data 是 Base64 格式的 JPEG 图片
      const imageUri = `data:image/jpeg;base64,${result.data}`;
      
      // 可以用于显示、保存或上传
      // 例如:<Image source={{ uri: imageUri }} />
    } else {
      console.error('截图失败:', result.error);
    }
  } catch (error) {
    console.error('错误:', error);
  }
}

完整示例代码

import React, { useState, useRef } from 'react';
import { View, Button, Image, StyleSheet } from 'react-native';
import {
  mediaDevices,
  RTCView,
  VideoFrameCaptureModule
} from 'react-native-webrtc';

export default function App() {
  const [stream, setStream] = useState(null);
  const [snapshot, setSnapshot] = useState(null);
  const streamRef = useRef(null);

  const startCamera = async () => {
    try {
      const newStream = await mediaDevices.getUserMedia({
        video: {
          facingMode: 'user',
          width: { ideal: 1280 },
          height: { ideal: 720 }
        }
      });
      setStream(newStream);
      streamRef.current = newStream;
    } catch (error) {
      console.error('启动摄像头失败:', error);
    }
  };

  const takeSnapshot = async () => {
    if (!streamRef.current) {
      alert('请先启动摄像头');
      return;
    }

    try {
      const videoTrack = streamRef.current.getVideoTracks()[0];
      const result = await VideoFrameCaptureModule.captureFrame(videoTrack.id);

      if (result.success) {
        setSnapshot(`data:image/jpeg;base64,${result.data}`);
        console.log('截图成功!尺寸:', result.width, 'x', result.height);
      } else {
        alert('截图失败:' + result.error);
      }
    } catch (error) {
      console.error('截图错误:', error);
      alert('截图异常:' + error.message);
    }
  };

  const stopCamera = () => {
    if (streamRef.current) {
      streamRef.current.getTracks().forEach(track => track.stop());
      streamRef.current = null;
      setStream(null);
    }
  };

  return (
    <View style={styles.container}>
      <View style={styles.videoContainer}>
        {stream && <RTCView streamURL={stream.toURL()} style={styles.video} />}
      </View>

      {snapshot && (
        <View style={styles.snapshotContainer}>
          <Image source={{ uri: snapshot }} style={styles.snapshot} />
        </View>
      )}

      <View style={styles.buttonRow}>
        <Button title="启动摄像头" onPress={startCamera} />
        <Button title="截图" onPress={takeSnapshot} />
        <Button title="停止" onPress={stopCamera} />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#000',
  },
  videoContainer: {
    flex: 1,
  },
  video: {
    flex: 1,
  },
  snapshotContainer: {
    height: 200,
    margin: 10,
    backgroundColor: '#333',
  },
  snapshot: {
    flex: 1,
  },
  buttonRow: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    padding: 10,
  },
});

🔧 技术实现细节

核心修改

截图功能通过以下核心组件实现:

  1. VideoFrameAdapter - 拦截 WebRTC 视频帧
  2. VideoFrameCapturer - 将 YUV 帧转换为 Bitmap
  3. VideoFrameCaptureModule - React Native 原生模块接口

视频处理流程

摄像头 → NV21/NV12 → MediaCodec → TextureBuffer (GPU)
                                      ↓
                              VideoFrameAdapter (拦截)
                                      ↓
                              toI420() 转换
                                      ↓
                              YUV → JPEG 压缩
                                      ↓
                              Base64 编码 → JavaScript

关键文件

android/src/main/java/com/oney/WebRTCModule/
├── VideoFrameHook/
│   ├── VideoFrameAdapter.java      # 视频帧拦截器
│   └── VideoFrameCapturer.java     # 帧捕获和转换
├── VideoFrameCaptureModule.java    # React Native 模块
└── WebRTCModule.java               # 主模块(包含截图逻辑)

📋 API 参考

mediaDevices.getUserMedia(constraints)

获取本地媒体流。

const stream = await mediaDevices.getUserMedia({
  video: {
    facingMode: 'user',  // 'user' | 'environment'
    width: { ideal: 1280 },
    height: { ideal: 720 },
    frameRate: { ideal: 30 }
  },
  audio: true
});

VideoFrameCaptureModule.captureFrame(trackId)

捕获视频帧。

const result = await VideoFrameCaptureModule.captureFrame(trackId);
// result: { success: true, data: "base64...", width: 1280, height: 720 }

🐛 已知问题

  1. 仅支持 Android - iOS 版本尚未实现
  2. 性能影响 - 截图时会轻微影响视频渲染性能
  3. 内存占用 - 高分辨率截图会暂时增加内存使用

🛠️ 开发调试

查看日志

# Android Logcat
adb logcat | grep -E "VideoFrame|WebRTC"

# 过滤截图相关日志
adb logcat | grep "VideoFrameCapturer"

关键日志输出

===== convertToBitmap: Buffer class = org.webrtc.TextureBufferImpl
===== convertToBitmap: frame size = 1280x720
===== convertToBitmap: I420 size = 1280x720
===== YUV stats (fixed): Y avg=128, U avg=180, V avg=150
===== JPEG size: 145663
===== Bitmap created: 1280x720

📚 参考资料


🤝 贡献

欢迎提交 Issue 和 Pull Request!

待实现功能

  • [ ] iOS 截图支持
  • [ ] 视频录制功能
  • [ ] 实时滤镜处理
  • [ ] 自定义分辨率/质量设置

📄 许可证

本项目遵循与原始项目相同的许可证(MIT License)。


🙏 致谢

  • 感谢 react-native-webrtc 团队的基础工作
  • 感谢 MinimaxQwen AI 助手在开发过程中的技术支持

最后更新: 2026 年 4 月 1 日