如何通过Flutter的sip_ua与webrtc包连接Free Switch PBX服务器
Flutter WebRTC 分步实现指南(适配Web端开发经验)
前提说明
Flutter中实现WebRTC依赖flutter_webrtc包,核心API和Web端的RTCPeerConnection、MediaStream等概念完全对齐,只是调用方式适配了Flutter的异步框架。
步骤1:添加依赖
在项目的pubspec.yaml中添加依赖:
dependencies: flutter_webrtc: ^0.9.46 # 请使用最新稳定版本
执行命令安装依赖:
flutter pub get
步骤2:初始化PeerConnection与本地媒体流
2.1 创建PeerConnection实例
和Web端逻辑一致,先配置ICE服务器,再初始化连接:
import 'package:flutter_webrtc/flutter_webrtc.dart'; final Map<String, dynamic> configuration = { 'iceServers': [ {'urls': 'stun:stun.l.google.com:19302'}, ] }; RTCPeerConnection? peerConnection; Future<void> initPeerConnection() async { peerConnection = await createPeerConnection(configuration); // 监听ICE候选生成事件 peerConnection!.onIceCandidate = (RTCIceCandidate candidate) { // 将候选通过信令服务器发送给对方 sendCandidateToSignalingServer(candidate.toMap()); }; // 监听远程媒体流添加事件 peerConnection!.onTrack = (RTCTrackEvent event) { if (event.streams.isNotEmpty) { // 获取远程流用于渲染 setState(() { remoteStream = event.streams[0]; }); } }; }
2.2 获取本地摄像头/麦克风流
对应Web端的getUserMedia方法,调用Flutter的同名异步方法:
MediaStream? localStream; Future<void> getLocalStream() async { final Map<String, dynamic> constraints = { 'audio': true, 'video': { 'facingMode': 'user', // 前置摄像头 'width': 1280, 'height': 720, } }; localStream = await navigator.mediaDevices.getUserMedia(constraints); // 将本地流添加到PeerConnection if (peerConnection != null) { localStream!.getTracks().forEach((track) { peerConnection!.addTrack(track, localStream!); }); } }
步骤3:信令交互(Offer/Answer流程)
逻辑和Web端完全一致,用Flutter异步语法实现:
3.1 发起方创建Offer
Future<void> createOffer() async { if (peerConnection == null) return; final RTCSessionDescription offer = await peerConnection!.createOffer(); await peerConnection!.setLocalDescription(offer); // 将Offer通过信令服务器发送给接收方 sendOfferToSignalingServer(offer.toMap()); }
3.2 接收方处理Offer并创建Answer
Future<void> handleRemoteOffer(Map<String, dynamic> offerMap) async { if (peerConnection == null) return; final RTCSessionDescription remoteOffer = RTCSessionDescription( offerMap['sdp'], offerMap['type'], ); await peerConnection!.setRemoteDescription(remoteOffer); // 创建Answer并发送给发起方 final RTCSessionDescription answer = await peerConnection!.createAnswer(); await peerConnection!.setLocalDescription(answer); sendAnswerToSignalingServer(answer.toMap()); }
3.3 发起方处理远程Answer
Future<void> handleRemoteAnswer(Map<String, dynamic> answerMap) async { if (peerConnection == null) return; final RTCSessionDescription remoteAnswer = RTCSessionDescription( answerMap['sdp'], answerMap['type'], ); await peerConnection!.setRemoteDescription(remoteAnswer); }
步骤4:处理ICE候选
接收方收到对方发送的ICE候选后,添加到本地PeerConnection:
Future<void> handleRemoteCandidate(Map<String, dynamic> candidateMap) async { if (peerConnection == null) return; final RTCIceCandidate candidate = RTCIceCandidate( candidateMap['candidate'], candidateMap['sdpMid'], candidateMap['sdpMLineIndex'], ); await peerConnection!.addCandidate(candidate); }
步骤5:渲染视频流
使用Flutter提供的RTCVideoView组件渲染本地和远程流:
@override Widget build(BuildContext context) { return Column( children: [ // 本地视频渲染 if (localStream != null) RTCVideoView( localStream!, objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, ), // 远程视频渲染 if (remoteStream != null) RTCVideoView( remoteStream!, objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, ), ], ); }
关键差异说明
- Flutter中所有异步操作依赖
Future,需用async/await处理,和Web端Promise逻辑一致但语法不同 - 视频渲染必须使用
RTCVideoView组件,而非Web端的video标签 - 事件监听通过设置
onIceCandidate、onTrack等属性实现,等价于Web端的addEventListener
内容的提问来源于stack exchange,提问作者M.zafar shafaq
相关产品推荐
相关产品推荐

