写点什么

AR+ 实时音视频通话,虚拟与现实无缝结合

  • 2019-10-09
  • 本文字数:4244 字

    阅读完需:约 14 分钟

AR+ 实时音视频通话,虚拟与现实无缝结合

今年中旬 Google 在万众期待下推出了 ARCore,能将现实与数码完美无缝地融合在一起,丰富我们的现实世界。通过它开发者可以更加快速方便地在 Android 平台开发 AR 应用,凭借 AR 技术大量产品能找到新颖的应用场景,甚至开辟出新的一条产品线。


目前市场上已经有不少基于 AR 技术的产品,例如宜家家居的 IKEA Place 应用提供了新型的在线选购家俬方式,用户只需要将手机摄像头摆向想要放置家具的角落,接着选取你想要的家具,通过简单的拖拉以及旋转即可完成布局,查看这件家具是否符合你的心意。


下图为使用 IKEA Place 的示意图,看起来这张椅子还挺适合的 :)



那么假如 AR 与其他技术进行结合,是否会有更激动人心的应用场景呢?


七牛实时音视频云 (以下简称七牛 RTN)基于已被广泛标准化的 WebRTC 技术栈,有全平台的兼容性,支持各大浏览器如 Chrome、Safari、Firefox 以及各端 Android、iOS、Windows 等。强大的七牛实时音视频流媒体网络在全球有 180 多个数据中心,具有强大的链路加速功能,丰富的节点保证了无论客户分布在全球的什么地区都可以获得加速。平均 200ms 的超低延时,为诸多对实时性有苛刻要求的客户场景提供最根本支持,如一对一语聊、聊天室、视频会议、在线教育等对交互性有强需求的场景均十分适合使用七牛 RTN。


在本篇中,我们会结合 Google 官方的示例 helloarjava将 AR 技术融入到实时音视频通话,其中会应用到 1.1.0+ 版本七牛 RTN SDK 的新功能 「外部音视频数据导入」。


以下为效果动图:


集成七牛 RTN SDK 到 AR Demo

在真正开始编码前,我们需要先将相应的项目和环境搭建完成

下载 七牛 RTN SDK 到当前目录 QNRTC-Android

git clone git@github.com:pili-engineering/QNRTC-Android.git
复制代码

下载 ARCore 到当前目录 arcore-android-sdk

git clone git@github.com:google-ar/arcore-android-sdk.git
复制代码

拷贝相应七牛 RTN SDK 文件到 helloarjava 工程中

1.将文件 QNRTC-Android/releases/qndroid-rtc-1.2.0.jar 拷贝到 arcore-android-sdk/samples/hello_ar_java/app/libs/ 中(libs 目录需要自行创建)


2.将 QNRTC-Android/releases/ 下的 armeabi、armeabi-v7a、arm64-v8a、x86 等 4 个文件夹拷贝到 arcore-android-sdk/samples/hello_ar_java/app/src/main/jniLibs 文件夹中(jniLibs 目录需要自行创建)


3.使用 AndroidStudio 打开 arcore-android-sdk/samples/hello_ar_java 工程,修改其中几项配置:


  • 为了让工程引用上面两步中添加的库,打开 app/build.gradle 文件,在 中增加行


implementation fileTree(include: ['*.jar'], dir: 'libs')
复制代码


  • 为了能进行实时通话,需要设置程序使用网络的权限,打开 AndroidManifest.xml 文件,在 manifest 标签中增加以下使用权限声明:


(1)<uses-permission android:name="android.permission.INTERNET"/>
(2)<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
复制代码

核心类介绍

在实际编码与代码分析前,我们先简单概述介绍其中会涉及到的核心类


QNRTCManager:七牛 RTN SDK 核心类,提供低延时实时音视频通话能力


Session:ARCore 核心类,管理 AR 系统状态包括摄像头 Camera 采集、点网监测、平面检测等能力


GLSurfaceView & Renderer:Android 系统提供的视图类与渲染类,分别提供负责画面显示与渲染


BackgroundRenderer & ObjectRenderer & PlaneRenderer & PointCloudRenderer: Demo 中提供的渲染类,分别负责以下部分的渲染:


  • 背景图渲染(摄像头预览原始图)

  • 物体及其阴影渲染(Android 模型及其阴影)

  • 平面渲染(AR 系统检测到的平面)

  • 点云渲染(AR 系统检测到的点云)

建立基本的实时音视频通话环境

首先需要实现实时音视频的房间事件监听器 QNRoomEventListener,其需要实现的方法很多,以下只展现这次简单示例需要用到的方法,完整的接口说明在这里


