最新发布《数智时代的AI人才粮仓模型解读白皮书(2024版)》,立即领取! 了解详情
写点什么

Flutter 实时音视频实践

  • 2019-11-30
  • 本文字数:3767 字

    阅读完需:约 12 分钟

Flutter 实时音视频实践

前两期 RTC Dev Meetup:Flutter 开发技术专场 的回顾视频已被上传至了 RTC 开发者社区,欢迎大家浏览与交流。

我们整理了其中一个演讲内容——由声网 Agora 高级架构师 张乾泽分享的“Flutter 实时音视频实践”。以下为演讲实录。


我今天给大家介绍的是 Flutter 实时音视频开发实践方面的经验。我叫张乾泽,毕业于英国牛津大学,之前在 SAP 主要担任移动端架构师,2017 年加入声网 Agora,目前是声网 Agora 的高级架构师,主要负责 RTC 技术在娱乐、直播、教育等行业的应用研发工作。


首先我们讲到 RTC 应用,什么样是 RTC 应用呢?RTC 是 Real-time Communications。大家平时在日常生活中已经接触到非常非常多的 RTC 应用,比如说直播,大家平时会用手机看熊猫直播、斗鱼直播,实时看主播的游戏画面、他们唱歌的画面、跳舞的画面。还有教育,通过互联网可以实现远程教育,比如学生和美国的老师可以直接进行实时互动。


在医疗方面,我们最近也看到很多的案例。以前你要到医院挂号排队,等一上午,医生看一下,然后明天再来复诊时重新挂号,又是一个上午的时间过去了。现在有了 RTC 后,你可以通过视频直接在家里看医生,医生在视频中问你一些问题,如果病症简单,你甚至都不需要去医院。


今天我们就拿常见的视频通话的应用,来看看如何基于 Flutter 来开发实现,以及其中会有什么样的困难。

架构逻辑与实现思路

首先讲一下 Flutter 的架构逻辑。如果比较熟悉 Flutter 的朋友可能会知道,它的渲染方式跟 React Native 最不一样的地方就是它对于自己的一些原生控件,没有利用系统本身提供 View。那么开发应用的时候,怎么渲染出来的呢?



它自己里面会建立一个 Layer Tree,Layer Tree 里面是它的一个树状结构,它把数据或者渲染的地方发到 Skia,Skia 得到 GPU 的 Vsync 信号的时候,再把这些数据传给 GPU 统一渲染。完全没有通过类似 UI View 这样的 Native 的 View 的。


在知道这个概念之后,我就开始着手开发这个应用。这个应用因为它本身就提供了一些常用的组件,比如 App 的一个框架,一些按钮和导航栏,Flutter 有现成的组件可以让你直接把这些东西画上去,只需要通过一些非常简单的配置即可。


Flutter 本身也提供了与 Native SDK 的通讯的方式,叫做 Channel Massage,跟 React Native 调用 Native 的思路非常像。所以我们有了声网 Agora SDK,会帮我们处理音频编解码、音频的传输,然后我们可以利用 Flutter 本身的组件把 UI 也画好,好像这个东西就 Work 了。当一切都似乎变得那么美好的时候,我卡在了视频上。Flutter 怎么渲染视频?


在 Native 平台都有系统组件来渲染视频,但 Flutter 没有这样的东西。我现在要把实时视频渲染出来。


于是我查看了 Flutter 的源码,其中有一个组件叫 Video player,这是放视频的。其中有一个 Texture Widget,它在这种模式下提供了一种机制,可以让你进行视频的渲染。

实现思路一:Texture Widget

首先视频是由一帧帧图像组成的。Flutter 的 Texture 提供了一个可以放在 Layer Tree 里的组件,组件中的数据源需要由你通过 Native 端来提供。


在这里以 iOS 为例,iOS 就需要提供 CVPixelBufferRef。这是一个数据,对应的就是视频中的一帧画面。把这个数据作为数据源提供给 Texture Widget,然后 Texture Widget 就可以把你提供的这些数据显示出来,最终就变成了一个视频。



上图是大致的实现架构。首先要在 Dart 上实现一个 Native 的 Plugin。Plugin Registar 是 Plugin 的一个入口,有一个属性叫做 TextureRegistry,你可以在这里注册一个你自己的 Texture 类,这个类可能实现了一个协议叫 Flutter Texture。你实现这个协议过程中有两个方法需要实现:一个方法叫做 CVPixelBufferRef,就是要提供数据源到你的 Texture。另一个方法你需要自己主动去调,叫做 textureFrameAvailable,它的作用是告诉 TextureRegistry 现在可以根据提供的数据来更新画面了,就是我提供数据。


