You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Expo在React Native中实现视频通话功能

在Expo React Native应用中实现视频通话功能

作为Expo新手,推荐两种实现路径:基于WebRTC原生实现(适合自定义需求)或使用第三方视频通话服务(快速上手,降低复杂度)。

方案一:使用Expo WebRTC(原生WebRTC实现)

WebRTC是实时音视频通信的标准协议,Expo提供expo-webrtc库直接支持该能力。

步骤1:安装依赖

npx expo install expo-webrtc expo-permissions

注:expo-permissions已标记为弃用,也可使用Expo新权限API(如expo-camera的权限方法),上述命令兼容现有项目。

步骤2:配置权限

在app.json的expo字段中添加摄像头和麦克风权限:

"expo": {
  // ...其他配置
  "permissions": [
    "CAMERA",
    "RECORD_AUDIO"
  ]
}

步骤3:实现基础通话逻辑

WebRTC需要信令服务器交换双方的SDP会话描述和ICE候选网络地址,你可以用WebSocket搭建简单信令服务,或使用开源服务。核心代码示例:

import React, { useState, useEffect, useRef } from 'react';
import { View, Button, StyleSheet } from 'react-native';
import { RTCPeerConnection, RTCView, mediaDevices } from 'expo-webrtc';
import * as Permissions from 'expo-permissions';

const VideoCall = () => {
  const [localStream, setLocalStream] = useState(null);
  const [remoteStream, setRemoteStream] = useState(null);
  const peerConnectionRef = useRef(null);

  // 请求权限并初始化本地流
  useEffect(() => {
    async function setupLocalStream() {
      const { status } = await Permissions.askAsync(Permissions.CAMERA, Permissions.RECORD_AUDIO);
      if (status !== 'granted') return;

      const stream = await mediaDevices.getUserMedia({ video: true, audio: true });
      setLocalStream(stream);
      
      // 创建PeerConnection实例
      const pc = new RTCPeerConnection({
        iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
      });
      peerConnectionRef.current = pc;

      // 添加本地流到PeerConnection
      stream.getTracks().forEach(track => pc.addTrack(track, stream));

      // 监听远程流
      pc.ontrack = (event) => {
        setRemoteStream(event.streams[0]);
      };

      // 监听ICE候选,通过信令通道发送给对方
      pc.onicecandidate = (event) => {
        if (event.candidate) {
          // 示例:socket.emit('ice-candidate', event.candidate);
        }
      };
    }
    setupLocalStream();

    return () => {
      localStream?.getTracks().forEach(track => track.stop());
      peerConnectionRef.current?.close();
    };
  }, []);

  // 创建通话Offer并发送给对方
  const createOffer = async () => {
    const pc = peerConnectionRef.current;
    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    // 示例:socket.emit('offer', offer);
  };

  return (
    <View style={styles.container}>
      {/* 本地视频画面 */}
      {localStream && (
        <RTCView streamURL={localStream.toURL()} style={styles.video} />
      )}
      {/* 远程视频画面 */}
      {remoteStream && (
        <RTCView streamURL={remoteStream.toURL()} style={styles.video} />
      )}
      <Button title="发起通话" onPress={createOffer} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    alignItems: 'center',
  },
  video: {
    width: 300,
    height: 400,
    marginVertical: 10,
    backgroundColor: '#000',
  },
});

export default VideoCall;

方案二:使用第三方视频通话服务(快速上手)

如果不想处理复杂的WebRTC信令和服务器,推荐用成熟的第三方服务(如Agora、Twilio),它们提供Expo专用SDK,开箱即用。

以Agora为例:

步骤1:安装依赖

npx expo install expo-agora

步骤2:获取App ID

去Agora控制台创建项目,获取专属App ID(直接官网注册即可)。

步骤3:实现通话功能

import React, { useState, useEffect } from 'react';
import { View, Button, StyleSheet } from 'react-native';
import { AgoraRtcEngine, AgoraVideoView } from 'expo-agora';

const APP_ID = '你的Agora App ID';

const VideoCallScreen = () => {
  const [engine, setEngine] = useState(null);
  const [isJoined, setIsJoined] = useState(false);

  // 初始化Agora引擎
  useEffect(() => {
    async function initEngine() {
      const agoraEngine = await AgoraRtcEngine.create(APP_ID);
      await agoraEngine.enableVideo();
      setEngine(agoraEngine);
    }
    initEngine();

    return () => {
      engine?.destroy();
    };
  }, []);

  // 加入通话频道
  const joinChannel = async () => {
    await engine?.joinChannel(null, 'test-call-channel', null, 0);
    setIsJoined(true);
  };

  // 离开通话频道
  const leaveChannel = async () => {
    await engine?.leaveChannel();
    setIsJoined(false);
  };

  return (
    <View style={styles.container}>
      {isJoined && (
        <AgoraVideoView
          style={styles.video}
          videoId={0} // 本地视频流ID
          mode="rtc"
          channelId="test-call-channel"
        />
      )}
      <Button 
        title={isJoined ? '结束通话' : '加入通话'} 
        onPress={isJoined ? leaveChannel : joinChannel} 
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  video: {
    width: 300,
    height: 400,
    marginBottom: 20,
    backgroundColor: '#000',
  },
});

export default VideoCallScreen;

新手提示

  • 优先选第三方服务:自己搭建WebRTC信令服务器需要后端知识,第三方服务能让你快速完成功能,专注业务逻辑。
  • 测试用真机:Expo Go在模拟器上可能无法调用摄像头,建议用两台真机测试通话。
  • 处理权限拒绝:一定要捕获用户拒绝权限的情况,避免应用崩溃。
  • 自定义开发客户端:如果Expo Go不满足需求,可使用npx expo run:android/ios构建自定义开发客户端。

内容的提问来源于stack exchange,提问作者Itay Lador

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:15:36