声网Agora

声网Agora 查看完整档案

上海编辑  |  填写毕业院校  |  填写所在公司/组织 github.com/AgoraIO 编辑
编辑

声网 Agora,为开发者提供最易用、可靠的实时音视频互动技术。一套 API,可快速实现音视频通话、聊天室、在线课堂及更多实时互动场景。https://www.agora.io/cn/

个人动态

声网Agora 发布了文章 · 4月9日

2021 技术展望 | 弱网下的极限实时视频通信

线上会议、在线教育、电商直播等多个场景的兴起,也使得实时互动技术从幕后走到台前,得到了更多人的关注。编解码、网络传输、计算机视觉等 RTE 相关的一系列技术也正焕发出更强的生命力。2021 年,在深度学习、5G 等技术的加持下,RTE 会进一步催生哪些可能?声网Agora 开发者社区联合 InfoQ 共同策划,邀请了声网Agora 开发者社区中的多位技术专家,从视频传输、计算机视觉、编解码标准发展、WebRTC、机器学习、音频技术等角度,共同撰写「2021 实时互动技术展望系列」,一窥技术新趋势。本文作者,南京大学陈浩、马展、刘浩杰。本系列内容由声网 Agora 开发者社区 与 InfoQ 联合策划,并由 InfoQ 审校,首发于 InfoQ。

实时视频通信已然成为当前互联网应用的亮点。特别在这疫情期间,全球都在“被隔离”,无法开展线下活动,更加迫切的需要以实时视频通信为技术支撑的各种虚拟线上交流。在可见的数年内,稳定高质量的互联网实时视频通信是各行各业的迫切需求,协同复工复产,帮助经济恢复;当用户习惯逐渐养成,实时视频通信又将成为生产生活的基本配置。

从应用的角度看,用户对服务的需求和网络基础设施永远是一对不可调和的矛盾。以实时视频通信为例,我们永远无法保证网络的全时稳定,弱网环境长期存在,特别在很多关乎到生活、生产乃至生命的关键时刻,通信网络往往受到极大的物理条件限制,如海事作业、应急救灾、高并发场景等。因此我们更加需要探索新理论新方法来有效的分析、精准的建模、准确的预判,以期实现弱网极限环境下(如极低带宽 <50kbps, 极不稳定网络抖动,极大时延等)的高质量实时视频通信。