其中有一个问题,现在有 TextureWidget,如果更新数据源的话,它怎么才能知道我要更新哪个 Texture 呢?其实,在注册这 Texture 的时候,它会返回一个 TextureID。你在创建 Texture Widget 的时候需要把这个 TextureID 传进去。这样的话 Texture 的组件就会跟你提供的这个实践进行绑定,知道你提供的数据源就是为这个 Texture 提供的数据。以此类推,我们也可以有很多个 Texture。



回到我们之前的设计来看(如上图),我们这边是一个视频通话应用,我们有很多本地的视频,有很多的远端的视频,这些视频都可以是不同的 Texture Widget,放在 Dart 的页面容器中,然后我们分别为它们提供数据源,进行数据渲染。


是不是感觉现在一切准备就绪了?其实还有一个问题。Flutter 官方的 Github 提供了一些示例代码,但是它提供的功能是让你播放一个静态缓存,我们这里提供的是一个实时的视频流,不是一个视频文件。不可能以读取一个文件的方式,把里面的数据一帧一帧地转化之后,传给 Texture Widget。我们需要有一个方法拿到这些实时的数据,把它作为数据源传给 Texture。



这时候我们就需要使用声网 Agora SDK。首先给大家普及一个概念,大家想象一下平时在看一个直播的时候,直播那边有一个摄像头,他玩一些游戏,他跳一些舞、唱一些歌,是怎样让我在手机里面看到这些数据的呢?总结来讲是一个非常简单的流程,如上图所示。首先主播有一个摄像头,进行数据的采集。这些数据是裸数据。在拿到这些数据后,我们需要进行编码。在编码过程中,我们可以对数据进行处理和格式化,比如说让它有一个特定的分辨率和帧率。直播不会把摄像头的所有的数据都传过来,他会对数据进行压缩、处理,这就是编码的过程。在编码完成后,我们就有一个视频数据,它会通过声网的云服务,快速传输到你的手机上。手机客户端上也有声网的 SDK,在拿到数据后,会把数据进行解码,并提供一个方法,将这些视频数据传到 UI View 上,最终显示为你所看到的视频。



如上图所示,基于刚才的架构,我们添加了一个声网 SDK。SDK 有一个方法叫做 AgoraVideoSink。它提供了一个回调,会把收到的所有视频数据按照你想要的格式传给你。我们在得到回调数据后,再把他传给 Flutter Texture。我们可以设定一个更新频率,每当得到一次回调后,通过 notify 告诉 TextureRegistery 将新的数据更新到 Texture。通过这样的一个过程,我们就能实现一个 Flutter 的实时音视频 App 了。

实现思路二:PlatformView

由于 Texture 会涉及到很多渲染的流程,所以很多人都会觉得它有些复杂。所以在 Flutter 1.0 版本中,Google 给出了一个新的东西,叫做 PlatformView。



它提供了一种方法,让我们可以创建 UI View,并加到 Dart 的 LayerTree 里。在 Dart 中的类对应到 iOS 和 Android 平台分别是 UIKitView 和 AndroidView。


PlatformView 该怎么用呢?在 PluginRegistar 中新增了 ViewFactory,ViewFactory 只有 CreateView 这一个方法需要实现。你可以在这个方法里首先提供一个 Identifier,在实现该方法后,可以返回一个你想要的 PlatformView,并与 Dart 组件绑定在一起。


因为我们的 SDK 支持传递 Native 的 View,然后将视频渲染到上面。如上图,我们基于刚才的架构做一下改动。声网 SDK 中提供了一个 CustomViewFoctory,它的作用就是创建一个原生的 View,然后 SDK 的 AgoraRtcEngine 会与 View 绑定,在收到数据流的时候会自动将它渲染到这个 View 上。因为每个 View 会对应一个 ViewID。那么我们只需要通过 ViewID 就可以得到这个 View,然后把它渲染出来。

性能对比

总结一下,在 Flutter 中实现实时音视频有两种方式,一种是 Texture,另一种是 PlatformView。我们将它们与 Native 的实现方式进行了性能对比,结果如下图所示。



三者相比,Texture 的实现方式性能比较差。PlatformView 的性能与 Native 相近。就目前的 Demo 来看,造成 Texture 的方法性能较差的原因可能有两个:


  • 第一,在收到视频数据之后,会立刻更新 Texture,但这样做的必要性不大,如果进行一些优化的话,还可以提升一些性能;

  • 第二,我们是通过一个回调来获取数据,然后将它提供给 Flutter 的 Texture,这个过程是通过 CPU 来完成的,但通常来讲,渲染的工作需要由 GPU 来做,所以数据从 GPU 到 CPU 又再到 GPU,这个过程非常耗费资源。