public class HelloArActivity extends AppCompatActivity implements GLSurfaceView.Renderer, QNRoomEventListener {    private boolean mPublished = false; // 标识本地是否发布成功
...
@Override public void onJoinedRoom() { mRTCManager.publish(); // 加入房间成功后,尝试发布 }
@Override public void onLocalPublished() { mPublished = true; // 发布成功后,标识为 true }
...}
复制代码


在 onCreate 方法尾部初始化实时音视频通话环境并加入指定房间,其中关于 Room Token 获取的方式可以参考这里


protected void onCreate(Bundle savedInstanceState) {    ...    QNRTCSetting setting = new QNRTCSetting();    setting.setExternalVideoInputEnabled(true); // 开启外部视频导入功能
mRTCManager.setRoomEventListener(this); // 设置房间事件监听器 mRTCManager.initialize(this, setting); // 七牛 RTN SDK 初始化
mRTCManager.joinRoom(###Your Room Token###); // 通过 Room Token 加入指定房间}
复制代码

建立基本的 AR 环境

利用 GLSurfaceView & Renderer 为绘制 AR 画面做好准备

在 Activity 类声明中实现 GLSurfaceView.Renderer 接口,在本 Demo 中如下,随即需要我们实现 3 个相应的方法,意义分别在注释中被描述:


public class HelloArActivity extends AppCompatActivity implements GLSurfaceView.Renderer, QNRoomEventListener {    /**     * 显示 Surface 创建完成时回调    **/    public void onSurfaceCreated(GL10 gl, EGLConfig config) {    }
...
/** * 显示 Surface 尺寸大小改变时回调 **/ public void onSurfaceChanged(GL10 gl, int width, int height) { }
...
/** * 显示 Surface 创建完成时回调 **/ public void onDrawFrame(GL10 gl) { }}
复制代码


在实现了 Renderer 渲染类后,我们需要提供用作显示的 Surface,以便让 Renderer 在其上进行渲染显示,GLSurfaceView 就有这种能力。


以下示例代码,从布局 xml 文件中解析出 GLSurfaceView 并设置 Renderer


surfaceView = findViewById(R.id.surfaceview); // 从布局 xml 中解析 GLSurfaceView...surfaceView.setRenderer(this); // 设置 Renderer
复制代码

创建 Session

Session 是 AR 系统的主入口类,在任何 AR 操作前必须先初始化并启动


protected void onResume() {    session = new Session(/* context= */ this); // AR 系统初始化    ...    session.resume(); // 开始 AR 会话,尝试开启摄像头,如摄像头被占用,会抛出 CameraNotAvailableException 异常}
复制代码

使用 OpenGL Shader 在显示 Surface 上绘制 AR 增强画面

在 AR 会话开始后,摄像头的每一帧数据都能提供以下信息


  • 原始摄像头预览数据

  • 检测到的平面数组

  • 检测到的点云数组

  • 平面触摸事件


我们可以在 onDrawFrame 方法中利用以上的事件进行相应的处理,例如遇到平面触摸事件,则在相应的位置放上一个 Android 模型,并且同时绘制出检测到的平面以及点云。


// 绘制背景private final BackgroundRenderer backgroundRenderer = new BackgroundRenderer();// 绘制物体private final ObjectRenderer virtualObject = new ObjectRenderer();// 绘制物体阴影private final ObjectRenderer virtualObjectShadow = new ObjectRenderer();// 绘制平面private final PlaneRenderer planeRenderer = new PlaneRenderer();// 绘制云点private final PointCloudRenderer pointCloudRenderer = new PointCloudRenderer();
public void onDrawFrame(GL10 gl) { frame = session.update(); // 获取摄像头原始数据帧(阻塞方法)
// Handle one tap per frame. handleTap(frame, camera); // 检测是否有平面点击事件,如有则在相应位置放置 Android 模型
... // Draw background. backgroundRenderer.draw(frame); // 将摄像头预览数据作为背景图绘制
... // Visualize tracked points. PointCloud pointCloud = frame.acquirePointCloud(); pointCloudRenderer.update(pointCloud); pointCloudRenderer.draw(viewmtx, projmtx); // 绘制点云
... // Visualize planes. planeRenderer.drawPlanes(session.getAllTrackables(Plane.class), camera.getDisplayOrientedPose(), projmtx); // 绘制平面
... // Update and draw the model and its shadow. virtualObject.updateModelMatrix(anchorMatrix, scaleFactor); virtualObjectShadow.updateModelMatrix(anchorMatrix, scaleFactor); virtualObject.draw(viewmtx, projmtx, colorCorrectionRgba, coloredAnchor.color); // 绘制 Android 模型 virtualObjectShadow.draw(viewmtx, projmtx, colorCorrectionRgba, coloredAnchor.color); // 绘制 Android 模型的阴影}
复制代码

将 AR 增强画面发布到实时音视频云

在分别实现了基本的实时音视频通话和 AR 增强画面后,现在只需要将它们进行最后的结合。


因为 Session 启动后会占用设备摄像头,因此七牛 RTN SDK 无法进行采集,这时候我们需要使用最新版本提供的功能「外部音视频数据导入」。


在发布流前,我们需要获取到 AR 增强画面的 NV21 格式数据,因为当前七牛 RTN Android SDK 的「外部视频数据导入」功能只支持 NV21 格式的数据。


以下示例代码在 onDrawFrame 方法中的尾部添加,将 GLSurfaceView 的 Surface 内容数据读取出来,进行必要的格式转换,接着发布出去:


public void onDrawFrame(GL10 gl) {    ...
if (mPublished) { // 只在七牛 RTN 发布流成功后才导入 AR 数据 // 将 AR 增强画面 的数据从 GPU 中读取出来 GLES20.glReadPixels(0, 0, mSurfaceWidth, mSurfaceHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mBufferRGBA);
// RGBA 转为 NV21(篇幅原因,不在此展开算法) mBufferNV21 = RGBAToNV21(mBufferRGBA, mSurfaceWidth, mSurfaceHeight);
// 通过 "外部视频数据导入" 功能将 NV21 数据形式的 AR 增强画面 发布出去 mRTCManager.inputVideoFrame(mBufferNV21, mSurfaceWidth, mSurfaceHeight, 0, frame.getTimestamp()); }}
复制代码

总结:

使用 1.1.0+ 版本七牛 RTN SDK 提供的 “外部音视频数据导入” 功能,可以轻松地把 AR 和直播场景结合起来。以上程序基于七牛 RTN SDK 以及相应的 RTN 网络运行,最大可以支持 20 人同时视频连麦。可以预见,AR 技术会为实时音视频通话带来全新的体验。


本文转载自公众号七牛云(ID:qiniutek)。


原文链接:


https://mp.weixin.qq.com/s/OUg5SvOo0FP8yczCe9gZjw


2019-10-09 14:441105

评论

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

基于 Flagger 和 Nginx-Ingress 实现金丝雀发布

郭旭东

Kubernetes CI/CD

如何快速将 Linux 系统制作成 ISO 镜像文件?

JackTian

Linux 运维 操作系统 镜像文件 ISO

Linux 操作系统!开篇!!!

苹果看辽宁体育

Linux

ARTS-week5

王钰淇

ARTS 打卡计划

架构师训练营第五周总结

Melo

极客大学架构师训练营

极客大学架构师训练营 系统架构 分布式缓存 一致性哈希 Hash 第9课 听课总结

John(易筋)

极客时间 极客大学 极客大学架构师训练营 分布式缓存 一致性哈希

被“假”老干妈耍惨了?憨憨腾讯花1624万卖萌,引全网吃瓜!

程序员生活志

腾讯 互联网 大厂

七月份最新“美团+字节+腾讯”面试题,测试一下你能走到哪一面?

犬来八荒

Java 面试 线程’

去面试Spring Cloud 被问的35个问题

小谈

面试 springboot SpringCloud buffer JVM原理

使用 Flutter 快速实现请假与写周报应用

LeanCloud

flutter 后端 数据 教程

游戏夜读 | 关卡设计新手必看

game1night

当国产iVX遇上新晋产品PowerPlatform,能否披荆斩棘、稳住阵脚?

代码制造者

程序员 编辑器 低代码 快速开发 开发工具

架构0期Week4作业1

Nan Jiang

写给孩子的两本书我读得津津有味

孙苏勇

读书 陪伴 随笔杂谈

如果是你,年薪80万和阿里P7月薪36K,会怎么选?

犬来八荒

Java 腾讯 面试 阿里

终于有大佬把TCP/IP协议讲清楚了!面试再也不怂面试官提问了

小闫

jdk JVM Netty buffer TCP/IP

到底什么是HashMap?

小闫

Java spring 后端 JVM hashmap

【自学成才系列一】multipass安装篇

小朱

multipass

产业数字化无法“一蹴而就”,而是“长跑冠军”。

CECBC

模式与重构-作业

秤须苑

信创舆情一线--英特尔暂停向浪潮供货

统小信uos

服务器 舆情 芯片

再有人问你分布式事务,把这篇扔给他

码哥小胖

分布式 Java 分布式

最详细的 Spring Cloud OAuth2 单点登录使用教程送给大家

小闫

面试 后端 JVM SpringCloud

谈谈容器和K8s

Gabriel

面试官:十亿级数据ES搜索怎么优化?我直接傻了

犬来八荒

Java 面试 大厂

Google官方MVP+Dagger2架构详解

小吴选手

架构 架构师 架构是训练营

架构0期Week4作业2

Nan Jiang

Java面试常用知识(附赠最新面试题)

架构大数据双料架构师

腾讯的辣酱不香了 支付宝的区块链真能解决“萝卜章”问题?

CECBC

双链通 萝卜章 区块链方案

「NIO系列」——之Reactor模型

小谈

Spring Boot reactor 后端 nio SpringCloud

拥抱开源开放,易观技术开发者的星海征途

易观大数据

海豚调度 调度引擎

AR+ 实时音视频通话,虚拟与现实无缝结合_文化 & 方法_孔维乐_InfoQ精选文章