过去的 5 年,我们南京大学电子学院团队在实时视频通信下做了一系列的探索工作,搭建了以互联网云游戏/云 VR 为应用的实时视频通信平台(https://www.anygame.info/) ,嵌入人工智能(AI)方法驱动自适应网络带宽调节和端到端用户体验优化。目前,该平台依然每天支持数百上千名用户实时操作,也帮助我们持续优化和更新,覆盖更多的应用场景。

近期乃至未来,我们认为实时视频通信的核心问题还未得到解决,特别是弱网下的高质量保证,而这些 corner case 往往是服务水平的直观体现。面对弱网的各种限制,我们提出极限实时视频通信:

第一次尝试实现全链路 AI 控制(包括编码和传输)

从 AlphaGo 开始,强化学习在任务决策方面展现了非凡的能力;三年前,我们提出基于强化学习的网络流控,自适应侦测调节带宽反馈给发送方优化视频压缩;这样的过程虽然带来了可见的效果,但是并没有真的解决网络流控和视频压缩流控的核心矛盾;网络流控的难点在于异构性,视频压缩的流控难点是内容多样性。近期,我们将强化学习的决策机制同时涵盖编码和传输,全链路 AI 控制(状态采集,决策预判),实现更加精准的带宽控制;

基于 IP 的分组交换网络在视频传输网络中占据主导地位,使得端到端网络的吞吐量、延迟等状态具有很高的时变性,并且在不同的用户之间由于网络资源竞争使得这些网络状态随时间动态波动。另一方面,由于实时视频通信要求的苛刻时延和视频内容复杂度差异,难以实现良好的码率控制。这使得难以通过对网路和内容建模生成统一、固定规则的码率自适应算法。

受人类行为决策思想启发,我们引入强化学习理论和工具,综合考虑视频编码与网络传输端到端流程,提出了基于强化学习的全链路网络流控,其系统框图如图 1 所示。智能体首先观察以往实时视频通信会话的经验,即从视频编码器和接收端收集的编码状态、网络和播放状态,使用神经网络挖掘编码和传输过程中视频内容和网络的潜在特征,并做出编码参数设置的决策。视频应用程序的发送端基于该决策编码和传输视频,在接收端进行解码播放后,产生新的状态,同时向智能体反馈当前决策的奖励。基于此奖励信号,智能体以最大化累积奖励为目标不断更新神经网络参数。最终,我们仅通过观察和学习编码、网络和播放的原始状态,对视频编码参数进行自适应调整,有效对抗网络波动的同时,有效提升用户体验质量(Quality of Experience, QoE)。

image.png

图 1 基于强化学习的全链路网络流控示意图

为评估基于强化学习的全链路网络流控的性能,我们选取当前先进的谷歌拥塞控制(Google Congestion Control,GCC)和瓶颈带宽与往返时延(Bottleneck Bandwidth and Round-trip time,BBR)算法进行了对比实验,结果如图 2 所示。可以看出,相对于 GCC 和 BBR 算法,我们可以提升分别 3.6%和 27.9%的归一化平均 QoE 分数。其中,我们以所有测试样本取得 QoE 的最小值与最大值进行归一化处理。

image.png

图 2 基于强化学习的全链路网络流控性能评估

引入网络多模态感知进行在线建模和推理

用户很难预判网络的好坏。网络的异构性让这个问题变得极为艰难。从医疗大样本数据分析推理得到启发,我们引入网络多模态感知,梳理网络的不同规则,应用在线建模逐步完善,覆盖各种网络情况。针对不同的网络情况应用对应的网络模型实现大幅性能提升;

对于实时视频通信场景,用于承载视频流的接入网络除了时变特性以外,还往往具备高度的异构性,如蜂窝链路(3G/4G/5G)、WiFi 无线链路、光纤链路等形态,这些接入网络具有不同的带宽、延迟和缓冲容量。此外,用户使用网络的环境也复杂多样,包括静止、步行、乘汽车、乘高铁等使用环境,使得带宽、延迟等网络特性动态改变,网络波动频繁。单一学习模型的性能往往难以覆盖如此复杂、异构的网络环境。

为此,我们引入了网络多模态感知进行在线建模和推理,其系统框图如图 3 所示。发送端经过视频获取、视频编码和视频流化等处理后将视频流发送到网络上,接收端接收视频数据进行解码和播放等操作,并收集网络状况和视频播放情况相关数据。为减小码率决策时延,我们将网路模态感知、码率自适应和在线建模与推理模块部署在接收端。首先,通过分析和挖掘历史网络状态特征,识别当前网络模态,初步感知整体网络质量情况。之后,使用基于强化学习理论的多模态码率自适应,依据网络模态动态切换码率自适应模型,从而针对不同网络状况精细化生成不同的码率自适应决策算法。在实际新网络环境下,基于多模态码率自适应模型应用在线建模和推理,进一步面向当前环境更新和优化模型和算法,解决新环境下模型性能退化问题。一次码率决策完成后,接收到通知和指导发送端的视频编码和视频流化模块对编码码率和发送码率进行调整,以抵抗动态网络波动。

image.png

图 3 网络多模态感知进行在线建模和推理系统框图

鉴于图 2 中 BBR 性能差于 GCC,我们选取 GCC 算法作为评估网络多模态感知进行在线建模和推理性能的对比对象,结果如图 4 所示。对比于 GCC 算法,多模态码率自适应模型可以提升 9.1%归一化平均 QoE。其中,我们以测试样本取得 QoE 的最小值与最大值进行归一化处理。在线建模与推理方法相对于 GCC 算法,能够提升约 15.1%归一化平均 QoE,并且在训练时也达到相对稳定和可接受的码率自适应性能。

image.png

图 4 网络多模态感知进行在线建模和推理性能评估

强化网络主动决策

在网络状态变差的时候,视频传输总会丢包;目前策略是 FEC 或者重传。无论哪一种方式都让网络更拥塞。从另外一个角度看,视频内容具备很强时空一致性(Spatiotemporal Coherency);因此,与其进行保护,不如直接有选择的丢弃,后期利用时空一致性进行补偿。

为此,我们引入了智能时空预测补偿模块,通过联合多帧视频时空相关一致性来在解码端直接重建丢弃的视频帧,其系统框图如图 5 所示。接收端经过视频解码得到一系列时空相关的视频解码帧,这些视频帧在编码端编码过程中已通过有选择的丢弃,来确保已存在的视频解码帧有很强的时空一致性来对丢弃帧进行恢复。智能时空预测补偿模型能根据输入的解码视频帧构造一个非线性的二阶预测模型,该模型利用了物理概念对运动进行二阶建模,结合非线性的神经网络模型更好地预测丢失视频帧。模型可基于接收到的视频解码帧,有选择地采用直接法和引导法,对不同运动特性和场景的视频进行分区域多重运动补偿,重建丢失的视频帧。此外,为了获得极高的视觉流畅度,我们在重建过程中引入了时空一致性的约束,使得重建的视频序列得到极高的视频时空流畅度,基本上在视觉感知不变的情况下,通过主动丢包可以大幅降低网络压力,保证流畅服务。

image.png

图 5 智能时空预测补偿模块

通过上述三个方面的创新,我们实现了 50kbps 下的高质量视频实时通信。

作者介绍:

马展,教授,南京大学, mazhan@nju.edu.cn

刘浩杰,博士生,南京大学, haojie@smail.nju.edu.cn

陈浩,副研究员,南京大学, chenhao1210@nju.edu.cn

点击了解更多实时互动信息~

查看原文

赞 0 收藏 0 评论 0

声网Agora 发布了文章 · 4月9日

2021 技术展望 | 走向未来的实时生成技术

线上会议、在线教育、电商直播等多个场景的兴起,也使得实时互动技术从幕后走到台前,得到了更多人的关注。编解码、网络传输、计算机视觉等 RTE 相关的一系列技术也正焕发出更强的生命力。2021 年,在深度学习、5G 等技术的加持下,RTE 会进一步催生哪些可能?声网Agora 开发者社区联合 InfoQ 共同策划,邀请了声网Agora 开发者社区中的多位技术专家,从视频传输、计算机视觉、编解码标准发展、WebRTC、机器学习、音频技术等角度,共同撰写「2021 实时互动技术展望系列」,一窥技术新趋势。本文作者,宋利,上海交通大学教授,声网Agora 开发者社区 MVP。本文首发于 InfoQ,由声网 Agora 开发者社区 与 InfoQ 联合策划,并由 InfoQ 审校。

疫情爆发至今一年多的时间里,很多行业在疫情期间都备受打击,然而也有一些行业“因祸得福”,快速增长,包括在线教育、在线诊疗、在家办公、在线买菜、在线直播等。这些在线业务行业,均要大量应用音视频直播技术,在音视频直播技术的背后有两项关键技术在支撑:实时通信技术(Real-time Communication)与实时渲染技术(Real-time Rendering)。目前二者正在与实时生成技术相结合,为我们带来更好的实时沟通体验。

RTC 技术与实时渲染技术

RTC(Real-time Communications),实时通信,是一个正在兴起的风口行业,其强调“实时”即 Real-time,延迟在毫秒级别,支持强互动,最典型的应用就是直播连麦和实时音视频通信。

提到直播,还有一个重要的技术叫做 CDN:内容分发网络,简单地说就是将网站/应用的图片、音频、视频等素材提前传输到距离用户更近的 CDN 节点上(在物理层面就是电信机房里的服务器),当用户访问时就可以就近快速下载、减少等待。现在有一些平台通过 CDN 来实现直播,然而 CDN 的技术机制理论上会有 5-10 秒的延迟,在浏览图片、短视频等素材来说用户感知不明显,对于不需要实时强互动的直播,比如体育赛事网络直播、演唱会网络直播、新闻现场直播,延迟在 5-10 秒之间则是可以接受的。

而像前文提到的办公、教育、社交、医疗、娱乐这些直播应该对互动有非常高的要求,5-10 秒的延迟是无法忍受的,一方面画面会存在延时、卡顿、模糊、杂音、回声等常见问题;另一方面,实时互动根本没法用,游戏或直播中的连麦,远程医疗医患对话,直播小班课老师学生间的答疑,需要讨论的视频会议……理论上都要做到跟移动电话一样低延时、高接通和强互动,否则不只是体验不行,而是没法用。正是因为此,视频会议、社交直播、小班课、游戏开黑等互动要求高的场景,RTC 技术基本上已成为唯一选择。国内的 RTC 服务供应商包括声网、腾讯云、阿里云等。

RTC 技术比较复杂,不只是需要专门的网络节点,同时对网络架构、通信协议、软件算法和应用机构都有特殊要求。一个完整的实时音视频系统包括以下几个部分:

image.png

此外 RTC 对数据传输的及时性的要求通常要高于可靠性的要求。如发送端采集的一帧编码数据丢失了,对于接收播放端可能并没有太大的影响,接收播放端可以利用收到的前面和后面的帧,通过补帧等技术,实现同样好的用户体验,再如一帧音频数据丢失了,接收端可以用 NetEQ 等技术,根据收到的前面和后面的数据,用算法填上这一帧的数据,而不会降低用户体验。

实时渲染(Real-time Rendering)主要用于实时图像生成与分析处理,负责渲染直播画面、直播特效等等,如美颜、动画表情互动、礼物特效,提供更加个性化、人性化的使用体验。实时渲染关注的是交互性和实时性,一般制作的场景需要进行优化以提高画面计算速度并减少延时。

实时渲染技术随着计算机图形学的发展在持续进步。2000 年之后,3D 图像渲染 GPU 已经成为台式机标配,CGI 开始无处不在,预渲染的图形在科学上几乎是真实照片级的。这时期的工作主要集中在集成更复杂的多阶段的图像生成。纹理映射也已经发展为一个复杂的多阶段过程,使用着色器(shader)将纹理渲染、反射技术等多种算法集成到一个渲染引擎中的操作并不少见。2009 年电影《阿凡达》运用动作捕捉技术为角色生成动画,能够将动画直接叠加到实时拍摄的图像上,真正实现了高质量的实时渲染。软件方面 OpenGL 也开始成熟。不久前英伟达发布的 DLSS 2.0(Deep learning super sampling),根据官方宣传,可以保证渲染程序在较低分辨率下对游戏画面进行实时光线追踪,而 DLSS 2.0 则会将渲染后的画面进行 4 倍超采样,从而保证细节与帧率的兼顾,标志着实时渲染技术有了新的突破。

实时生成技术进展

近年来,随着互联网的迅猛发展和智能移动设备快速普及每时每刻都有大量的图像被生产、编辑和传播,越来多任务需要算法具备成图像生成能力,现有的直播渲染技术已经不能满足观众需求,实时生成画面+实时传输通信是未来趋势。与此同时,深度学习在语音识别、自然语言处理计算机视觉等许多领域都取得了巨大的成功,由层叠神经元组计算模型——深度神经网络,拥有比传统算法更加强大的特征提取及表示能力。因此人们开始研究其在生成模型上的应用。深度模型通过训练样本去估计数据集的概率分布,接着便可以利用这个生成新的数据或者操纵原有的数据。

基于生成对抗网络 GAN(Generative Adversarial Networks, GANs)图像生成研究目前收到了广泛关注。GAN 是由 Goodfellow 等人在 2014 年提出。这个深度生成模型背后的思想是博弈论,训练的过程可以被视作二元零和博弈。GAN 包含两个组成部分,生成器(generator)和判别器(discriminator),两者均由多层感知机组成。在训练过程中,生成器 G 旨在生成尽可能逼真的图像数据去骗过判别器 D,而判别器则努力去分辨真实的样本和生成器输出的假样本。可以证明,该对抗训练过程最终将收敛到理论上的唯一解,在这种情况下,生成器生成的数据和真实数据将无法区分。训练完成后,生成器便可以从噪声中随机采样,生成训练数据集中不存在的新本。相比于传统模型例如玻尔兹曼机,GAN 不再需要复杂的马尔科夫链,只使用反向传播即可。同时大量实验 表明,GAN 可以生成更加锐利、逼真的图像,因此其在图像生成领域得到了广泛的应用。

近期一些 GAN 领域的工作实现了实时的图像生成功能,如实时的人脸驱动。Siarohin 等人提出了一阶运动模型,包含关键点检测器、密集运动场估计网络和运动迁移网络。关键点检测器通过无监督的训练,对源图像和目标图像分别提取关键点,接着密集运动场估计网络利用两幅图像的关键点信息估计出稀疏间运动信息,接着根据局部仿射变换去估计出密集的运动场,最后迁移网络接受目标图像作为输入,将编码器的特征基于此前得到的运动场进行扭曲,再送入解码器,获最后重现图像。这种方法实现的实时人脸驱动效果如下。

image.gif

还有一些插件借助相似的方法,可以在 ZOOM 视频会议中实现实时换脸。下图 ZOOM 会议中的马斯克并非马斯克本人,而是换脸得到的。

image.gif

近期,NVIDIA 推出一款 Cloud-AI 视频流平台——Maxine,它可以在视频通话中,提供高清画质、噪音消除、目光校正,以及实时转录、翻译等功能,并且支持电脑、平板、手机等多种类型的设备,用于解决当前视频通话存在的各种问题。Maxine 增加了消除伪影的功能,可以使得画面更清晰,能过滤掉常见的背景噪音,如敲击键盘、主机运行的嗡嗡声、家里吸尘器的声音,还提供了实时翻译、转录字幕的功能。最重要的是借助视频压缩技术,可以有效减少数据传输的带宽。Maxine 通过把带宽问题变成计算问题,可以将传输所需带宽减少到 H.264 视频压缩标准所需带宽的十分之一,极大地增加视频的流畅度。Maxine 采用的 AI 视频压缩技术的核心在于它不是对整个屏幕的像素进行流式处理,而是分析通话中每个人的面部关键点,然后在另一端的视频中重新设置人脸的动画,如此一来便可以大幅降低的数据的传输量,同时还可以保证视频传输的质量。在面对面互动体验方面,Maxine 还增加了动画头像交互和虚拟助手功能。动画头像交互允许视频通话者根据喜好选择动画虚拟头像 ,这些头像虽不是真实的,但可以通过交互者的声音和情绪基调自动驱动。

image.png

image.png

FaceBook 也使用深度生成模型以极小的带宽(小于 10kbits/s)提取并传输人脸特征点,然后在用户接收端设备上自动重建人脸,进而实现视频通话。他们设计的网络大小仅仅为 3MB,可以在 iPhone8 上运行。

image.png

RT2C

实时通信未来的发展趋势是与实时生成相结合,实现实时创作与连接(RT2C,Real-time Creation and Connection),其中创作部分包括生成和渲染,连接部分包括传输通信与社交网络。这将极大拓展媒体传播场景,提供更高品质的内容,让媒体制作更加便捷和多样化,提供更新颖、更人性化的观看效果和使用体验,更加吸引观众,拓展市场。一个典型应用是虚实结合的自由视角直播技术。

自由视角直播是指用户应该能够自由地选择观看直播的视角。传统的直播只为观众提供固定的一个视角,用户只能随着导播镜头被动地去观看。现有的一些多链路直播也只是事先在场景周围固定几个摄像机,然后提供这几个摄像机的观看视角,不是真正的“自由视角”。自由视角直播是让用户可以平滑无缝、自由地选择观看角度,通过遥控器或者手势滑动视窗,充分避免遮挡影响,实现 720°的无缝观看,不错过每一个精彩细节。同时提供一些上帝视角俯视全场,便于观众随时了解全场整体态势,也提供一些运动员或演员的跟踪视角、放大视角,让观众能随时跟踪自己喜欢的运动员或演员的表现。让观众仿佛在现场自由穿梭,随意欣赏表演或比赛,关注自己最在意的细节。使得人对真实世界的视觉感知同时具备了沉浸感、立体感、空间感,还解决了一般的立体视频内容不丰富、交互不自然的问题。与此同时还可以进行 AR 场景增强,在直播的视频流中渲染入一些现场并不存在的特效景象,让电视前的观众有亦真亦幻的视觉感受。比如在大型表演直播中添加虚拟的人物、景象或动态效果,与真实的演员进行互动;在比赛现场的场间休息中渲染一些大型的吉祥物投影或者啦啦队表演。

自由视角生成首先需要做摄像机自动定标,这方面已经有很多研究。视角生成领域相关技术大致可以分为三种:基于模型的绘制、基于图像的绘制和基于景深图像的绘制。基于模型的绘制主要指通过对场景进行三维建模,在获取场景纹理信息后,使用计算机图形学方法做旋转平移得到新视角图像。基于图像的绘制主要指直接利用参考图像来生成新视角,离散采样然后通过插值合成新视角的图像。基于景深的绘制在图像上加入了场景深度,用于辅助绘制新视角的图像。其中基于景深的绘制是比较流行的方法。通过这些方法可以实现自由视角和上帝视角的生成。而跟踪视角的生成需要借助视频检测与追踪技术,从不同摄像机中识别和检测人物,并且保证任何时刻都至少有一台摄像机能跟踪到观众选择跟踪的人物。视频追踪方面目前已经有很多成熟的方法可以用,包括一些搭建 RNN 网络来进行的追踪的研究,通过学习新的距离度量方法来进行滤波的限制玻尔兹曼机进行的追踪研究等等。下图展示了一种自由视角生成的解决方案。

image.png

神经渲染也是获取新视角的重要方法。有些神经渲染方法会在图像融合阶段用一个神经网络来学习输入参考视角之间的一个混合权重,好处是可以更充分学习对每一个输入视角。有些神经渲染方法不仅学习输入参考视角的混合权重,还要学习场景本身的几何结构、表面材质等属性,并且在一个可微的图形学渲染器中生成出新的视角。还有些神经渲染方法学习一个体素网格模型,用一个固定分辨率的体素网格来记录和更新从输入学到的特征,后续再通过一个渲染网络生成新视角。近年提出的神经渲染方法 NeRF,直接从空间位置和视角(5 维输入)映射到颜色和不透明度(4 维输出)来进行体渲染,首先构建一个场景的稀疏模型,然后对系数模型中的采样点进行积分,用神经网络学习采样点与虚拟视角之间的关系,在静态场景上取得了很好的效果,如下图所示:

image.png

然而 NeRF 只能处理静态场景,并且需要大量时间和数据去训练模型。NeRF 的改进方法 Deformable NeRF 可以处理动态场景的神经渲染方法,而且可以在手机端运行,效果如下图所示:

image.png

AR 场景增强的相关技术已经在大型晚会中得到了较多的应用。一般来讲,需要事先在线下构建好虚拟模型及其动态效果,对场地构建 3D 模型和坐标,进行三维注册,在直播时将模型和动态效果渲染入视频流,嵌入场地的特定位置,然后呈现出来。现在对于大型场景的建模可以借助激光雷达完成。由于计算量巨大,需要借助边缘计算的方法,提高响应速度,降低延迟。

在传输部分,自由视角技术除了可以采用更大带宽、更低延迟的网络进行传输外,还可以采用硬件编解码、CDN 网络优化等方法进一步提高实时性。随着 5G 网络带来的增强带宽、海量连接、低延时高可靠特性,以及 VR/AR 技术的快速发展,上述技术路线正在逐渐落实。湖南电视台与华为联合制作的节目《舞蹈风暴》借助时空凝结设备,360 度立体呈现了舞者表演中的每一个旋转翻腾,用“风暴时刻”定格每一个精彩瞬间,让舞蹈之美在节目中得以具象呈现,带来了赏心悦目的视觉体验。

image.png

Intel True View 也为我们带来了良好的自由视体验。在橄榄球比赛这样激动人心的直播中,Intel True View 同样可以让电视机前的观众随意地选择自己想要的观看视角,紧盯自己最关注的细节,打破了传统直播视角固定的缺陷,增强了互动性。

总结,本文对 RTC 技术做了介绍,并简述了实时渲染技术的发展历史,然后介绍了实时图像与视频生成领域的相关研究工作与最新进展,最后提出 RTC 技术将朝着实时生成与传输 RT2C 方向发展。

点击了解更多实时互动信息~

参考资料

1.CSDN. 实时通信 RTC 技术栈之:视频编解码[EB/OL].https://blog.csdn.net/netease... 2018.10.29

2.知乎. LiveMe FE 李承均:RTC 技术的入门和实践[EB/OL].https://zhuanlan.zhihu.com/p/... 2020.08.05

3.知乎. 走过半个多世纪,计算机图形学的发展历程告诉你 5 毛钱的电影特效究竟多难[EB/OL].https://zhuanlan.zhihu.com/p/... 2020.03.31

4.Siarohin A, Lathuilière S, Tulyakov S, et al. First order motion model for image animation [C]// Conference on Neural Information Processing Systems (NeurIPS), 2019.12

5.Wang T C, Mallya A, Liu M Y. One-Shot Free-View Neural Talking-Head Synthesis for Video Conferencing[J]. arXiv preprint arXiv:2011.15126, 2020.

6.Oquab M, Stock P, Gafni O, et al. Low Bandwidth Video-Chat Compression using Deep Generative Models[J]. arXiv preprint arXiv:2012.00328, 2020.

7.Mildenhall B, Srinivasan P P, Tancik M, et al. Nerf: Representing scenes as neural radiance fields for view synthesis[J]. arXiv preprint arXiv:2003.08934, 2020.

8.Park K, Sinha U, Barron J T, et al. Deformable Neural Radiance Fields[J]. arXiv preprint arXiv:2011.12948, 2020.

9.网易号. 惊艳之举!湖南广电联手华为再掀“舞蹈风暴”[EB/OL].http://mp.163.com/article/FR1... 2020.11.09

10.Youtube. It’s called True View | Intel[EB/OL].https://www.youtube.com/watch... 2020.09.03

查看原文

赞 0 收藏 0 评论 0

声网Agora 发布了文章 · 3月10日

最近爆火的互动播客,要解决哪些技术难题?

嘿,你也听播客么?

有机构统计过,去年 1 月美国最热门的播客单月受众就超过了 2370 万人,那时疫情还未影响人们的生活。随着 RTC 技术的普及,还有人们生活方式的变化,播客也演进出了新的形态。今年 1 月,播客在 RTC 技术,以及 Elon Musk “流量”的加持下,以“互动播客”的新形态火了起来。这段时间国内外对“互动播客”场景的追捧者越来越多。

“互动播客”的创新与亮点

“互动播客”是全新的线上兴趣/话题式语聊互动场景,不论是名人/大V,还是普通网友都可以随时开启或参与一场海阔天空的互动交流,而且听众可以随时“举手”上麦参与实时互动交流。

听上去,“互动播客”跟休闲语聊房很像,其实从内容、用户关系、信息分发等方面有很多差别:

网上已经有很多人剖析过其背后的“产品成功学”了。那么从“播客”到“互动播客”背后的技术发生了哪些变化?好的音频互动体验,需要在哪些环节进行优化?

新形态播客的技术变化

一、实时互动技术赋予“内容平权”

很多人说,“互动播客”的成功很大一部分功劳在“内容平权”,也就是说任何人都可以在平台上创建播客房间发起主题讨论,或者随时加入到播客房间进行互动交流。不过,要实现“内容平权”,也需要有技术的支持。为什么这么说呢?

首先“互动播客”相对于播客,最重要的就是让主持人、嘉宾和每一位听众都可以实时互动进行语音交流,赋予听众更强的互动性与参与感。而想要连麦互动,不仅需要超低延时传输,网络框架还需支持双向传输,但 CDN 只支持单向传输,所以无法实现连麦互动。这时需要借助像声网Agora SD-RTN™ 这样覆盖全球的实时传输网络,能通过低延时的数据传输,与全球的用户进行互动。这是其背后技术中网络层面的变化。

二、Nova音频引擎,提供专业设备级优质音频体验

另一方面,传统的播客节目为了保证音质和听感,会购买专业设备,并选择合适的环境录制,以避免周围的噪声、回声。而在“互动播客”中,用户可以随时随地拿起手机在房间中与人畅谈或收听节目,不用专业设备也能有相同的音质体验。这是由于从编解码、3A 算法等一套软件算法替代了专业设备的作用,让非专业用户也能有好的音质和体验。

在编解码方面,声网在 SDK 中已经集成了针对音频实时互动优化的自研编解码器 Agora Nova™。为了能在纯语音场景下提供更好的音质体验,Nova™没有与其它语音编解码器一样采用8kHz 或 16kHz 采样率,而是使用 32kHz 采样率,可捕捉到更多语音细节。同时,经过理论推导和大量实验验证,设计了一套精简的语音高频分量编码系统,优化 Nova™的编码复杂度。在抗丢包能力的保障上,我们也在保证编码效率的前提下选择了最平衡的方案,经过实验验证,这种方案即又保证了编码压缩效率,又保证了丢包时的恢复率。在主、客观评价体系下,Agora Nova™ 的语音编码质量高于 Opus。

在3A(降噪、回声消除、自动增益)方面,声网SDK可够智能识别出各类环境,全面消除回声,并提供超一流的双讲表现。同时,声网SDK在降噪模块能精确检测出噪声信号,并动态调整降噪算法类型和参数,在不损伤语音音质的情况下,有效消除各类噪音。音频的自动增益,即使在嘈杂环境下用户也能体验优异,最大程度保证了音频质量,保证互动播客的清晰体验。

由于在互动播客场景下,用户可能会来自全球各地。那么为了保证全球用户都可获得一致的流畅体验。声网通过多维度的网络估计模型,可智能识别网络链路情况、用户网络环境,然后根据用户网络环境、设备性能、网络链路情况的自适应码率、帧率。同时配合优秀的抖动缓冲机制和抗丢包算法,可保证在80% 丢包情况下,仍能进行流畅的音频通话。

不仅如此,声网Agora通过协同调节人声的音调、音色、动态、韵律、空间效果等,实现对人声的美化,同时支持通过对人声的某一个或多个频段进行时域和空域处理,从而达到提升音质和调整人声音色的目的。

基于以上包括网络传输、编解码、降噪与回声消除、码率自适应、弱网对抗等一系列完备的技术,我们推出了“互动播客场景解决方案”。

声网互动播客场景解决方案

全球覆盖的低延时互动

互动播客场景方案的传输基于声网Agora SD-RTN™实现。SD-RTN™在全球部署节点,覆盖了 200+国家与地区,可为实时音频、视频提供“专线”级别的质量与互动体验。基于智能路由策略以及自研传输协议 Agora AUT,全球优质网络传输覆盖率超过99%。

全球一致的高音质体验

声网自研的 NOVA™ 语音引擎与业界主流编解码器相比,在相同码率下,音频采集与有效频率范围更优,可保证声音的高保真度。NOVA™ 在采样率一定的情况下,码率更小,减少对用户带宽的压力,保证用户在任意弱网条件下保持良好的音频体验。

同时,声网采用业界领先的软件3A 算法,可智能适应各类环境,在不损伤语音音质的情况下,有效消除各类噪音、回声。最大程度保证音频互动体验。

十倍弹性网络架构设计,轻松应对流量突发暴增

声网为实时传输设计的 SD-RTN™网络采用超高弹性网络架构设计,在网络架构设计上能够应对10倍以上的负荷。可以从容应对很多上市公司、大流量平台、爆款客户突发的流量暴增。

安全合规,符合全球性信息安全与隐私保护法规要求

声网Agora已满足ISO 27001、ISO 27017、ISO27018等相关标准的全部要求,并通过且获得了挪威船级社(DNV)颁发的全球范围认证。我们的网络架构和基础设施符合SOC2标准,确保所有的物理和虚拟访问都得到有效管理、监控和控制 。同时声网还聘请包括Trustwave Holdings在内的全球隐私保护及安全专家进行审核,通过了第三方隐私保护审计、以及安全专家在网络渗透、应用程序漏洞和合规性评估等多项审计测试,全面符合GDPR、CCPA、COPPA、HIPAA,以及中国数据安全法(草案),个人信息保护法(草案)等国际国内相关法规要求。

在隐私保护方面,声网完全不会访问或存储用户的任何个人身份信息(PII),只会收集提供服务中必要的运营信息——这些数据包括IP地址(识别用户的地理位置以符合区域法规和网络连接)、计量数据(因为声网是按使用时长收费的)和体验质量数据(通过水晶球帮助客户进行体验质量监测)。

在信息安全方面,声网为应用开发者提供了身份验证、数据加密以及网络地理围栏等诸多缺省和可配置的安全选项,以保护开发者的音视频媒体流数据。Agora SDK 提供内置 AES 加密算法供客户直接选择使用。加密密钥由客户的应用程序管理,并在Agora网络外部的终端用户设备之间进行传输。

声网还与多家全球备受信赖的安全组织合作,从而保障及时发现漏洞并告知客户,帮助客户快速开展必要的修复工作。

互动音频最佳实践支持

在过去 7 年间,声网服务了几千家客户,包括唱吧、口袋狼人杀、荔枝、陌陌等,积累了多种实时音视频互动场景的最佳实践,有充足的实战经验和各类预案保证。

XLA体验质量保证

2020年7月,声网基于近万亿分钟的用户体验数据及海量用户主观体验评价,定义并推出了实时互动行业首个体验质量标准XLA。如有指标没有达标,声网最高可进行100%赔付,这一承诺也展现了声网在实时互动领域的技术实力和服务质量,目前市场上还没有其他服务提供商能够针对实时音视频服务提出类似承诺保障。

不止于“快速实现”

事实上,今年 2 月我们的社区中就已经有开发者自己用 Agora Web SDK ,用 2 天的时间实现并开源了一个应用(点击这里了解更多)。他表示,在应用中,实现音频互动功能大约只用了 7 行代码。
目前比较成熟的互动播客场景的架构如下图所示。用户可以通过直播间列表或其它一级入口进入播客直播间。在直播间中,会有一个虚拟的讲台(频道),主持人与嘉宾在频道中进行对话。‘

如果将这个过程翻译为 API 调用逻辑,如下图所示:

这是我们最常见的互动播客的玩法。不过随着用户的使用,我们也看到了很多其它的玩法。而开发者完全可以基于 Agora API 中的不同参数组合,来为不同的玩法提供最佳的音质。我们来例举几个典型玩法对应的参数组合:

Elon Musk 式的典型嘉宾对谈玩法

在这种情况下,嘉宾相对固定,不会有频繁上下麦的情况。而且所有嘉宾都是语音聊天。所以我们可以将Audio Profile 设定为 Speech Standard。AudioScenariosheding 设置为 Default。这时将会默认采用 32 kHz 采样率,语音编码, 编码码率最大值为 18 Kbps。

RtcEngine.setAudioProfile(Constants.AUDIO_PROFILE_SPEECH_STANDARD, Constants.AUDIO_SCENARIO_DEFAULT)

开放式交流

可能有些人曾经看到过这样的房间:房主讲房间作为一个开放交流的地方,所有听众都可以申请上台连麦。这种情况下就会出现频繁上下麦。所以这时候,我们可以将AudioProfile 设定为 Music Standard,将AudioScenario 设置为 ChatroomEntertainment。

RtcEngine.setAudioProfile(Constants.AUDIO_PROFILE_MUSIC_STANDARD, Constants.AUDIO_SCENARIO_CHATROOM_ENTERTAINMENT)

线上演唱会

可能是想组织一场只有“歌舞节目”的晚会,在春节期间,有用户开始组织朋友在互动播客中办起了线上演唱会。为了保证音质,我们需要音乐编码的支持。这时我们可以将 AudioProfile 设定为 MusicHighQuality,以提供高音质支持;将AudioScenario 设置为 GameStreaming,以保证在高音质下仍能提供较好的实时互动体验。

RtcEngine.setAudioProfile(Constants.AUDIO_PROFILE_MUSIC_HIGH_QUALITY, Constants.AUDIO_SCENARIO_GAME_STREAMING)

这里我们只是举了三个例子,围绕互动播客场景还有很多玩法正在涌现。如果你有新的想法,但还不知道如何基于 Agora API 实现,可以在 RTC社区发帖留言与我们交流。如需了解场景方案的更多细节,欢迎拨打 400 632 6626 详询。

查看原文

赞 0 收藏 0 评论 0

声网Agora 发布了文章 · 3月3日

基于容器环境的1-1课堂的开发部署

作者:申屠鹏会

近年来,容器化已经是业界的共识了,不仅可以减少运维的成本,也有助于进行产品的快速迭代,同时,本地也可以利用容器,搭建出和生产几乎一样的环境,很方便的进行开发demo或者进行小功能的测试部署。接下来,我将从产品的需求分析,设计,业务编码,集成测试,到正式上线,利用声网强大的SDK,全程用容器化的思想,完成一个一对一课堂软件的开发。(因为资源关系,开发时候的容器环境只用Docker,而非K8s)。

项目介绍

疫情以来,传统的一对一家教已经很难实现了,利用网络进行视频教学逐渐成为主流,但是现有的腾讯会议,ZOOM,小鱼会议等平台,侧重点还是多人视频会议的场景,对于一对一辅导教学还是有所欠缺的。因此,希望开发一个能够支持学生和老师实时音频互动,实时文字沟通,白板,课堂回放,作业布置,批改,屏幕共享的1对1课堂教学软件。

需求分析

一般通过项目介绍,可以大致知道是一个怎么样的产品。如:产品的形态是什么,用户是什么,主要功能是什么。那么在需求分析阶段,就要细化,归类,取舍。在一般的互联网公司,经常有的还有需求评审,有了需求,能不能实现,能不能按时完成,都是需要考虑的。但是现在我们自己做demo的化,最简单的还是画一个思维导图,把功能分成几个模块,列一下优先级就行了。接下来就是对项目介绍的需求分析。首先,我们明确产品的形态,对于教学软件来说,最方便的就是Web端了,只要打开浏览器,配备一个有摄像头的电脑就可以开始学习,手机总归小了一点。然后根据介绍,一对一的教学意味着还有用户管理的功能。除此之外,最重要的就是课堂功能了,老师能够在课堂给学生讲课,录视频,共享桌面等功能,同时还需要和学生进行沟通,布置作业,因此还需要消息通知等功能。

那么经过以上分析,我们先做一个思维导图,重点是功能分类。如下

经过分析总结,发现总共分为四个模块,分别是课堂管理,用户管理,白板功能,实时音视频,根据需求分析,就可以开始进行下一步的技术选型了。

技术选型

现在的技术有很多,光编程语言就有几十种,每种语言都有自己的框架,通信协议也有各种RPC,那么技术选型其实就是从广泛的技术海中选取最适合自己需求的技术,需要注意的是,技术选型从来不是以技术稳定或者技术先进为标准的,而是应该找最适合的。由此,我们开始进行技术的选型。通常我会从底层开始选取,下面我制作了一个表格,以供参考。

备选技术实现功能理由
Golang后端语言能够很方便的编译成可执行文件,然后打包成容器服务
html等Web前端页面不采用vue等框架的原因是为了快速开发体验
Mysql后端数据库开源免费,够用就行
Redis缓存,用户鉴权等功能
Agora SDK实时音视频互动业界最流畅最强大的音视频SDK
腾讯云后端服务器提供容器部署,网关等服务。
第三方白板白板功能

有了大致的技术选型之后,接下去就是进行架构设计。

架构设计

由于功能较少,服务大致分成了Redis缓存,Mysql数据库,后端服务,前端服务,以及网关五个服务。架构图画的比较丑,如下:

声网有个更好看的图片,我也放上来:

对比着看的化,声网的更加细化,尤其AgoraEdu云服务提供了不少功能,但我们自己开发的时候,用自己的服务器,那需要干的事情还是有点多的。在自己设计的架构图里,所有Agora的SDK会被打包进前端服务里,用户管理等模块会属于后端服务,两者都是容器化的服务,之间通过https的接口进行访问。而Mysql和Redis则提供了数据库的功能。网关层则是一个鉴权,限流和HTTPS加密的服务。接下去就是实战部分了。实战我会偷点懒,会把CI/CD的省略,我会在本地编程测试完成之后再打包镜像到服务器的Docker,如果工程量大的时候还是建议大家用持续部署的方式来做。

环境准备

尽管从这开始已经是实战部分了,但是“磨刀不误砍柴工”,我们可以先准备好所需的环境。

所需的开发环境:

操作系统:macos或者windows 10

编程环境:Golang

软件:Docker

有了最基础的几个之后,可以开启一些服务了。

数据库

Docker run -d -p 3306:3306 --name mysql mysql:5.7

缓存

Docker run -d -p 6379:6379 --name redis redis:4.0

检查环境是否都正常:

环境就绪后,那么接下去就是开发了。

编码开发

在编码过程中,我们可以先编写后端的服务,然后有接口提供了,再编写前端的,如此交替式编程,快速完成一个Demo。

首先我们创建两个空文件夹,一个作为后端服务,一个作为前端服务。然后打开前端服务,新建一个Html。

为了方便起见,我们用CDN的方式引入Agora的SDK。

<script data-original="https://cdn.agora.io/sdk/release/AgoraRTCSDK-3.2.1.js"></script>

Agora提供了一个实现音视频通话的调用过程,强烈建议阅读一下:

从上往下,以教师学生为例,业务逻辑可以是这样的:

老师通过AgoraRTC.createClient和Client.init创建本地客户端,然后通过Client.join加入频道。这时候可以理解为创建了一个课堂。接着通过创建本地流-播放本地流-发布本地流的过程,发送音视频数据。

那么学生端的操作就是通过订阅远端流,接受音频数据,然后进行播放。

如果要离开课堂的话,那就是通过Client.leave离开频道。

Agora的SDK可以替我们做这些工作,是不是非常强大?

获取SDK的权限

我们先到agora.io上注册一下我们的项目,随后会展示一些示例代码,如图:

我们选择Web端,按照请求调用的路径,我们需要先初始化一个客户端对象,然后填入项目的APP ID和Token。同时,对于一对一视频场景,mode设置为rtc。

可以看到我们需要传入一个APPID和一个Token还有频道。这些就由我们的后端提供。

具体逻辑为,用户登录之后,停留在课堂管理界面。然后新建课堂,输入频道号,然后点击建立的时候,后台返回APPID和Token,同时将课堂号存入数据库。

Agora很贴心的列出了几乎所有涉及的API,如下:

部署测试

代码编写完成后,就可以打包成镜像,然后部署到服务器上,再配置一个反向代理,就能给朋友分享访问啦,接下来我们对前端和后端分别进行打包。

对于前端来说,我们没有用框架,因此我们可以直接用一个nginx镜像,将其中的index替换成我们项目的index.html即可。

对于后端来说,Go可以通过:CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go方便的编译成可执行文件。我们只需要From一个空镜像,copy编译好的可执行文件即可。

后端Dockerfile:

非常简单,只需要将编译好的可执行文件main 用copy命令复制到容器内部某个目录,然后等容器起来的时候运行 ./main运行即可。

体验分享

Agora的开发者中心文档非常全面,关键的地方还有最佳实践的示例可以避免踩坑,同时,Agora提供了很多新手入门的Demo和开源项目,社区也是非常的活跃。

几乎可以这么说,只要懂得基础的编程知识,不管是初级程序员还是高级程序员,也不管是后端开发还是前端开发,都很快速的上手,如果有问题也能在开发者中心的文档库里搜到,这就是开发者中心最大的价值吧。

除此之外,通过Agora的demo体验,整个音视频的效果是出人意料的。可能很多人会觉得,不就是音视频通话吗,微信也有啊,QQ也有啊,甚至只要一个聊天社交软件可能都会有视频通话;先别说很多都用了声网的技术,就算是微信自研的,也会发现,相同的网络环境下,微信视频比较模糊,延迟也会稍高,同时如果在密闭房间,回音的现象很严重。声网这点做的很不错。

除此之外,声网也是见过SDK覆盖最全的,

可以从这截图发现,几乎涵盖了所有的平台。这些细节也可以看出声网在这方面也是投入了很多精力。

最让人惊喜的还是注册用户就送超长的视频通话时长,足够用来做一个小范围的音视频直播应用了。感谢声网。

补充

本文的例子和官网的一对一需求是差不多的,官网会更简单些,因为有Agora云服务,提供了开箱即用的API,可以让前端同学减少对后端的接触——换句话说,没有后端知识,也能够很快速的开发一个合格的应用。

本文的目的还在于对全栈开发者有个参考,如何从需求分析到技术选型,乃至产品部署上线,用模块化,容器化的思想快速开发一个音视频的Demo。

本Demo在线体验地址:https://agora.xabc.site

官方教程Demo体验地址:https://docs.agora.io/cn/Vide...

作者网站:https://xabc.site

查看原文

赞 0 收藏 0 评论 0

声网Agora 发布了文章 · 3月1日

「Typing」开源—— 3步打造属于自己的实时文字互动社交App

为了与开发者一起更好地探索互动实时消息的更多可能性,我们基于声网云信令/ RTM(Real-time Messaging)SDK 开源了一个实时文字互动 Demo——「Typing」。从体验来讲,「Typing」与音视频通话更为类似。对方打字时的速度或每一个停顿都可以被看见,并且实时展示的文字信息与数据也不会有历史留存。

开源地址:https://github.com/AgoraIO-Community/typing/releases


「Typing」Demo演示

这样一种几乎“无时延”、无留存信息的互动方式在很多针对 Z 世代群体(Generation-Z,一般是指在1995年——2009年出生的一代)进行开发的 App 中也受到了广泛的应用。

比如主打 00 后社交新模式的「Honk」就是一款致力于“消除”社交延时的文字对话互动 App,希望通过“真阅后即焚”的 100% 实时、无历史数据留存的私密体验,让使用者体验到几乎无时间差的熟人社交型文字互动。在「Honk」上线的第二天,下载排名就达到了美国 iOS 社交类榜单的第 10 位。


Honk丨图片来源:Sensor Tower

Z 世代是伴随着互联网和社交媒体长大的一代,相较于其他群体而言,他们对于技术和互联网社交的需求显得更为原始本能——实时互动、安全及熟人社交。而 「Honk」 之所以能够颠覆传统的文本消息互动体验,背后依靠的正是实时消息技术。

关于实时消息

通常实时消息可以分为两种,一种是帮助用户来交流的消息,比如文字消息、点赞、送礼物、发弹幕等。另一种则是信令消息,比如聊天室中禁言踢人的权限管理、上麦请求等。与微信、Snapchat 等这类即时通讯聊天软件相比,实时消息传输的重点在于信令、消息传输的低延时和高送达率上。

声网云信令/RTM (Real-time Messaging)SDK 是一个通用的消息系统,主要是为了解决实时场景下信令的低延迟和高并发问题。云信令/RTM (Real-time Messaging)SDK 的服务器端采用分布式架构,没有一个单点或者中心式的情况,通过多机房多路保活机制,智能优化路径,在其它节点失效时可以自动转移,选择最优节点路径传输。因此,可以有效保证传输的稳定性与可靠性,在性能方面也可以支持高吞吐量和低延时。

我们尝试基于声网云信令/RTM(Real-time Messaging) SDK 实现了 「Honk」 中的实时文字消息聊天功能,并作为 Demo 开源。希望可以抛砖引玉,与社区的开发者们一起探索更多基于实时信令和虚拟键盘的互动实时消息的新玩儿法。

「Typing」开源

目前的「Typing」Demo 中,我们提供了类似 「Honk」 的实时文字聊天,以及点击对方聊天框发送震动的功能,开发者只需要简单的几步就可以实现。以 iOS 版为例:

安装

更改目录为 iOS 文件夹,运行以下命令安装项目依赖项,

pod install

输入验证,生成正确的 xcworkspace

获取 App ID

要构建并运行示例应用程序,需要获取一个应用 ID :
👉1、在agora.io创建一个开发者帐户。完成注册过程后,会重新回到仪表板。
👉2、在左侧的仪表板树中导航到项目 > 项目列表。
👉3、保存仪表板上的 App ID 以备以后使用。
👉4、生成一个临时访问 Token (24 小时内有效) 从仪表板页面给定的通道名称,保存以后使用。

*注:对于安全性要求更高的场景,如果想要部署自己的RTM Token服务器,请参阅文档(https://docs.agora.io/cn/Real-time-Messaging/token_server_rtm

接下来,打开 Typing.xcworkspace 并编辑 KeyCenter.swift 文件。在 KeyCenter 中更新 <#Your App Id#>,用仪表盘生成的 Token 更改<#Temp Access Token#>

*注:如果建立的项目没有打开security token,可以将 token 变量保留为nil。

1Swift
2    struct KeyCenter {
3        static let AppId: String = <#Your App Id#>
4
5        // assign token to nil if you have not enabled app certificate
6        static var Token: String? = <#Temp Access Token#>
7    }

目前,该 Demo 支持 iOS 与 Android 平台。对于 Android 平台的小伙伴,可以选择下载打包好的 apk 文件,直接体验「Typing」。

我们相信,关于声网云信令/RTM(Real-time Messaging)SDK 的应用场景和使用方式在不断涌现的新需求下,还有很大的待挖掘潜力。例如,或许你可以考虑把手机键盘变成一个简易的虚拟钢琴键盘,为对方弹奏一首简单的小乐曲?开发者可以通过「Typing」,快速了解声网云信令/RTM(Real-time Messaging) SDK的基本用法,并且继续探索除了文字实时交流之外的,基于各种类型虚拟键盘所进行的 1 对 1 实时互动。

如果你对「Typing」感兴趣的话,可以进入我们的讨论群与社区的开发者们进行交流,也可以在 GitHub 仓库提交 Issue 留下你的问题、收藏/Fork「Typing」项目,或是通过 Pull Request 提交你的创意与成果。

扫描下方二维码

加入「Typing」讨论群

开源地址:https://github.com/AgoraIO-Community/typing/releases
查看原文

赞 1 收藏 0 评论 0

声网Agora 发布了文章 · 2月24日

开发者投稿|使用声网的RTM SDK轻松给angular应用加上实时聊天功能

作者:陈畏民

源起

今年寒假的前半段时间, 在家捣鼓了一个情侣类web应用, 基于aspnetcore和angular搭建的; 寒假中实现了'告白', '相册', '说说', '纪念日'这些功能, 然后前端界面上留一个功能的坑位: 聊天, 点击这个聊天按钮, 可以看到四个字, 那就是敬请期待; 部署上线后, 用户当然只有我和我的"好朋友"使用, "好朋友"先跨了我真棒, 然后问聊天功能马上可以用了吧? 我沉默了, 心想着这个功能后面用signalr试试看吧; 现在已经2020秋了, 聊天功能的界面上依旧是那四个字: 敬请期待

!

这个国庆, 我意识到不能再拖了, 自己埋的坑, 应该趁早把它填了, 否则"好朋友"会觉得你很菜, 一个"简单的"聊天功能都做不出来;

遇见声网(agora)

最开始想用signalr自己实现聊天功能的, 但是考虑到一方面, 自己的服务器资源有限(1核1G轻量应用服务器); 另一方面, 自身精力能力有限, 写出来也许不难, 但是要写好确是不简单的; 于是寻思着找找现成的东西用用吧, 机缘巧合, 我听说了声网(agora), 于是去他的官网看了一番, 看到有详细的文档, 足量的免费额度...于是决定先白嫖试用一下

关于agora

特地找了一下agora的相关资料, 看起来是挺靠谱的, 在全球都有数据中心和服务器; 小米、陌陌、新东方等知名企业都用过他们的云服务;

基于agora的rtm sdk给我的应用加上聊天功能

参考官网的文档

我的环境

  • win10系统
  • npm包管理
  • angular8.x
  • vscode

步骤

安装依赖

npm i agora-rtm-sdk
安装完后需要修改下agora-rtm-sdk/index.d.ts的文件的2258
原来的内容为:

export type { RtmChannel, RtmClient, RtmEvents, RtmMessage, RtmStatusCode };

修改为:

export { RtmChannel, RtmClient, RtmEvents, RtmMessage, RtmStatusCode };

不修改的话, 编译会报错

引入依赖

因为是在在angular组件ChatComponent中实现聊天相关的功能, 所以在其中引入rtm sdk的依赖 import AgoraRTM from 'agora-rtm-sdk';

创建rtm客户端并登陆到agora的rtm服务器

一行代码创建rtm客户端:

const rtmClient = AgoraRTM.createInstance('<your app id>');

<details>
<summary>登陆到rtm服务器</summary>

const rtmClient = AgoraRTM.createInstance('fd033b52ca5d40599efc96f6e2131639');

async function rtmClientLogin(user: User) {
  try {
    await rtmClient.login({ token: null, uid: user.id });
  } catch(err) {
    console.log('AgoraRTM client login failure', err);
  }
}

// 在组件的 ngOnInit 方法中调用 rtmClientLogin
async ngOnInit() {
    try {
      let user = await this.userServ.getUser().toPromise();
      if (user instanceof User) {
        this.user = user;
        rtmClientLogin(this.user);
      } else {
        throw new Error('无法获取用户数据');
      }
    } catch(err) {
      this.notifyServ.error('初始化聊天组件失败', null);
      console.error('初始化聊天组件失败', err);
    }
  }

ps: 测试阶段, 所以使用的rtm的授权方式是AppID, 如果要使用这种授权方式, 在rtm控制台创建项目的时候要注意一下, 身份认证模式勾选 App ID, 否则在登陆到rtm服务器的时候, 会报红

发送/接收消息

消息发送失败需要通知用户, 错误通知直接使用了antdesign的NzNotificationService, 在构造函数注入即可; 这个应用中, 互相发消息的双方是情侣, User表示当前用户, User.Spouse表示用户的伴侣; 消息发送成功需要清空发送消息文字框并将发送的消息加入消息数组中, 让angular更新视图

发送消息
async sendMessage() {
  if (!this.newMessage) {
    return;
  }
  const spouseId = this.user.spouse.id;

  try {
    const result = await rtmClient.sendMessageToPeer({
      text: this.newMessage
    }, spouseId);
    if (!result.hasPeerReceived) {
      throw new Error('对方未接受消息');
    } else {
      this.messages.push({
        text: this.newMessage,
        sender: this.user,
        receiver: this.user.spouse,
        dateSended: new Date()
      });
      this.newMessage = undefined;
    }
  } catch (err) {
    this.notifyServ.error('发送消息失败', null);
    console.log('发送消息失败', err);
  }
}

ngOnInit生命周期函数中监听收到新消息事件, 收到新消息后, 将新消息加入消息数组中, angular会通过数据绑定更新视图, 渲染ui

监听并处理收到新消息事件

async ngOnInit() {
  try {
    let user = await this.userServ.getUser().toPromise();
    if (user instanceof User) {
      this.user = user;
      rtmClientLogin(this.user);
      监听接收到消息事件
      rtmClient.on('MessageFromPeer', (rtmMessage, peerId) => {
        this.messages.push({
          text: rtmMessage.text,
          sender: this.user.spouse,
          receiver: this.user,
          dateSended: new Date()
        });
      });
      
    } else {
      throw new Error('无法获取用户数据');
    }
  } catch(err) {
    this.notifyServ.error('初始化聊天组件失败', null);
    console.error('初始化聊天组件失败', err);
  }
}

前端html代码

<div id="container">
    <div class="messages">
        <div class="message-item"
             *ngFor="let msg of messages">
            <div class="sendedMessage"
                 *ngIf="msg.sender.id === user.id">
                <span class="message-text">{{msg.text}}</span>
                <span>
                    <nz-avatar nzIcon="user"
                               [nzSrc]="msg.receiver.profileImageUrl"></nz-avatar>
                </span>
            </div>

            <div class="receviedMessage"
                 *ngIf="msg.sender.id === user.spouse.id">
                <span>
                    <nz-avatar nzIcon="user"
                               [nzSrc]="msg.sender.profileImageUrl"></nz-avatar>
                </span>
                <span class="message-text">{{msg.text}}</span>
            </div>
        </div>
    </div>

    <div class="new-message">
        <div nz-row
             nzJustify="end">
            <div nz-col
                 nzSpan="18">
                <textarea nz-input
                          [(ngModel)]="newMessage"
                          [nzAutosize]="{ minRows: 1, maxRows: 6 }"></textarea>
            </div>
            <div nz-col
                 nzSpan="6">
                <button nz-button
                        nzType="primary"
                        class="mx-auto"
                        style="width: 100%;"
                        (click)="sendMessage()">发送</button>
            </div>
        </div>
    </div>
</div>

前端css

:host {
    height: 100%;
    display: block;
    position: relative;
}

#container {
    height: 100%;
    display: flex;
    flex-direction: column;
    padding-top: 4px;
}

.messages {
    flex-grow: 1;
}

nz-alert {
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 85%;
    text-align: center;
}

.sendedMessage {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    margin-bottom: 8px;
}

.receviedMessage {
    margin-bottom: 8px;
}

.message-text {
    background: #fff;
    padding: 8px 4px;
}

.sendedMessage .message-text {
    margin-right: 4px;
}

.receviedMessage .message-text {
    margin-left: 4px;
}

效果如何?

动图演示:

静图:

小结

上文基于agora的rtm sdk, 初步实现了简单的聊天功能; 体验下来感觉很方便, 不需要关注后端实现, 只需要处理前端逻辑即可轻松构建出实时聊天功能; 当然, 正式在生产环境使用, 还是需要后端配合生成一个身份认证令牌(token)来保证安全性的; 上文暂时只实现了文字的发送接收, 实际上rtm sdk还支持文件和图片的收发, 功能很强大, 有机会再继续探索。


本文是参与声网"内容共建计划"的开发者投稿作品

了解更多实时互动相关内容可点击进入声网RTC 开发者社区进行查看

查看原文

赞 1 收藏 1 评论 0

声网Agora 发布了文章 · 2月3日

开源 | MoonLight —— 助你实现更好的 iOS/Mac 自动化性能测试

作者:MoonLight 开源项目作者、声网Agora Echoo J

什么是 MoonLight?

MoonLight 是 iOS/Mac 上的轻量化的性能测试组件,它可以单独集成在任何 App 中实现自动化性能数据的采集,你可以非常轻松的获取到 App CPU、System CPU、App Memory、System GPU 以及 GPU Info 的数据。MoonLight 由声网Agora 开发,并已开源至 Github。

开源地址:https://github.com/AgoraIO-Community/MoonLight

MoonLight 的愿景

MoonLight,它的中文意思名为月光。月光弥漫在地球之上是宁静且自然的,月光会给予地球上的人们以指引。而月光的寓意恰好和我们开发性能测试组件的出发点相契合。

我们希望 iOS/Mac 的性能测试也能像月光一样,轻松且自然。MoonLight 有着更低的性能消耗,更容易的使用方式,更精准的性能数据。它将帮助开发团队更快速更精确的定位性能问题,进而推动性能优化和提升。帮助测试团队更快更准的获取性能数据,提升测试效率。

对比其他的性能测试工具

Instruments

MoonLight采集到的性能数据是基本和Instruments保持一致的。具体的优劣对比如下:

  1. Instruments无法实现性能自动化,无法将获取到的性能数据提取出来进行分析,最后提供出去的性能数据准确度不够,存在人为误差。MoonLight可以解决这个问题。
  2. Instruments无法实现远程性能测试,自然也无法实现高并发的性能测试,通常来说需要一台设备连接USB线后测试,然后一台测试完再测试下一台。MoonLight可以一次性测试非常多台,也没有必须连接数据线的要求。
  3. 高版本的Instruments无法测试一些低端系统机器的性能,MoonLight可以完美支持。
  4. 对于macOS上的App, Instruments是不支持GPU的输出,MoonLight支持。进过测试,GPU的输出和macOS自带的活动管理器GPU输出保持一致。
  5. Instruments优点是数据可视化,并且可以提供内存泄漏测试。MoonLight暂时不提供数据可视化,但是由于MoonLight是可编程的,当开发者拿到相关的性能数据后, 可以自行实现数据上报或者可视化的处理。

GT

  1. GT不支持macOS,MoonLight支持。
  2. GT采集到的App Memory数据和Instruments是不一致的。GT 无法输出 GPU、System CPU, 但是MoonLight可以。
  3. GT集成到App中,需要添加非常多的依赖库,取消掉Bitcode支持,自身也比较庞大,并且会增加App的包大小。MoonLight更轻量化,对于iOS仅仅只需要增加一个系统库,对于Mac不需要增加任何的系统库。

Perfdog

  1. Perfdog无法支持macOS上的App的性能测试。
  2. Perfdog并非是一个自动化的性能测试工具,优点是数据可视化。
  3. Perfdog并非是一个开源的测试工具,之前在iOS 14上出现过App CPU不准的Bug, 而我们也并不清楚其实现的原理和代码,未来依旧有可能在某些系统上出现性能项测试不准的情况。

Requirements

  • iOS 8.0+
  • macOS 10.11+

Installation

Cocoapods

  • iOS:

Warning! For iOS, do not use it on AppStore release. Recommend use it on debug mode.

pod 'MoonLight_iOS', :configurations => ['Debug']
  • macOS:
pod 'MoonLight_macOS'

Usage

// Step1: create MoonLight instance and set sampling interval.
    _moonLight = [[MoonLight alloc]initWithDelegate:self timeInterval:1];

// Step2: start timer.
    [_moonLight startTimer];


// Step3: through the callback, you can get all the performance data per interval.
- (void)captureOutputAppCPU:(float)appCPU systemCPU:(float)systemCPU appMemory:(float)appMemory gpuUsage:(float)gpuUsage gpuInfo:(NSString *)gpuInfo {
    NSLog(@"appMemory:%f", appMemory);
    NSLog(@"appCPU:%f", appCPU);
    NSLog(@"gpuUsage:%f", gpuUsage);
    NSLog(@"systemCPU:%f", systemCPU);
    NSLog(@"gpuInfo:%@", gpuInfo);
}

// Step4:if you want to stop capturing the performance data, use "stopTimer".
    [_moonLight stopTimer];

MoonLight 自测的结果

iOS/Mac MoonLight 自身的性能消耗非常低,几乎可以忽略不计;测试的过程中,性能输出稳定;App CPU、System CPU、App Memory、GPU 可以和Instruments或者活动监视器结果保持一致。

一、MoonLight VS Instruments

  • iOS

ios

  • macOS

macos

备注:MoonLight对CPU有做归一化处理. CPU(MoonLight) = CPU(Instruments) / 核心数

二、MoonLight 自身的性能消耗

测试case:

Step1: 打开App,打开MoonLight的检测,测试性能data1。

Step2: 打开App, 不打开MoonLight的检测,测试性能data2。性能消耗 = data1 - data2

  • iOS

App Memory 消耗 = 7.38-7.34 = 0.04Mb ;App CPU 消耗 = (2.1%-0.1%)/ (6核) = 0.33% ;GPU = 0% ,并且整个性能测试阶段,数据波动稳定,不会出现MoonLight的开启造成性能有不稳定变化。

测试设备:iPhone XS iOS 14.2 六核

  • macOS

App Memory 消耗 = 14.42-14.36 = 0.06Mb ;App CPU 消耗 = (0.08%-0.0%)/ (4核) = 0.02% ;GPU = 0% ,并且整个性能测试阶段,数据波动稳定,不会出现MoonLight的开启造成性能有不稳定变化。

测试设备:Macbook Pro 2017 13.3 Intel i5 , System: BigSur 11.0.1

————————————————————————————

写在最后

MoonLight 是我们从日常的开发中诞生的开源工具,我们希望它能帮助开发团队更快速更精确的定位性能问题,进而推动性能优化和提升;帮助测试团队更快更准的获取性能数据,提升测试效率。欢迎大家使用。

MoonLight 开源地址:https://github.com/AgoraIO-Community/MoonLight

扫码加入交流群,与开源项目作者交流工具使用与开发的日常

扫码加入交流群

查看原文

赞 3 收藏 1 评论 0

声网Agora 发布了文章 · 1月27日

iOS ReplayKit 与 RTC

作者:声网Agora Cavan
在日益繁多的直播场景中,如果你也是某位游戏主播的粉丝的话,有一种直播方式是你一定不陌生的,那就是我们今天要聊的屏幕分享。

直播场景下的屏幕分享,不仅要将当前显示器所展示的画面分享给远端,也要将声音传输出去,包括应用的声音,以及主播的声音。鉴于这两点需求,我们可以简单分析出,进行一次屏幕分享的直播所需要的媒体流如下:

  1. 一条显示器画面的视频流
  2. 一条应用声音的音频流
  3. 一条主播声音的音频流

ReplayKit 是苹果提供的用于 iOS 系统进行屏幕录制的框架。

首先我们来看看苹果提供的用于屏幕录制的 ReplayKit 的数据回调接口:

override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
        DispatchQueue.main.async {
            switch sampleBufferType {
            case .video:
                AgoraUploader.sendVideoBuffer(sampleBuffer)
            case .audioApp:
                AgoraUploader.sendAudioAppBuffer(sampleBuffer)
            case .audioMic:
                AgoraUploader.sendAudioMicBuffer(sampleBuffer)
            @unknown default:
                break
            }
        }
    }

