本文内容
在本文中我将介绍如何将Vuforia的视频共享给Agora系统,利用声网提供的免费平台将实时视频内容共享出去。这次的案例中涉及两个技术点,一个是Vuforia的视频接口获取,一个是Agora系统以外部视频源的方式进行实时视频的传输。同时我们也通过这个小案例来熟悉两款SDK的使用。
SDK简介
本篇文章我们将介绍两款SDK:
第一款是声网的SDK,主要功能是进行实时视音频的传输、消息传输,兼容 iOS、Android、Windows、macOS、Web、小程序、RTOS、Flutter、Electron、React Native、Unity、Unreal 等 20 大开发平台。对于注册用户,每个月均有10000分钟的免费时长,这对于普通开发者进行如那件的开发和测试已经是足够的了,并且实测在4G网络的情况下端到端延迟<400ms,开发测试也是十分良好的体验,同时还有免费的后台管理系统对应用进行监控,这个后面用到时候再细说。
第二款是Vuforia的SDK,这是一款增强现实的底层SDK,也是可以免费使用的,是以Licence授权形式授权用户使用,对于没有购买Licence的开发者在视频画面的左下角会有“Vufiria”标志,当让对于开发者来说问题不大。
开发环境
主机:windows 10
引擎:Unity 3D 2019.3.1、Visual Studio 2015
实现步骤
我们将通过如下方式进行本次项目的实现。首先Vuforia支持以注册事件的方式回调自身因为AR所独占的视频数据,而Agora本身支持独占相机资源也支持以外部视频源的方式进行直播,我们需要将这两部分结合起来。同时,做这个视频共享的目的还有一个,就是将Unity 3D渲染的3D效果也同步直播出去,这才是最根本的目的。
第一步:导入SDK
(1)打开Unity 3D,创建工程。进入Unity的官方商城,分别获取到Vuforia的开发SDK和Agora的开发SDK
顺利导入之后,简单看一下结构:将所有相关内容作为一个Package放到一个文件夹是很好的习惯,不用担心里面的Plugins,系统会自动寻找其中的插件。基于Unity平台,目前Agora支持安卓、Iphone、Mac、Win32/64,不过还没有基于Unity3D平台的Html5的插件,期待未来能有实现(毕竟比较擅长Unity,其他不太熟悉)
使用Agora要使用licence,下面看一下注册和licence申请:
注册:输入相关信息
申请licence:成功登录尽可进入项目页面,在项目页面中即可创建项目(记得实名制哦)。
水晶球:项目的详细数据分析,这个功能目前我们还用不到,后面再介绍
(2)再来简单看一下需要配合来做的Vuforia。前面介绍过了,这是一款可以给开发者免费试用(加水印)的增强现实SDK,同样支持多平台的使用。
需要注意的是,我们同样需要申请licence,地址:https://developer.vuforia.com/。
打开“0-Main”场景,在下图的左下角点击“Open Vuforia.....”即可进入到相关配置页面,即输入licence的界面。
(3)小结:熟悉了本教程所用的两种SDK及其结构、功能、注册和Licence申请,对于这两种SDK有各种技术能力,感兴趣的同学可以在官方网站多停留一会。
第二步:Vuforia的准备工作
这一步中我们将完成一个AR场景的搭建,完成Vuforia视频的获取、屏幕截屏作为后期Agora视频源的输入。
(1)搭建AR场景:打开上图中“0-Main”场景,完成licence输入,选中场景中“ImageTarget”,在右侧“Image Target Behaviour”中选中如下内置识别图
(注意:首次选择From Database 会提示导入数据,请不要拒绝^_^,其次记得电脑上查摄像头)。点击运行或者CTRL+P运行,将摄像头对准识别图(识别图在Assets/Editor/Vuforia/ImageTargetTextures/VuforiaMars_Images/)即可看到模型在图片上。
(2)编写代码:简单介绍一下,这个脚本中我们使用了Vuforia提供的注册回调机制,将自身从相机获取的视频共享出来。要注意一下这其中比较重要的像素格式,同样在Agora系统中也会有像素格式的问题。
A:透明度 R:红色 G:绿 B:蓝
ARGB_4444:每个像素占四位,即A=4,R=4,G=4,B=4,那么一个像素点占4+4+4+4=16位
ARGB_8888:每个像素占四位,即A=8,R=8,G=8,B=8,那么一个像素点占8+8+8+8=32位
RGB_565:每个像素占四位,即R=5,G=6,B=5,没有透明度,那么一个像素点占5+6+5=16位
GrayScale:像素占四位,即R=G=B=gray
如下,“TakeScreen”函数是对整个Scene中一个Camera场景进行截图,目的是获取渲染后的相机效果。
...
public class VuforiaImageShare : MonoBehaviour
{
public UnityEngine.UI.RawImage tex;
public UnityEngine.UI.RawImage screenImage;
public Camera renderCamera;
#region PRIVATE_MEMBERS
private PIXEL_FORMAT mPixelFormat = PIXEL_FORMAT.UNKNOWN_FORMAT;
private bool mFormatRegistered = false;
#endregion // PRIVATE_MEMBERS
#region MONOBEHAVIOUR_METHODS
//作为共享的图片数据
Texture2D mTexture;
Texture2D screenShot;
Rect mRect;
private RenderTexture renderTex;
//启用相机画面或者屏幕渲染画面
public bool useCam = true;
void Start()
{
//注册的图片返回格式,有多种格式可选GRAYSCALE/RGBA8888/RGB565等常见格式
#if UNITY_EDITOR
mPixelFormat = PIXEL_FORMAT.RGBA8888; // Need Grayscale for Editor 经测试,在Editor模式同样可以RGBA8888
#else
mPixelFormat = PIXEL_FORMAT.RGB888; // Use RGB888 for mobile
#endif
//注册回调
// Register Vuforia life-cycle callbacks:
VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
VuforiaARController.Instance.RegisterTrackablesUpdatedCallback(OnTrackablesUpdated);
VuforiaARController.Instance.RegisterOnPauseCallback(OnPause);
#endregion // MONOBEHAVIOUR_METHODS
// 创建一个RenderTexture对象
renderTex = new RenderTexture((int)Screen.width, (int)Screen.height, 0);
}
...
将以上脚本挂在任一场景中GameObject上,拖入对应的参数脚本运行程序,可以看到左下角为屏幕实时渲染的截图(包含渲染过的3D模型),右下角为实时获取的Vuforia实时回调图片。
(3)小结:至此我们完成了对于Agora数据的录入准备工作,包括视频原始数据和经过渲染的屏幕数据(较重要),后期在视频会议、远程协助等方面可以有比较多的应用。
第三步:Agora应用
我们在这一步将熟悉Agora的流程,跑通demo,学习外部视频源输入的代码。
(1)学习Demo场景。在如下场景中,输入按照之前步骤在agora官网创建项目获得的AppID,点击运行即可进入视频房间(是不是很简单(*^▽^*))。
下面简单介绍几个重要函数:打开脚本“TestHelloUnityVideo”这里面的“loadEngine”即为Agora引擎重要的初始化步骤。
...
public void loadEngine(string appId)
{
// start sdk
Debug.Log("initializeEngine");
if (mRtcEngine != null)
{
Debug.Log("Engine exists. Please unload it first!");
return;
}
// init engine
mRtcEngine = IRtcEngine.GetEngine(appId);
// enable log
mRtcEngine.SetLogFilter(LOG_FILTER.DEBUG | LOG_FILTER.INFO | LOG_FILTER.WARNING | LOG_FILTER.ERROR | LOG_FILTER.CRITICAL);
}
...
下面的“join”函数,为用户加入房间以及各种回调函数的设计:
...
public void join(string channel)
{
Debug.Log("calling join (channel = " + channel + ")");
if (mRtcEngine == null)
return;
// set callbacks (optional)
mRtcEngine.OnJoinChannelSuccess = onJoinChannelSuccess;
mRtcEngine.OnUserJoined = onUserJoined;
mRtcEngine.OnUserOffline = onUserOffline;
// enable video
mRtcEngine.EnableVideo();
// allow camera output callback
mRtcEngine.EnableVideoObserver();
// join channel
mRtcEngine.JoinChannel(channel, null, 0);
}
...
接下来的“leave”函数,切记在程序退出时记得关闭,不然可能会导致一些bug。
...
public void leave()
{
Debug.Log("calling leave");
if (mRtcEngine == null)
return;
// leave channel
mRtcEngine.LeaveChannel();
// deregister video frame observers in native-c code
mRtcEngine.DisableVideoObserver();
}
...
(2)接下来,我们要完成Agora系统的外置视频源输入,有以下内容:
(a)设置Agora的SDK为外置视频源模式,在“join”函数中, mRtcEngine.SetExternalVideoSource(true, false);
请确保你是在调用pushExternalVideoFrame前已调用 setExternalVideoSource, 并将参数 pushMode 设为 true ,不然调用本方法后会一直报错。
(b)添加外部视频源推送函数,需要注意的是:
VIDEO_PIXEL_FORMAT.VIDEO_PIXEL_RGBA;目前已经支持多种视频格式,在unity中不必讲RGBA再转换成BGRA(赞~)
externalVideoFrame.cropLeft;等四个位置,这里是做视频的裁剪
externalVideoFrame.rotation = 0;这里在移动端具有重要作用,作为视频的旋转设置
(c)依据第二步我们所获得的视频图片数据源(两种哈),形成完整的Agroa外置视频源系统代码(详细代码可在工程中查看):
这一步我们将两个系统进行融合,下图是简单场景编写,详细内容会在附件连接中提供下载。下图为Agroa的AR识别场景,在开启后将可以看到AR场景并开启外部视频源的数据推送。
在此之前,我们需要将Agroa例程中的“SceneHome”输出为exe可运行程序(请记得licence和BuildSetting添加场景)。
导出后,请先运行编辑器中的AR场景,因为要抢占开发电脑的摄像头(agroa默认取第一个摄像头),创建好系统场景;
之后开启事先导出的Agroa的例程场景,输入频道号“Agora”即可,分别看一下只传输视频和传输AR视频的效果
下面是切换了AR渲染后的效果,可以明显看到在右侧客户端画面中,出现了渲染过的3D人物。
待解决的问题
(1)通过传送渲染过的相机,对计算能力的要求,目前本机I7 9700k,1050TI显卡,编辑器内可以达到60帧,是否有更高效的方法?
(2)仔细观察会发现,左侧屏幕中,Vuforia回调的视频画面是上下反转的,而传到左侧,又反转了一次;是什么问题该如何处理;
(3)仔细观察会发现,右侧原始画面在左侧展示时候,虽然压缩了但是明显的也被裁减了,这是为什么呢?
相关资源
论坛:
Agora开发者中心:https://docs.agora.io/cn
AgoraGit仓库:https://github.com/AgoraIO
本次源代码:
链接:https://pan.baidu.com/s/1DIQNFTrSUHsARhRH_KchNQ
提取码:n8ne