Flutter WebRTC视频通信插件videosdk_webrtc的使用
Flutter WebRTC视频通信插件videosdk_webrtc的使用
功能性
功能特性 | Android | iOS | Web | macOS | Windows | Linux | 嵌入式 | Fuchsia |
---|---|---|---|---|---|---|---|---|
音频/视频 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | [WIP] | |
数据通道 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | [WIP] | |
屏幕捕获 | ✔️ | ✔️(*) | ✔️ | ✔️ | ✔️ | ✔️ | [WIP] | |
统一计划 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | [WIP] | |
多流传输 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | [WIP] | |
媒体录制 | ⚠️ | ⚠️ | ✔️ | |||||
SFrame/帧加密器 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ||
插入流 |
iOS
在您的Info.plist
文件中添加以下条目,该文件位于<项目根目录>/ios/Runner/Info.plist
:
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) Camera Usage!</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) Microphone Usage!</string>
这将允许您的应用程序访问摄像头和麦克风。
iOS注意事项
WebRTC.xframework编译版本在m104发布后不再支持iOS arm设备。因此,需要在您的项目的ios/Podfile
中添加以下行:
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
# Workaround for https://github.com/flutter/flutter/issues/64502
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES' # <= 这一行
end
end
end
Android
确保在您的Android Manifest文件中包含以下权限,该文件位于<项目根目录>/android/app/src/main/AndroidManifest.xml
:
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
如果需要使用蓝牙设备,请添加以下权限:
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
默认情况下,Flutter项目模板会添加这些权限,所以可能已经存在。
还需要将构建设置设为Java 8,因为官方WebRTC jar现在使用了EglBase
接口中的静态方法。只需在您的应用级build.gradle
中添加以下内容:
android {
//...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
如果有必要,在同一build.gradle
中您可能需要将defaultConfig
的minSdkVersion
增加到23(当前默认的Flutter生成器将其设置为16)。
完整示例代码
import 'dart:core';
import 'package:flutter/foundation.dart'
show debugDefaultTargetPlatformOverride;
import 'package:flutter/material.dart';
import 'package:flutter_background/flutter_background.dart';
import 'package:videosdk_webrtc/flutter_webrtc.dart';
import 'package:flutter_webrtc_example/src/capture_frame_sample.dart';
import 'src/device_enumeration_sample.dart';
import 'src/get_display_media_sample.dart';
import 'src/get_user_media_sample.dart'
if (dart.library.html) 'src/get_user_media_sample_web.dart';
import 'src/loopback_data_channel_sample.dart';
import 'src/loopback_sample_unified_tracks.dart';
import 'src/route_item.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
if (WebRTC.platformIsDesktop) {
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
} else if (WebRTC.platformIsAndroid) {
//startForegroundService();
}
runApp(MyApp());
}
Future<bool> startForegroundService() async {
final androidConfig = FlutterBackgroundAndroidConfig(
notificationTitle: 'Title of the notification',
notificationText: 'Text of the notification',
notificationImportance: AndroidNotificationImportance.Default,
notificationIcon: AndroidResource(
name: 'background_icon',
defType: 'drawable'), // 默认为mipmap文件夹下的ic_launcher
);
await FlutterBackground.initialize(androidConfig: androidConfig);
return FlutterBackground.enableBackgroundExecution();
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late List<RouteItem> items;
[@override](/user/override)
void initState() {
super.initState();
_initItems();
}
ListBody _buildRow(context, item) {
return ListBody(children: <Widget>[
ListTile(
title: Text(item.title),
onTap: () => item.push(context),
trailing: Icon(Icons.arrow_right),
),
Divider()
]);
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text('Flutter-WebRTC example'),
),
body: ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.all(0.0),
itemCount: items.length,
itemBuilder: (context, i) {
return _buildRow(context, items[i]);
})),
);
}
void _initItems() {
items = <RouteItem>[
RouteItem(
title: 'GetUserMedia',
push: (BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => GetUserMediaSample()));
}),
RouteItem(
title: 'Device Enumeration',
push: (BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
DeviceEnumerationSample()));
}),
RouteItem(
title: 'GetDisplayMedia',
push: (BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
GetDisplayMediaSample()));
}),
RouteItem(
title: 'LoopBack Sample (Unified Tracks)',
push: (BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
LoopBackSampleUnifiedTracks()));
}),
RouteItem(
title: 'DataChannelLoopBackSample',
push: (BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
DataChannelLoopBackSample()));
}),
RouteItem(
title: 'Capture Frame',
push: (BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
CaptureFrameSample()));
}),
];
}
}
更多关于Flutter WebRTC视频通信插件videosdk_webrtc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter WebRTC视频通信插件videosdk_webrtc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用videosdk_webrtc
插件进行视频通信的基本示例代码。请注意,这只是一个基础示例,实际项目中可能需要根据具体需求进行调整和扩展。
首先,确保你的Flutter项目已经创建好,并且在pubspec.yaml
文件中添加了videosdk_webrtc
依赖:
dependencies:
flutter:
sdk: flutter
videosdk_webrtc: ^最新版本号 # 请替换为实际可用的最新版本号
然后运行flutter pub get
来安装依赖。
接下来是示例代码,这里展示如何初始化WebRTC并进行基本的视频通信设置。
main.dart
import 'package:flutter/material.dart';
import 'package:videosdk_webrtc/videosdk_webrtc.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter WebRTC Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: VideoCallScreen(),
);
}
}
class VideoCallScreen extends StatefulWidget {
@override
_VideoCallScreenState createState() => _VideoCallScreenState();
}
class _VideoCallScreenState extends State<VideoCallScreen> {
late VideoRTC videoRTC;
@override
void initState() {
super.initState();
initWebRTC();
}
void initWebRTC() {
videoRTC = VideoRTC(
config: RTCConfiguration(
// 配置你的STUN/TURN服务器信息
iceServers: [
RTCIceServer(urls: ['stun:stun.l.google.com:19302']),
// 如果需要TURN服务器,请添加相应的配置
// RTCIceServer(
// urls: ['turn:your-turn-server-url'],
// username: 'your-username',
// credential: 'your-credential',
// ),
],
),
onLocalStream: (MediaStream stream) {
// 处理本地视频流
print('Local stream available');
},
onRemoteStream: (MediaStream stream, String peerId) {
// 处理远程视频流
print('Remote stream available from $peerId');
},
onError: (String errorMessage) {
// 处理错误
print('Error: $errorMessage');
},
);
// 开始获取本地媒体流
videoRTC.startLocalMediaStream();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter WebRTC Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 显示本地视频
Container(
width: 300,
height: 400,
child: videoRTC.localVideoRenderer != null
? RTCVideoRendererWidget(videoRenderer: videoRTC.localVideoRenderer!)
: Center(child: CircularProgressIndicator()),
),
SizedBox(height: 20),
// 显示远程视频(假设只有一个远程对等体)
Container(
width: 300,
height: 400,
child: videoRTC.remoteVideoRenderers.isNotEmpty
? RTCVideoRendererWidget(videoRenderer: videoRTC.remoteVideoRenderers.first)
: Container(),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 连接到远程对等体(这里需要实现具体的信令机制来交换SDP和ICE候选)
// 例如,通过WebSocket或其他方式发送offer/answer
// connectToRemotePeer();
},
child: Text('Connect to Remote Peer'),
),
],
),
),
);
}
// 这是一个假设的方法,用于连接到远程对等体
// 你需要实现自己的信令机制来交换SDP和ICE候选
void connectToRemotePeer() async {
// 创建offer
RTCSessionDescription offer = await videoRTC.createOffer();
// 设置本地描述
await videoRTC.setLocalDescription(offer);
// 发送offer到远程对等体(通过信令服务器)
// ...
// 接收remote description(answer)并设置
// RTCSessionDescription answer = ...; // 从信令服务器接收
// await videoRTC.setRemoteDescription(answer);
// 添加ICE候选(从信令服务器接收)
// videoRTC.addIceCandidate(...);
}
@override
void dispose() {
videoRTC.dispose();
super.dispose();
}
}
注意事项:
-
信令机制:上述代码中的
connectToRemotePeer
方法是一个占位符,你需要实现自己的信令机制来交换SDP和ICE候选。这通常通过WebSocket、Firebase或其他实时通信服务来完成。 -
错误处理:在实际应用中,需要更全面的错误处理逻辑,以确保在各种网络条件下都能稳定工作。
-
UI优化:示例中的UI非常简单,实际项目中可能需要更复杂的布局和交互设计。
-
权限处理:在Android和iOS上,你需要确保在
AndroidManifest.xml
和Info.plist
中添加了必要的权限,以允许应用访问摄像头和麦克风。 -
TURN服务器:如果你的应用需要在NAT后面进行通信,可能需要配置TURN服务器。TURN服务器通常需要付费,并且会增加延迟。
-
依赖版本:确保使用最新版本的
videosdk_webrtc
插件,并查阅其官方文档以获取最新的API和配置信息。
这个示例提供了一个基本的框架,你可以在此基础上根据具体需求进行扩展和优化。