从枚举 sampleBufferType 上,我们不难看出,刚好能符合我们上述对媒体流的需求。

视频

格式

guard let videoFrame = CMSampleBufferGetImageBuffer(sampleBuffer) else {
    return
}
        
let type = CVPixelBufferGetPixelFormatType(videoFrame)
type = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange

通过 CVPixelBufferGetPixelFormatType,我们可以获取到每帧的视频格式为 yuv420

帧率

通过打印接口的回调次数,可以知道每秒能够获取的视频帧为30次,也就是帧率为 30。

格式与帧率都能符合 Agora RTC 所能接收的范围,所以通过 Agora RTC 的 pushExternalVideoFrame 就可以将视频分享到远端了。

agoraKit.pushExternalVideoFrame(frame)

插入一个小知识

显示器所显示的帧来自于一个帧缓存区,一般常见的为双缓存或三缓存。当屏幕显示完一帧后,发出一个垂直同步信号(V-Sync),告诉帧缓存区切换到下一帧的缓存上,然后显示器开始读取新的一帧数据做显示。

这个帧缓存区是系统级别的,一般的开发者是无法读取跟写入的。但是如果是苹果自身提供的录制框架 ReplayKit 能够直接读取到已经渲染好且将用于显示器的帧,且这一过程不会影响渲染流程而造成掉帧,那就能减少一次用于提供给 ReplayKit 回调数据的渲染过程。