总结一下,我个人对于 Texture 和 PlatformView 的优缺点比较。我个人觉得 Texture 这个东西实现“更 Dart”,什么叫“更 Dart”?就是没有很多原生的参与,比如 UI View ,更符合 Dart 的生态环境,在设计上更加纯粹。但是它也有缺点。如果用它做一些事情,不做特殊处理的话,可能很难避免 CPU、GPU 中间数据拷贝,造成性能损失。如果你要用它去做一个地图,那你就得把地图数据渲染放在 Flutter 上,用 Flutter 的逻辑全部重新实现一遍。这个对于大多数开发者来说,对于正在蓬勃发展中的一个生态来说是非常不利的。所以我个人认为这也是 Google 在 Flutter 1.0 加入了 PlatformView 的原因。



使用 PlatformView 有什么优点呢?我刚才说了,它可以把之前实现 Native View 的功能直接放在 Dart 里。对于开发者来说,更加简单易用。也可以避免前者存在在 CPU、GPU 数据拷贝带来的性能损失问题。但问题,它在设计上不那么纯粹,会引入一下不可控的因素。


本文转载自公众号声网 Agora(ID:shengwang-agora)。


原文链接:


https://mp.weixin.qq.com/s/8_epFcHKbaWT0P6IlyeXPg


2019-11-30 13:231855

评论

发布
暂无评论
发现更多内容

内地与香港司法协助落实,对 Web3.0 行业有何影响?

TechubNews

听懂一句AI实话,做成一件零售实事

脑极体

AI

Qt项目第二弹-文件加解密之RSA

springIce

rsa qt openssl

商汤科技日日新SenseNova 4.0发布:这⼀次,带来全新的AI体验!

Lily

2024-02-03:用go语言,你有 k 个背包。给你一个下标从 0 开始的整数数组 weights, 其中 weights[i] 是第 i 个珠子的重量。同时给你整数 k, 请你按照如下规则将所有

福大大架构师每日一题

福大大架构师每日一题

Docker里的基础术语有哪些?

百度搜索:蓝易云

Docker 云计算 运维 服务器 云服务器

@工控工程师,往这儿看!80%工控兄弟都在种草的宝藏应用,你知道几条?

AIRIOT

新增模型检验,指标自动评估模型效果|ModelWhale 版本更新

ModelWhale

人工智能 机器学习 大数据 数据分析 模型训练

Linux重启网卡报错Determining if ip address怎么解决?

百度搜索:蓝易云

云计算 Linux 运维 服务器 云服务器

ubuntu系统安装SGE教程

百度搜索:蓝易云

Linux 运维 服务器 云服务器 SGE

Linux命令之fg详解

百度搜索:蓝易云

云计算 Linux 运维 服务器 云服务器

什么是HTTP劫持,有什么方案能处理

德迅云安全杨德俊

专有云 ABC Stack 联合银联商务打造金融级云平台,入选《2024 央国企上云用云典型案例》

Baidu AICLOUD

专有云 金融云

Linux中如何检查或删除文本文件重复出现的行列?

百度搜索:蓝易云

Linux 运维 云服务器 sort uniq

喜报|博睿数据算力调度可观测平台荣获信通院“算力服务领航者计划”优秀案例

博睿数据

可观测性 运维监控

K8s 集群可观测性-数据分流最佳实践

观测云

K8s 多集群管理

关键词搜索拼多多商品列表数据接口Python

tbapi

拼多多API接口 关键词搜索拼多多API接口 拼多多商品列表数据接口

河南省政务民生、本地生活、新闻等垂域应用启动鸿蒙原生应用开发

最新动态

论文分享:利用对象存储进行高性能数据分析

Greptime 格睿科技

数据库 rust 对象存储 时序数据库

容器化对数据库的性能有影响吗?

小猿姐

数据库 Kubernetes 容器化

如何用NGINX实现UDP四层反向代理?

百度搜索:蓝易云

云计算 运维 服务器 udp 云服务器

基于客户真实使用场景的云剪辑Timeline问题解答与代码实操

阿里云视频云

云计算 视频云 云剪辑

完蛋!我把AI喂吐了!

有道技术团队

网易有道 AIGC Prompt QAnything

在线模型系统分布式异构计算演变-京东广告算法架构体系建设

京东零售技术

人工智能 机器学习 算法

想好新年去哪了吗?合合信息扫描全能王用AI“留住”年味

合合技术团队

文字识别 新年计划 图像处理 合合信息 扫描全能王

【AIOps】日志分析领域难题:如何对混合日志进行自动化解析?

华为云PaaS服务小智

人工智能 软件开发 华为云

淘宝app端商品详情数据采集

tbapi

投资更好的管理会计系统,探索全面预算管理的奥秘

智达方通

管理会计 全面预算管理

《UNIX环境高级编程(第3版)》PDF

程序员李木子

EigenLayer火的原因还有介绍

币离海

以太坊 EigenLayer 质押

Flutter 实时音视频实践_文化 & 方法_声网_InfoQ精选文章