Flutter-WebRTC 鸿蒙平台使用指南

1. 插件介绍

fluttertpc_flutter_webrtc 是一个专为开源鸿蒙(HarmonyOS)平台适配的 Flutter WebRTC 插件,基于官方的 flutter_webrtc 项目进行定制修改,提供了完整的 WebRTC 功能支持,包括实时音视频通信、设备管理、屏幕共享等核心能力。

主要功能特性

  • 设备管理:支持枚举、选择音频/视频输入输出设备
  • 媒体流处理:获取摄像头、麦克风媒体流,支持自定义分辨率和帧率
  • 对等连接:实现完整的 WebRTC 信令流程和媒体协商
  • 屏幕共享:支持获取屏幕共享媒体流
  • 数据通道:支持点对点数据传输

2. 插件安装与配置

2.1 Git 依赖引入

由于这是一个专为鸿蒙平台定制的修改版本,需要通过 Git 方式引入依赖。在 Flutter 项目的 pubspec.yaml 文件中添加以下配置:

dependencies:flutter_webrtc:git:url: https://gitcode.com/openharmony-sig/fluttertpc_flutter_webrtc 

然后执行以下命令获取依赖:

flutter pub get 

2.2 鸿蒙平台权限配置

在鸿蒙应用中使用 WebRTC 功能需要配置以下权限:

2.2.1 配置旋转权限

打开 entry/src/main/module.json5 文件,为 EntryAbility 添加自动旋转配置:

"abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", "description": "$string:EntryAbility_desc", "icon": "$media:icon", "label": "$string:EntryAbility_label", "startWindowIcon": "$media:startIcon", "startWindowBackground": "$color:start_window_background", "exported": true, "skills": [ // ... ], "orientation": "auto_rotation", // 添加自动旋转支持 } ] 
2.2.2 配置应用权限

entry/src/main/module.json5 文件中添加以下权限配置:

"requestPermissions": [ { "name" : "ohos.permission.INTERNET", "reason": "$string:internet" }, { "name" : "ohos.permission.CAMERA", "reason": "$string:camera" }, { "name": "ohos.permission.MICROPHONE", "reason": "$string:microphone" } ] 
2.2.3 配置权限描述

打开 entry/src/main/resources/base/element/string.json 文件,添加权限描述:

{"string":[{"name":"internet","value":"需要网络权限以进行实时通信"},{"name":"camera","value":"需要相机权限以捕获视频"},{"name":"microphone","value":"需要麦克风权限以捕获音频"},]}

3. API 使用示例

3.1 设备枚举

import'package:flutter_webrtc/flutter_webrtc.dart';// 枚举所有媒体设备 Future<void>enumerateDevices()async{ List<MediaDeviceInfo> devices =await navigator.mediaDevices.enumerateDevices();// 分类设备 List<MediaDeviceInfo> audioInputs = devices.where((device)=> device.kind =='audioinput').toList(); List<MediaDeviceInfo> audioOutputs = devices.where((device)=> device.kind =='audiooutput').toList(); List<MediaDeviceInfo> videoInputs = devices.where((device)=> device.kind =='videoinput').toList();// 打印设备信息print('音频输入设备: ${audioInputs.map((d) => d.label).toList()}');print('音频输出设备: ${audioOutputs.map((d) => d.label).toList()}');print('视频输入设备: ${videoInputs.map((d) => d.label).toList()}');}

3.2 获取媒体流

// 初始化视频渲染器final RTCVideoRenderer _localRenderer =RTCVideoRenderer();await _localRenderer.initialize();// 获取摄像头和麦克风媒体流 Future<void>getUserMedia()async{try{ MediaStream stream =await navigator.mediaDevices.getUserMedia({'audio':true,'video':{'width':1280,'height':720,'frameRate':30,},});// 设置渲染器源 _localRenderer.srcObject = stream;// 获取轨道信息 List<MediaStreamTrack> tracks = stream.getTracks();print('获取到的媒体轨道: ${tracks.map((t) => t.kind).toList()}');}catch(e){print('获取媒体流失败: $e');}}

3.3 配置对等连接

// 创建对等连接 RTCPeerConnection? _peerConnection; Future<void>initPeerConnection()async{try{ _peerConnection =awaitcreatePeerConnection({});// 监听 ICE 候选 _peerConnection!.onIceCandidate =(RTCIceCandidate candidate){// 发送 ICE 候选到远程端print('ICE 候选: $candidate');};// 监听连接状态 _peerConnection!.onConnectionState =(RTCPeerConnectionState state){print('连接状态: $state');};// 监听远程流 _peerConnection!.onTrack =(MediaStreamTrackEvent event){if(event.track.kind =='video'){// 设置远程视频渲染器源 _remoteRenderer.srcObject = event.streams[0];}};}catch(e){print('初始化对等连接失败: $e');}}

3.4 媒体协商流程

// 创建 Offer Future<void>createOffer()async{if(_peerConnection ==null)return;try{ RTCSessionDescription offer =await _peerConnection!.createOffer();await _peerConnection!.setLocalDescription(offer);// 发送 Offer 到远程端print('创建 Offer: $offer');}catch(e){print('创建 Offer 失败: $e');}}// 处理 Answer Future<void>handleAnswer(RTCSessionDescription answer)async{if(_peerConnection ==null)return;try{await _peerConnection!.setRemoteDescription(answer);print('设置远程 Answer 成功');}catch(e){print('设置远程 Answer 失败: $e');}}// 添加 ICE 候选 Future<void>addIceCandidate(RTCIceCandidate candidate)async{if(_peerConnection ==null)return;try{await _peerConnection!.addCandidate(candidate);print('添加 ICE 候选成功');}catch(e){print('添加 ICE 候选失败: $e');}}

3.5 切换音频/视频设备

// 切换音频输入设备 Future<void>switchAudioInput(String deviceId)async{if(_localStream ==null)return;try{// 获取新的音频流 MediaStream newStream =await navigator.mediaDevices.getUserMedia({'audio':{'optional':[{'sourceId': deviceId}],},'video':false,});// 替换音频轨道 MediaStreamTrack newTrack = newStream.getAudioTracks().first; RTCRtpSender? sender = _senders.firstWhereOrNull((s)=> s.track?.kind =='audio');if(sender !=null){await sender.replaceTrack(newTrack);}print('切换音频输入设备成功');}catch(e){print('切换音频输入设备失败: $e');}}

4. 完整示例应用

插件提供了完整的示例应用,展示了各个功能模块的使用方法。主要示例模块包括:

  • 设备枚举示例:演示如何枚举和选择媒体设备
  • 媒体流获取示例:演示如何获取和显示音视频流
  • 屏幕共享示例:演示如何获取屏幕共享流
  • 数据通道示例:演示如何使用 WebRTC 数据通道

运行示例应用

cd example flutter run 

5. 注意事项与兼容性

5.1 兼容性要求

  • Flutter SDK: 3.7.12-ohos-1.0.6 或更高版本
  • 鸿蒙 SDK: 5.0.0(12) 或更高版本
  • DevEco Studio: 5.0.13.200 或更高版本
  • 鸿蒙 ROM: 5.1.0.120 SP3 或更高版本

5.2 功能限制

目前鸿蒙平台不支持以下功能:

  • 媒体录制功能
  • 部分高级音视频处理特性

6. 总结

fluttertpc_flutter_webrtc 插件为鸿蒙平台提供了完整的 WebRTC 能力支持,使开发者能够轻松构建实时音视频通信应用。通过本文的介绍,您已经了解了该插件的安装配置、核心 API 使用以及最佳实践。

该插件遵循标准的 WebRTC API 设计,与其他平台的使用方式保持一致,降低了跨平台开发的学习成本。同时,它针对鸿蒙平台进行了专门优化,确保在鸿蒙设备上获得最佳的性能和兼容性。

加入社区

欢迎加入开源鸿蒙跨平台社区,与更多开发者交流学习:

开源鸿蒙跨平台社区

Read more

介绍终身机器人学习的数据集LIBERO

介绍终身机器人学习的数据集LIBERO

1 LIBERO的作用 LIBERO是一个用于研究多任务和终身机器人学习中知识迁移的综合基准测试平台,LIBERO是基于robosuite框架构建的。它专注于机器人操作任务,这些任务需要两类知识: 1. 陈述性知识:关于物体和空间关系的知识 2. 程序性知识:关于运动和行为的知识 2 核心原理 任务生成与基准设计 LIBERO提供了一个程序化生成管道,原则上可以生成无限数量的操作任务。系统包含130个任务,分为四个任务套件,每个套件都有受控的分布偏移: * LIBERO-Spatial/Object/Goal:专注于特定类型知识的迁移 * LIBERO-100:包含需要迁移纠缠知识的100个操作任务 学习框架 系统采用模仿学习作为主要学习方法,因为任务使用稀疏奖励函数(任务完成时获得+1奖励)。LIBERO提供高质量的人类遥操作演示数据集用于训练。 算法与策略架构 LIBERO实现了三种视觉运动策略网络: * bc_rnn_policy:基于RNN的行为克隆策略 * bc_transformer_policy:基于Transformer的行为克隆策略

Chrome 开发者工具(DevTools)快速入门——前端必备技能

Chrome 开发者工具(DevTools)快速入门——前端必备技能

在前端开发中,Chrome 开发者工具(DevTools) 是我们排查问题、优化性能、理解浏览器行为最强大的助手之一。无论是想快速定位页面样式异常、分析接口请求,还是调试 JavaScript 逻辑,DevTools 都能提供直观高效的方式帮助我们“看清代码背后发生了什么”。 这篇笔记将带你快速入门,从最基本的面板功能到常用调试技巧,让你能在实战中灵活运用它,提升开发效率与问题解决能力。 1. 打开方式与放大缩小 1. 快捷键: * Windows/Linux:F12 或 Ctrl + Shift + I * macOS:Command + Option + I 1. 右键打开:在页面任意元素上右键 → “检查 (Inspect)” 2. 菜单打开:点击右上角 ⋮ → “更多工具” → “开发者工具” 在使用 Chrome 开发者工具时,可以通过 鼠标滚轮 快速调整界面缩放。

【前端地图】地图基本操作控制——平移、缩放、旋转、手势控制、地图样式切换、全屏模式支持

【前端地图】地图基本操作控制——平移、缩放、旋转、手势控制、地图样式切换、全屏模式支持

🎮 第3节 | 地图基本操作控制 🎯 学习目标 老曹说:“地图不能动算什么地图?今天教你让地图飞起来!” 1. 🧭 掌握地图平移、缩放、旋转三大基础操作 2. 🖱️ 理解手势控制与事件监听机制 3. 🎨 实现地图样式动态切换(白天/黑夜/卫星图) 4. 🖥️ 支持全屏模式与自适应布局 🧠 引言:让用户掌控地图! 地图不只是看的,更是用来“玩”的!优秀的用户体验离不开流畅的操作反馈。本节课带你解锁地图操控的所有姿势,让你的地图像游戏一样丝滑。 老曹吐槽时间: “有些产品地图做得跟 PPT 似的,点都点不动……用户:你礼貌吗?” 🧭 一、三大基础操作详解 1.1 平移(Pan)📍 平移是最常见的操作,通过改变地图中心点实现视角移动。 ✅ 高德地图实现 // 方法一:直接设置中心点 map.setCenter([116.404,

前端人拿不到offer,九成是不知道这个新风向

今年大部分互联网公司面试的题目已经开始小部分八股文,大部分场景题了,公司需要的不仅是知识扎实,而且招进来就能上手项目的面试者… 2026最新高频场景题 * 1. 请求失败会弹出一个toast,如何保证批量请求失败,只弹出一个toast * 2. 如何减少项目里面if-else * 3. babel-runtime 作用是啥 * 4. 如何实现预览PDF文件 * 5. 如何在划词选择的文本上添加右键菜单(划词:鼠标滑动选择一组字符,对组字符进行操作) * 6. 富文本里面,是如何做到划词的(鼠标滑动选择一组字符,对组字符进行操作)? * 7. 如何做好前端监控方案 * 8. 如何标准化处理线上用户反馈的问题 * 9. px如何转为rem * 10. 浏览器有同源策略,但是为何 cdn 请求资源的时候不会有 跨域限制 * 11. cookie可以实现不同域共享吗 * 12. axios是否可以取消请求 * 13. 前端如何实现折叠面板效果? * 14. dom里面,如何判定a元素是否是b元素的子元 * 15. 判断一个对象是否为空,包含了其原型链上是否有自