音频

ReplayKit 能提供的音频有两种,分为麦克风录制进来的音频流,与当前响应的应用播放的音频流。(下文将前者称为 AudioMic,后者为 AudioApp)

可以通过下面的两行代码,来获取音频格式

CMAudioFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer);
const AudioStreamBasicDescription *description = CMAudioFormatDescriptionGetStreamBasicDescription(format);

AudioApp

AudioApp 会在不同的机型下有不一样的声道数。例如在 iPad 或 iPhone7 以下机型中,不具备双声道播放的设备,这时候 AudioApp 的数据就是单声道,反之则是双声道。

采样率在部分试过的机型里,都是 44100,但不排除在未测试过的机型会是其他的采样率。

AudioMic

AudioMic 在测试过的机型里,采样率为 32000,声道数为单声道。

音频前处理

如果我们将 AudioApp 与 AudioMic 作为两条音频流去发送,那么流量肯定是大于一条音频流的。我们为了节省一条音频流的流量,就需要将这两条音频流做混音(融合)。

但是通过上述,我们不难看出,两条音频流的格式是不一样的,而且不能保证随着机型的不同,是不是会出现其他的格式。在测试的过程中还发现 OS 版本的不同,每次回调给到的音频数据长度也会出现变化。那么我们在对两条音频流做混音前,就需要进行格式统一,来应对 ReplayKit 给出的各种格式。所以我们采取了以下几个重要的步骤:

     if (channels == 1) {
        int16_t* intData = (int16_t*)dataPointer;
        int16_t newBuffer[totalSamples * 2];
                
        for (int i = 0; i < totalSamples; i++) {
            newBuffer[2 * i] = intData[i];
            newBuffer[2 * i + 1] = intData[i];
        }
        totalSamples *= 2;
        memcpy(dataPointer, newBuffer, sizeof(int16_t) * totalSamples);
        totalBytes *= 2;
        channels = 2;
    }
  • 无论是 AudioMic 还是 AudioApp,只要进来的流为单声道,我们都将它转化为双声道;
     if (sampleRate != resampleRate) {
        int inDataSamplesPer10ms = sampleRate / 100;
        int outDataSamplesPer10ms = (int)resampleRate / 100;
        
        int16_t* intData = (int16_t*)dataPointer;
        
        switch (type) {
            case AudioTypeApp:
                totalSamples = resampleApp(intData, dataPointerSize, totalSamples,
                                           inDataSamplesPer10ms, outDataSamplesPer10ms, channels, sampleRate, (int)resampleRate);
                break;
            case AudioTypeMic:
                totalSamples = resampleMic(intData, dataPointerSize, totalSamples,
                                           inDataSamplesPer10ms, outDataSamplesPer10ms, channels, sampleRate, (int)resampleRate);
                break;
        }
        
        totalBytes = totalSamples * sizeof(int16_t);
    }
  • 无论是 AudioMic 还是 AudioApp,只要进来的流采样率不为 48000,我们将它们重采样为 48000;
  memcpy(appAudio + appAudioIndex, dataPointer, totalBytes);
  appAudioIndex += totalSamples;
    memcpy(micAudio + micAudioIndex, dataPointer, totalBytes);
  micAudioIndex += totalSamples;
  • 通过第一步与第二步,我们保证了两条音频流都为同样的音频格式。但是由于 ReplayKit 是一次回调给到一种数据的,所以在混音前我们还得用两个缓存区来存储这两条流数据;
  int64_t mixIndex = appAudioIndex > micAudioIndex ? micAudioIndex : appAudioIndex;
            
  int16_t pushBuffer[appAudioIndex];
            
  memcpy(pushBuffer, appAudio, appAudioIndex * sizeof(int16_t));
            
  for (int i = 0; i < mixIndex; i ++) {
       pushBuffer[i] = (appAudio[i] + micAudio[i]) / 2;
  }
  • ReplayKit 有选项是否开启麦克风录制,所以在关闭麦克风录制的时候,我们就只有一条 AudioApp 音频流。所以我们以这条流为主,去读取 AudioMic 缓存区的数据长度,然后对比两个缓存区的数据长度,以最小的数据长度为我们的混音长度。将混音长度的两个缓存区里的数据做融合,得到混音后的数据,写入一个新的混音缓存区(或者直接写入 AudioApp 缓存区);
