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

AR+ 实时音视频通话,虚拟与现实无缝结合_第1张图片

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

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

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

AR+ 实时音视频通话,虚拟与现实无缝结合_第2张图片

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

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

在本篇中,我们会结合 Google 官方的示例 helloarjava(https://github.com/google-ar/arcore-android-sdk)将 AR 技术融入到实时音视频通话,其中会应用到 1.1.0+ 版本七牛 RTN SDK 的新功能 「外部音视频数据导入」。

以下为效果动图:

集成七牛 RTN SDK 到 AR Demo

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

下载 七牛 RTN SDK 到当前目录

      QNRTC-Android

git clone [email protected]:pili-engineering/QNRTC-Android.git

下载 ARCore 到当前目录 

      arcore-android-sdk

git clone [email protected]:google-ar/arcore-android-sdk.git

拷贝相应七牛 RTN SDK 文件到 

      helloarjava 工程中

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

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

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

为了让工程引用上面两步中添加的库,打开 app/build.gradle 文件,在    中增加行implementation fileTree(include: ['*.jar'], dir: 'libs')

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

(1)

(2)


核心类介绍

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

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

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

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

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

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

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

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

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

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

首先需要实现实时音视频的房间事件监听器 QNRoomEventListener,其需要实现的方法很多,以下只展现这次简单示例需要用到的方法,完整的接口说明在这里(https://developer.qiniu.com/rtn/sdk/4387/qnroomeventlistener)

publicclassHelloArActivityextendsAppCompatActivityimplementsGLSurfaceView.Renderer,QNRoomEventListener{

privatebooleanmPublished =false;// 标识本地是否发布成功

...

@Override

publicvoidonJoinedRoom(){

mRTCManager.publish();// 加入房间成功后,尝试发布

}

@Override

publicvoidonLocalPublished(){

mPublished =true;// 发布成功后,标识为 true

}

...

}

在onCreate方法尾部初始化实时音视频通话环境并加入指定房间,其中关于 Room Token 获取的方式可以参考这里(https://developer.qiniu.com/rtn/sdk/4538/server-api-reference#5)

protectedvoidonCreate(Bundle savedInstanceState){

...

QNRTCSetting setting =newQNRTCSetting();

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 个相应的方法,意义分别在注释中被描述:

publicclassHelloArActivityextendsAppCompatActivityimplementsGLSurfaceView.Renderer,QNRoomEventListener{

/**

* 显示 Surface 创建完成时回调

**/

publicvoidonSurfaceCreated(GL10 gl, EGLConfig config){

}

...

/**

* 显示 Surface 尺寸大小改变时回调

**/

publicvoidonSurfaceChanged(GL10 gl,intwidth,intheight){

}

...

/**

* 显示 Surface 创建完成时回调

**/

publicvoidonDrawFrame(GL10 gl){

}

}

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

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

surfaceView = findViewById(R.id.surfaceview);// 从布局 xml 中解析 GLSurfaceView

...

surfaceView.setRenderer(this);// 设置 Renderer


创建 Session

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

protectedvoidonResume(){

session =newSession(/* context= */this);// AR 系统初始化

...

session.resume();// 开始 AR 会话,尝试开启摄像头,如摄像头被占用,会抛出 CameraNotAvailableException 异常

}


使用 OpenGL Shader 在显示 Surface 上

绘制 AR 增强画面

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

原始摄像头预览数据

检测到的平面数组

检测到的点云数组

平面触摸事件

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

// 绘制背景

privatefinalBackgroundRenderer backgroundRenderer =newBackgroundRenderer();

// 绘制物体

privatefinalObjectRenderer virtualObject =newObjectRenderer();

// 绘制物体阴影

privatefinalObjectRenderer virtualObjectShadow =newObjectRenderer();

// 绘制平面

privatefinalPlaneRenderer planeRenderer =newPlaneRenderer();

// 绘制云点

privatefinalPointCloudRenderer pointCloudRenderer =newPointCloudRenderer();

publicvoidonDrawFrame(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 内容数据读取出来,进行必要的格式转换,接着发布出去:

publicvoidonDrawFrame(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 技术会为实时音视频通话带来全新的体验。


免费时长额度赠送活动

七牛实时音视频云从 10 月 30 日 起,实行每月免费时长额度赠送活动。纯音频、标清、高清、超清 4 档位分别赠送 5000 分钟,如果完全使用,折算总消费金额共 770 元。

推荐阅读

从零到一,使用实时音视频 SDK 一起开发一款 Zoom 吧

一人一天,如何开发一个抖音级的短视频?

七牛云徐晶:基于 WebRTC 架构的直播课堂实践

七牛云 RTN:基于 WebRTC 零基础搭建实时音视频平台

千亿级数量下日志分析系统的技术架构选型



牛人说

「牛人说」专栏致力于技术人思想的发现,其中包括技术实践、技术干货、技术见解、成长心得,还有一切值得被发现的内容。我们希望集合最优秀的技术人,挖掘独到、犀利、具有时代感的声音。

投稿邮箱:[email protected]

AR+ 实时音视频通话,虚拟与现实无缝结合_第3张图片

点击「阅读原文

了解更多七牛云信息

你可能感兴趣的:(AR+ 实时音视频通话,虚拟与现实无缝结合)