AR+ 实时音视频通话,×××无缝结合

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

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

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

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

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

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

以下为效果动图

准备工作0: 集成七牛 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 文件到 hello_ar_java 工程中

  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 文件,在 dependencies 中增加行 implementation fileTree(include: [‘*.jar‘], dir: ‘libs‘)
    • 为了能进行实时通话,需要设置程序使用网络的权限,打开 AndroidManifest.xml 文件,在 manifest 标签中增加以下使用权限声明
      • <uses-permission android:name="android.permission.INTERNET"/>
      • <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 系统检测到的点云)

准备工作1: 建立基本的实时音视频通话环境

首先需要实现实时音视频的房间事件监听器 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 加入指定房间
}

准备工作2: 建立基本的 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 技术与实时音视频通信的结合会带来更多的应用场景。

原文地址:http://blog.51cto.com/7741292/2317763

时间: 2024-10-30 15:12:59

AR+ 实时音视频通话,×××无缝结合的相关文章

如何优化传输机制来实现实时音视频的超低延迟?

1.前言 要在语音视频 SDK 中实现超低延迟,实时的语音视频传输机制是必不可少的,而 FEC 和 ARQ 的智能结合是实时语音视频传输机制的基石. 在语音社交.视频社交.游戏语音和互动直播等领域,关于在语音视频实时传输中实现低延迟这个议题,已经有不少的文章提出各种方案.绝大部分方案的思路都是"优化",比如说,优化编码.推流.传输和播放等各个环节. 愚以为,要在实时语音视频传输中获得超低延迟,是不能单靠挖空心思去"优化"的,而是要依靠实时的传输机制.就像高铁和火车有

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

zoom(zoom.us) 是一款受到广泛使用的在线会议软件.相信各位一定在办公.会议.聊天等各种场景下体验或者使用过,作为一款成熟的商业软件,zoom 提供了稳定的实时音视频通话质量,以及白板.聊天.屏幕共享.PPT放映等常用功能.但是在当今浏览器成为端上主流的时代,实时音视频又怎甘于落后呢?相比于需要安装包的 Zoom,直接在网页上开发一款类似的会议软件肯定会受到更多的关注.当需要开会的时候,直接通过一个链接,大家就可以接入并开始会议了.现在,使用七牛实时音视频的 Web SDK,我们可以将

实时音视频互动系列(下):基于 WebRTC 技术的实战解析

在 WebRTC 项目中,又拍云团队做到了覆盖系统全局,保证项目进程流畅.这牵涉到主要三大块技术点: 网络端.服务端的开发和传输算法 WebRTC 协议中牵扯到服务端的应用协议和信令服务 客户端iOS.安卓 H.264 编解码技术 △ WebRTC 技术点 实时音视频互动必须遵守三大点 必须基于 UDP 协议,否则不要谈实时 因为 TCP 协议的重传机制(传输保障)会导致累积延迟问题,用 UDP 协议没有传输保障机制,但需要自行完善丢包容错逻辑. 又拍云音视频互动方案是基于UDP 协议,使用 T

实时音视频互动系列(上):又拍云UTUN网络详解

如何定义实时音视频互动, 延迟 400ms 内才能无异步感 实时音视频互动如果存在1秒左右的延时会给交流者带来异步感,必须将视频播放延迟限制在400ms以内,才能给用户较好的交互体验. 当延迟控制在400ms以内时,两个人音视频互动是实时的,不会有异步感存在,即实时音视频互动. 实时音视频互动产生延迟的原因 音视频互动的延迟是如何产生的? 我们先假设这样一个场景:位于北京的A客户端与位于广州的B客户端进行实时音视频互动. 该场景会有以下几个产生延迟的原因: 光的传输耗时 30ms: 网络处理耗时

Android端实时音视频开发指南

简介 yun2win-sdk-Android提供Android端实时音视频完整解决方案,方便客户快速集成实时音视频功能. SDK 提供的能力如下: 发起 加入 AVClient Channel AVMember yun2win官网:www.yun2win.com SDK下载地址:http://www.yun2win.com/h-col-107.html 开发准备 注册并创建应用 到 github下载yun2winSDK及demo 下载源码详解 app为主体显示Module uikit为公共服务M

web端实时音视频功能开发指南

yun2win官网:www.yun2win.com SDK下载地址:http://www.yun2win.com/h-col-107.html 简介 yun2win-sdk-web提供web端实时音视频功能完整解决方案,方便客户快速集成音视频功能. SDK 提供整套解决方案 yun2win官网:www.yun2win.com SDK下载地址:http://www.yun2win.com/h-col-107.html 开发准备 1.准备Chrome浏览器版本49及以上 2.给网站配置CA证书 3.

iOS端im实时音视频功能快速开发实操指导!

所需工具yun2win实时音视频IOS端sdk 下载地址:https://github.com/yun2win/yun2win-sdk-iOS/tree/master/Y2W_IM_SDK yun2win官网:www.yun2win.com 简介 Y2W_RTC_SDK集成多种实时通讯能力: 实时音频 实时视频 屏幕共享 协作白板 开发流程 发起方使用Y2WRTCManager对象的createChannel方法创建Y2WRTCChannel对象 接收方使用Y2WRTCManager对象的get

实时音视频技术难点及解决方案

对于一个实时互动的音视频系统而言,存在很多技术难点,有几个比较重要的点: 首先是低延迟,如果要满足比较流畅地进行实时互动,那么单向的端到端的迟延大概要在400毫秒以下才能保证流畅沟通; 第二点就是流畅性,你也很难想象在视频过程中频繁卡顿会有良好的互动; 第三点是回声消除,回声的产生是扬声器播放的声音经过环境反射被麦克风重新采集并传输给对方,这样对方就会一直听到自己的回声,整个互动过程会非常难受; 第四点是国内外互通,随着现在国内同质化产品越来越多,国内的竞争也异常激烈,很多厂商纷纷选择出海,这时

摸索在web端使用腾讯云的实时音视频

今天接到一个新任务,要在web端集成,实时音频/视频,选择了腾讯云的服务: 腾讯云实时 音视频 文档地址:https://cloud.tencent.com/document/product/647/17021 点击web下的下载按钮会弹出一个网页可以在web端体验 实时 音视频 的demo demo地址:https://trtc-1252463788.file.myqcloud.com/web/demo/official-demo/index.html?_ga=1.256196107.1236