[AgoraAudioProcessing pushAudioFrame:(*unsigned* *char* *)pushBuffer
                                   withFrameSize:appAudioIndex * *sizeof*(int16_t)];
  • 最后我们再将这段混音后的数据拷贝进 Agora RTC 的 C++ 录制回调接口里,这时候就可以把麦克风录制的声音与应用播放的声音传输到远端了。

通过对音视频流的处理,结合 Agora RTC SDK,我们就完成了一个屏幕分享直播场景的实现了。

具体的实现上的细节,可以参考 https://github.com/AgoraIO/Ad...

查看原文

赞 0 收藏 0 评论 0

声网Agora 发布了文章 · 1月25日

AI模型在移动设备的部署

近年来,随着AI技术的快速发展,AI模型部署到移动端设备的需求越来越强烈。AI模型部署到移动端设备,能带来诸多好处:

  1. 对于公司而言,无需为AI模型部署云端服务器,能够大幅度降低公司的运营和服务成本;
  2. 对于用户而言,用户的数据,如视频、图片、声音、文字等,无需上传至云端服务器,可在本地移动端进行计算,用户的隐私得到有效的保护。

然而,AI模型在移动端设备部署,却面临如下挑战和限制:

  1. 移动端设备运算能力有限,尽管现在的移动端设备的CPU、GPU、NPU能提供强大的运算能力,但相对AI模型来说,移动端设备的运算仍然不足,一些云端的模型,无法在移动设备上正常运行,即使能运行,用户体验也会打折扣;
  2. 移动端设备对AI模型的存储大小较为敏感,以vgg16模型为例,其大小为500MB,如此大的模型,如果集成到app,估计没有多少用户愿意下载使用;
  3. 移动端设备无法为AI模型提供足够的内存,AI模型除了运算复杂、模型过大外,对内存的消耗,小则几个GB,大小十几个GB;

