DeepAR为您提供有趣的AR过滤器和3D面具,它们可以无缝地集成到您的移动应用程序中,让您的用户为他们的视频通话添加AR效果,用华丽的太阳镜捕捉视频,以及更多。
到目前为止,我们已经正式支持原生的Android、iOS和Web SDKs。宣布对Flutter的官方支持也是非常令人激动的
DeepAR Flutter插件的第一个版本支持我们大多数用户需要的所有主要功能(以后会有更多先进的东西)。
自然的选择是转向Flutter平台通道,并在现有的DeepAR Android和iOS SDK中建立一个包装。
对于任何不熟悉的人来说,Flutter平台通道提供了API来连接我们的Flutter代码和本地Android和iOS代码。这些都是用来建立任何依赖原生功能的插件,如播放音频和连接到蓝牙,仅举几例。
虽然Flutter平台通道允许我们调用原生的DeepAR方法,但由于数据从Dart→C++→Java/Swift再返回的过程中,确实带来了延迟的因素。它也会随着参数中传递的数据大小的增加而增加。
对于零星调用本地方法的方法来说,这种延迟不会导致任何问题--比如拍摄屏幕截图或切换过滤器。然而,对于需要传递大参数的流数据的方法来说,它可能是一个瓶颈,在我们的例子中,它是向DeepAR提供实时相机帧进行处理,然后作为一个小部件进行渲染。
在我们的第一次尝试中,我们试图建立在官方相机插件的基础上,因为它为用户提供了先进的功能,如开箱即用的缩放和对焦。该插件还暴露了startImageStream()方法,为我们提供了实时帧,然后我们可以将其传递给我们的本地实现进行处理。简单吧?
虽然这确实有效,但我们观察到应用程序的性能大幅下降,同时内存使用率也很高。原因是我们没有考虑到处理大字节的图像数据并通过平台桥传输到DeepAR本地方法的延迟和高内存消耗。
在使用Flutter开发工具进行检查时,我们发现大量的资源被消耗在将我们的 Uint8List 图像帧添加到JSON中,将其编码为 字节数据并在本地代码中解码。但是,有一个合适的优化方法来解决这个问题。
平台通道提供了多种编解码器来进行平台间的通信。StandardMessageCodec与JSON一起工作,导致了不必要的编码。我们很幸运,Flutter也提供了一个BinaryCodec,可以直接处理字节数据,这正是我们需要的。
优化后,性能明显改善,我们能够在谷歌Pixel 4A上顺利地运行和渲染框架。然而,内存消耗仍然很大。在2GB内存的低端设备上运行该插件,其性能并不令人满意,而且应用程序滞后。我们遇到了一个死胡同,没有进一步优化的可能,不得不想出一个不同的方法。
为了避免通过Flutter平台通道调集相机帧的瓶颈,我们决定编写我们自己的相机的本地实现,并将其直接与DeepAR配对。正如预期的那样,这工作得很好。
我们在Android和iOS上分别使用CameraX和CameraController。为了将帧渲染成Flutter小部件,我们有两个选择。
DeepAR使用OpenGL将其输出渲染到Android表面。FlutterTexture部件可以被配置为使用OpenGL图像源,这比原生视图的性能要好。因此,我们决定使用该纹理。
在Android上的实现是直接的,并顺利地工作。然而,在iOS上,FlutterTexture并没有为OpenGL提供一个直接的窗口(表面)来渲染。相反,要渲染的内容需要来自CVPixelBuffer。
DeepAR在被配置为产生CVPixelBuffers时,在CPU和内存使用方面有额外的开销。这在旧的iPhone设备上构成了一个性能问题。
为了解决这个问题,我们决定使用Native View来实现iOS。这导致了性能的显著提高,即使在iPhone 7上,我们也能获得足够好的性能。这就是梦想,对吗?
从这里开始,事情就相对简单了,我们使用一个dart包装器合并了两个本地实现,并添加了截图和录制视频的功能。我们暴露了一个DeepArController类,其方法类似于默认的相机包,以便为我们的开发者同伴保持简单。
请在pub.dev上查看该插件,源代码在这里。我们正在接受来自社区的修复和改进请求。我们也鼓励你在我们的GitHub仓库中为面临的任何问题提出问题。
用爱制造 💙
我们写关于AR案例研究、见解和我们正在创造的最新AR技术。