因此,要将AI模型成功部署到移动端设备,并提供很好的用户体验,需要从模型轻量级设计、模型转换、模型量化以及推理加速等方面不断探索和优化。

模型轻量级设计

AI模型在模型结构设计阶段,应该根据移动端设备的硬件特性进行设计,在满足模型的性能前提下,模型的层数和每个层的通道数尽量小。卷积层的卷积核大小尽量小,不宜大量使用5x5、7x7,以3x3和1x1为主。模型轻量级设计可参考MobileNet和ShuffleNet。MobileNet是Google面向移动端设备推出的轻量级模型,已经经历了三个版本的迭代。MobileNet V1模型的核心思想是将原来标准的卷积操作因式分解成一个depthwise convolution和一个1x1的pointwise convolution操作;MobileNet V2在V1的基础上引入了残差结构,扩充了维度,并且在输出端pointwise卷积采用了线性激活;MobileNet V3采用了Neural Architecture Search(NAS),引入基于squeeze and excitation结构的轻量级注意力模型。ShuffleNet是旷视科技提出的轻量级模型,并经过了二个版本迭代。ShuffleNet V1的核心采用了两种操作:pointwise group convolution和channel shuffle,在保持精度的同时大大降低了模型的计算量;ShuffleNet V2则根据相同的FLOPs(float-point operations)情况下模型速度差别很大的现象,指出内存访问损失时间(MAC)和FLOPs共同决定实际落地时训练和运行的速度。

模型转换

当前,主流的深度学习开源训练框架有Tensorflow、Pytorch等,Tensorflow凭借先发优势和完整的社区,在工业界得到广泛的应用,而Pytorch借助其易用性和不错的性能,在学术界的影响力已超越了Tensorflow。虽然Tensorflow和Pytorch均提供了移动端版本,但推理速度有限,不能满足移动端对推理速度的要求。经过几年的发展,移动端的推理框架已经形成群雄争霸的局部。当前主流的移动端推理框架有ncnn、MACE、MNN、TNN。

ncnn 是腾讯优图实验室首个开源项目,是一个为手机端极致优化的高性能神经网络前向计算框架。ncnn 从设计之初深刻考虑手机端的部属和使用。无第三方依赖,跨平台,手机端 cpu 的速度快于目前所有已知的开源框架。

MACE是小米公司推出的一个专为移动端异构计算平台的神经网络计算框架,主要从性能、功耗、系统响应内存占用、模型加密与保护、硬件支持范围进行了专门的优化。

MNN是一个高效、轻量的深度学习框架。它支持深度模型推理与训练,尤其在端侧的推理与训练性能在业界处于领先地位。目前,MNN已经在阿里巴巴的手机淘宝、手机天猫、优酷、钉钉、闲鱼等20多个App中使用,覆盖直播、短视频、搜索推荐、商品图像搜索、互动营销、权益发放、安全风控等70多个场景。此外,IoT等场景下也有若干应用。

TNN:由腾讯优图实验室打造,移动端高性能、轻量级推理框架,同时拥有跨平台、高性能、模型压缩、代码裁剪等众多突出优势。TNN框架在原有Rapidnet、ncnn框架的基础上进一步加强了移动端设备的支持以及性能优化,同时也借鉴了业界主流开源框架高性能和良好拓展性的优点。

移动端推理框架ncnn、MACE、MNN、TNN,并不能直接兼容Tensorflow、Pytorch的模型,而需要先将Tensorflow、Pytorch转换成ONNX(Open Neural Network Exchange),再将ONNX转换到ncnn、MACE、MNN、TNN所支持的模型。ONNX是一个用于表示深度学习模型的标准,可使模型在不同框架之间进行转移。

移动端部署

通过ONNX将Tensorflow、Pytorch转换至ncnn、MACE、MNN或TNN,根据ios或android,编译移动端推理框架的库。为了进一步追求模型的推理速度,可利用推理框架对模型进行卷积层与激活层融合,减小网络层间的IO开销;也可将float32进行int8量化,在不降低模型的精度前提下,理论上可将模型大小缩减4倍,推理速度提高2~3倍的提高。

查看原文

赞 0 收藏 0 评论 0

声网Agora 发布了文章 · 1月12日

自动切换横竖屏幕——手机加速度传感器在Android横竖屏切换中的应用

作者: 声网Agora 工程师 黄龙飞

前言
在日常生活中使用手机,通常都会遇到下面这两种场景。
场景一:
在使用手机看视频且设备开启屏幕自动旋转时,手机横着拿和竖着拿,所看到的效果会不一样。竖屏状态下的展示如下图(图1)所示,横屏状态下的展示如图2所示。

Screenshot_20200812-105649_Tencent%20Video

图1.竖屏播放视频

Screenshot_20200812-105700_Tencent%20Video

图2.横屏播放视频

场景二:
在使用的手机应用中,某些应用的某些界面会根据当前手机横竖屏的状态,展示不同的界面效果,方便大家使用。比如AgoraVideoCall中的会议界面,具体如图3 & 图4所示:

Screenshot_20200816-170356_Agora%20Video%20Call

图3.AgoraVideoCall会议界面竖屏展示

Screenshot_20200816-170407_Agora%20Video%20Call

图4.AgoraVideoCall会议界面横屏展示

上述中的两种场景,都是根据用户手持手机的方式及旋转动作自动识别出用户是想要横屏展示还是竖屏展示的。关于“手机如何根据用户的旋转动作而识别出用户意图"这个问题将会在下文中具体阐述。

加速度传感器原理
手机实现这一功能的核心部件是加速度传感器,在介绍加速度传感器之前,先了解一下传感器坐标系。

  • 传感器坐标系
通常,传感器框架使用标准的 3 轴坐标系来表示数据值。对于大多数传感器,当设备处于默认屏幕方向时,会相对于设备屏幕来定义坐标系(参见图 5)。当设备处于默认屏幕方向时,X 轴为水平向右延伸,Y 轴为垂直向上延伸,Z 轴为垂直于屏幕向外延伸。在此坐标系中,屏幕后面的坐标将具有负 Z 值。关于此坐标系,特别需要注意的一点就是传感器的坐标系不会随着设备的移动而改变。

图5.传感器坐标系(相对于设备)。

  • 加速度传感器
加速度传感器,它采用弹性敏感元件制成悬臂式位移器,与采用弹性敏感元件制成的储能弹簧来驱动电触点,完成从重力变化到电信号的转换。例如:一个壳体与要测量加速度的物体,通过弹簧连接在一起,组成的一个重力感应器,当我们把壳体向上移动时,金属球会因为惯性向下拉伸弹簧,这时我们只需要测量出弹簧的拉伸量,我们就可以由此计算出重力。由此易得,X,Y,Z加速度计,就能测量一个物体在三维空间中的运动方向。详细说明请参阅[重力感应原理]

加速度传感器在Android横竖屏切换中的应用
加速度传感器在移动设备中的应用众多,本文主要介绍加速度传感器在Android系统中横竖屏切换的应用,其原理主要为:通过监听加速度传感器,实时获得X、Y、Z三个方向的加速度值;当4(X_X + Y_Y)>=Z*Z时,开始计算设备在X与Y平面上的旋转角度;最后根据旋转角度计算出设备的横竖屏状态。下面贴出主要代码。

/**
* 在onResume中,向SensorManager注册监听加速度传感器
*/
@Override
protected void onResume() {
    super.onResume();
    orientationListener = new OrientationListener(this);
    orientationListener.enable();
}

public void enable() {
    if (mSensor == null) {
        Log.w(TAG, "Cannot detect sensors. Not enabled");
        return;
    }
    if (mEnabled == false) {
        if (localLOGV) Log.d(TAG, "OrientationEventListener enabled");
        mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
        mEnabled = true;
    }
} 

class SensorEventListenerImpl implements SensorEventListener {
    private static final int _DATA_X = 0;
    private static final int _DATA_Y = 1;
    private static final int _DATA_Z = 2;

    /**
    ** 通过X、Y、Z三个方向的加速度值的变化,计算出设备旋转的角度。
    **/
    public void onSensorChanged(SensorEvent event) {
        float[] values = event.values;
        int orientation = ORIENTATION_UNKNOWN;
        float X = -values[_DATA_X];
        float Y = -values[_DATA_Y];
        float Z = -values[_DATA_Z];        
        float magnitude = X*X + Y*Y;
        // Don't trust the angle if the magnitude is small compared to the y value
        if (magnitude * 4 >= Z*Z) {
            float OneEightyOverPi = 57.29577957855f;
            float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi;
            orientation = 90 - (int)Math.round(angle);
            // normalize to 0 - 359 range
            while (orientation >= 360) {
                orientation -= 360;
            } 
            while (orientation < 0) {
                orientation += 360;
            }
        }
        if (mOldListener != null) {
            mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values);
        }
        if (orientation != mOrientation) {
            mOrientation = orientation;
            onOrientationChanged(orientation);
        }
    }
} 

public class OrientationListener extends OrientationEventListener {
    private int degree = 0;//旋转角度
    private int mOrientation = 0;//2—横屏 1-竖屏,0-未知
    public OrientationListener(Context context) {
        super(context);
    }
    /**
    * 根据旋转的角度,得出设备横竖屏状态
    **/
    @Override
    public void onOrientationChanged(int orientation) {
        degree = orientation;
        if (degree > 0 && degree < 45) {
            mOrientation = 1;
        } else if (degree > 45 && degree < 135) {
            mOrientation = 2;
        } else if (degree > 135 && degree < 225) {
            mOrientation = 1;
        } else if (degree > 225 && degree < 315) {
            mOrientation = 2;
        } else if (degree > 315 && degree < 360) {
            mOrientation = 1;
        } 
        if (mOrientation == 2) {
            Log.i("OrientationListener ", "横屏");
        } else if (mOrientation == 1) {
            Log.i("OrientationListener ", "竖屏");
        }
    }
} 

特别说明:Math.atan2(-Y, X) 是计算从原点(0,0)到(x,y)点的线段与x轴正方向之间的平面角度(弧度值),
float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi得到的是原点(0,0)到(x,y)点的线段与x轴正方向之间的角度,90 - (int)Math.round(angle)为设备旋转的角度。

实战演练
本节实现一个简易的打高尔夫球游戏,练习一下加速度传感器的运用。该游戏为多人游戏,游戏规则为:参与者通过摇晃手机控制高尔夫球的移动,当高尔夫球落到洞中则计1分,否则不计分,每人操作3次,得分最高者获胜。游戏实现原理是根据加速度传感器获得设备旋转角度,实时计算并更新高尔夫球的位置,根据高尔夫球的位置与洞的重合度,判断高尔夫球是否落入洞中。落入洞中则得分,否则,不计分。游戏具体实现见附件,演示如下。

链接: https://pan.baidu.com/s/1Kas3kL0fdaXbygGA--l7JQ 2 提取码: 87nh
链接: https://pan.baidu.com/s/1yXNbbI3QhYG3BMZsyG2PSw 1 提取码: 8uaz

扩展
大多数移动设备,除了上面介绍的加速度传感器外,还有很多内置传感器,比如:重力传感器、旋转矢量传感器、屏幕方向传感器、温度传感器、光传感器、压力传感器等(如需了解详细信息,请参阅传感器)。开发者可以根据这些传感器,实现许多非常智能的功能。比如:

  • 通过光线传感器,自动调节屏幕的亮度,保护用户的眼睛
  • 通过加速度传感器,实现计步器和运动检测功能
  • 通过湿度传感器和温度传感器,计算露点和绝对湿度
  • 通过GPS,实现导航功能

参考文献:

附件
AccelerometerPlay.zip (5.0 KB)

查看原文

赞 0 收藏 0 评论 0

认证与成就

  • 获得 120 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • Agora SOLO

    声网Aogra 开源了自研的抗丢包音频编解码器 SOLO ,面向所有音视频、WebRTC 开发者。开发者可以将其结合到需要实时音视频传输的项目中,它可以在网络丢包率较高的情况下,让音视频应用仍可拥有较高质量的音频体验。25%丢包率下,MOS 值优于 Opus。

注册于 2016-05-10
个人主页被 5.8k 人浏览