乐趣区

关于直播:微信小游戏直播在Android端的跨进程渲染推流实践

本文由微信开发团队工程师“virwu”分享。

1、引言

近期,微信小游戏反对了视频号一键开播,将微信降级到最新版本,关上腾讯系小游戏(如跳一跳、欢畅斗地主等),在右上角菜单就能够看到发动直播的按钮一键成为游戏主播了(如下图所示)。

然而微信小游戏出于性能和平安等一系列思考,运行在一个独立的过程中,在该环境中不会初始化视频号直播相干的模块。这就意味着小游戏的音视频数据必须跨过程传输到主过程进行推流,给咱们实现小游戏直播带来了一系列挑战。

(本文同步公布于:http://www.52im.net/thread-35…)

2、系列文章

本文是系列文章中的第 5 篇:

《直播零碎聊天技术(一):百万在线的美拍直播弹幕零碎的实时推送技术实际之路》
《直播零碎聊天技术(二):阿里电商 IM 音讯平台,在群聊、直播场景下的技术实际》
《直播零碎聊天技术(三):微信直播聊天室单房间 1500 万在线的音讯架构演进之路》
《直播零碎聊天技术(四):百度直播的海量用户实时音讯零碎架构演进实际》
《直播零碎聊天技术(五):微信小游戏直播在 Android 端的跨过程渲染推流实际》(* 本文)

3、视频采集推流

3.1 录屏采集?
小游戏直播实质上就是把主播手机屏幕上的内容展现给观众,自然而然地咱们能够想到采纳零碎的录屏接口 MediaProjection 进行视频数据的采集。

这种计划有这些长处:

1)零碎接口,实现简略,兼容性和稳定性有肯定保障;
2)前期能够扩大成通用的录屏直播;
3)对游戏性能影响较小,经测试对帧率影响在 10% 以内;
4)能够间接在主过程进行数据处理及推流,不必解决小游戏跨过程的问题。
然而最终这个计划被否决了,次要出于以下思考:

1)须要展现零碎受权弹窗;
2)须要审慎解决切出小游戏后暂停画面推流的状况,否则可能录制到主播的其余界面,有隐衷危险;
3)最要害的一点:产品设计上须要在小游戏上展现一个评论挂件(如下图),便于主播查看直播评论以及进行互动,录屏直播会让观众也看到这个组件,影响观看体验的同时会裸露一些只有主播能力看到的数据。

转念一想,既然小游戏的渲染齐全是由咱们管制的,为了更好的直播体验,是否将小游戏渲染的内容跨过程传输到主过程来进行推流呢?

3.2 小游戏渲染架构
为了更好地形容咱们采纳的计划,这里先简略介绍一下小游戏的渲染架构:

能够看到图中左半边示意在前台的小游戏过程,其中 MagicBrush 为小游戏渲染引擎,它接管来自于小游戏代码的渲染指令调用,将画面渲染到在屏的 SurfaceView 提供的 Surface 上。整个过程主过程在后盾不参加。

3.3 小游戏录屏时的状况
小游戏之前反对过游戏内容的录制,和直播原理上相似,都须要获取以后小游戏的画面内容。

录屏启用时小游戏会切换到如下的模式进行渲染:

能够看到,MagicBrush 的输入指标不再是在屏的 SurfaceView,而是 Renderer 产生的一个 SurfaceTexture。

这里先介绍一下 Renderer 的作用:

Renderer 是一个独立的渲染模块,示意一个独立的 GL 环境,它能够创立 SurfaceTexture 作为输出,收到 SurfaceTexture 的 onFrameAvailable 回调后通过 updateTexImage 办法将图像数据转换为类型是 GL_TEXTURE_EXTERNAL_OES 的纹理参加后续的渲染过程,并能够将渲染后果输入到另一个 Surface 上。

上面逐渐对图中过程进行解释:

1)MagicBrush 接管来自小游戏代码的渲染指令调用,将小游戏内容渲染到第一个 Renderer 所创立的 SurfaceTexture 上;

2)随后这个 Renderer 做了两件事件:

2.1)将失去的小游戏画面纹理再次渲染到了在屏的 Surface 上;
2.2)提供纹理 ID 给到第二个 Renderer(这里两个 Renderer 通过共享 GLContext 来实现共享纹理)。
3)第二个 Renderer 将第一个 Renderer 提供的纹理渲染到 mp4 编码器提供的输出 SurfaceTexture 上,最终编码器编码产生 mp4 录屏文件。

3.4 革新录屏计划?
能够看到,录屏计划中通过一个 Renderer 负责将游戏内容上屏,另一个 Renderer 将同样的纹理渲染到编码器上的形式实现了录制游戏内容,直播其实相似,是不是只有将编码器替换为直播的推流模块就能够了呢?

的确如此,但还短少要害的一环:推流模块运行在主过程,咱们须要实现跨过程传输图像数据!如何跨过程呢?

说到跨过程:可能咱们脑海里蹦出的第一反馈就是 Binder、Socket、共享内存等等传统的 IPC 通信办法。但认真一想,零碎提供的 SurfaceView 是十分非凡的一个 View 组件,它不通过传统的 View 树来参加绘制,而是间接经由零碎的 SurfaceFlinger 来合成到屏幕上,而 SurfaceFlinger 运行在零碎过程上,咱们绘制在 SurfaceView 所提供的 Surface 上的内容必然是能够跨过程进行传输的,而 Surface 跨过程的办法很简略——它自身就实现了 Parcelable 接口,这意味着咱们能够用 Binder 间接跨过程传输 Surface 对象。

于是咱们有了上面这个初步计划:

能够看到:第 3 步不再是渲染到 mp4 编码器上,而是渲染到主过程跨过程传输过去的 Surface 上,主过程的这个 Surface 是通过一个 Renderer 创立的 SurfaceTexture 包装而来的,当初小游戏过程作为生产者向这个 Surface 渲染画面。当一帧渲染结束后,主过程的 SurfaceTexture 就会收到 onFrameAvailable 回调告诉图像数据曾经筹备结束,随之通过 updateTexImage 获取到对应的纹理数据,这里因为直播推流模块只反对 GL_TEXTURE_2D 类型的纹理,这里主过程 Renderer 会将 GL_TEXTURE_EXTERNAL_OES 转换为 GL_TEXTURE_2D 纹理后给到直播推流编码器,实现推流过程。

通过一番革新:上述计划胜利地实现了将小游戏渲染在屏幕上的同时传递给主过程进行推流,但这真的是最优的计划吗?

思考一番,发现上述计划中的 Renderer 过多了,小游戏过程中存在两个,一个用于渲染上屏,一个用于渲染到跨过程而来的 Surface 上,主过程中还存在一个用于转换纹理以及调用推流模块。如果要同时反对录屏,还须要在小游戏过程再起一个 Renderer 用于渲染到 mp4 编码器,过多的 Renderer 意味着过多的额定渲染开销,会影响小游戏运行性能。

3.5 跨过程渲染计划
纵观整个流程,其实只有主过程的 Renderer 是必要的,小游戏所应用的额定 Render 无非就是想同时满足渲染上屏和跨过程传输,让咱们大开脑洞——既然 Surface 自身就不受过程的束缚,那咱们罗唆把小游戏过程的在屏 Surface 传递到主过程进行渲染上屏吧!

最终咱们大刀阔斧地砍掉了小游戏过程的两个冗余 Renderer,MagicBrush 间接渲染到了跨过程传递而来的 Surface 上,而主过程的 Renderer 在负责纹理类型转换的同时也负责将纹理渲染到跨过程传递而来的小游戏过程的在屏 Surface 上,实现画面的渲染上屏。

最终所须要的 Renderer 数量从原来的 3 个缩小到了必要的 1 个,在架构更加清晰的同时晋升了性能。

后续须要同时反对录屏时,只有稍作改变,将 mp4 编码器的输出 SurfaceTexture 也跨过程传递到主过程,再新增一个 Renderer 渲染纹理到它下面就行了(如下图所示)。

3.6 兼容性与性能
到这里,不禁有点放心,跨过程传输和渲染 Surface 的这套计划的兼容性会不会有问题呢?

实际上,尽管并不常见,然而官网文档外面是有阐明能够跨过程进行绘制的:

SurfaceView combines a surface and a view. SurfaceView’s view components are composited by SurfaceFlinger (and not the app), enabling rendering from a separate thread/process and isolation from app UI rendering.

并且 Chrome 以及 Android O 当前的零碎 WebView 都有应用跨过程渲染的计划。

在咱们的兼容性测试中,笼罩了 Android 5.1 及当前的各个支流零碎版本和机型,除了 Android 5.x 机型上呈现了跨过程渲染黑屏的问题外,其余均能够失常渲染上屏和推流。

性能方面:咱们应用了 WebGL 水族馆的 Demo 进行了性能测试,能够看到对于均匀帧率的影响在 15% 左右,主过程的 CPU 因为渲染和推流有所升高,奇怪的是小游戏过程的 CPU 开销却呈现了一些降落,这里降落的起因临时还没有确认,狐疑与上屏操作移到主过程相干,也不排除是统计办法的影响。

3.7 小结一下
为了实现不录制主播端的评论挂件,咱们从小游戏渲染流程动手,借助于 Surface 跨过程渲染和传输图像的能力,把小游戏渲染上屏的过程移到了主过程,并同时生成纹理进行推流,在兼容性和性能上达到了要求。

4、音频采集推流

4.1 计划抉择
在音频采集计划中,咱们留神到在 Android 10 及以上零碎提供了 AudioPlaybackCapture 计划容许咱们在肯定的限度内对系统音频进行采集。过后预研的一些论断如下。

捕捉方 – 进行捕捉的条件:

1)Android 10(api 29)及以上;
2)获取了 RECORD_AUDIO 权限;
3)通过 MediaProjectionManager.createScreenCaptureIntent()进行 MediaProjection 权限的申请(和 MediaProjection 录屏共用);
4)通过 AudioPlaybackCaptureConfiguration.addMatchingUsage()/AudioPlaybackCaptureConfiguration.excludeUsage() 增加 / 排除要捕捉的 MEDIA 类型;
5)通过 AudioPlaybackCaptureConfiguration.addMatchingUid() /AudioPlaybackCaptureConfiguration.excludeUid()增加 / 排除能够捕捉的利用的 UID。
被捕捉方 – 能够被捕捉的条件:

1)Player 的 AudioAttributes 设置的 Usage 为 USAGE_UNKNOWN,USAGE_GAME 或 USAGE_MEDIA(目前绝大部分用的都是默认值,能够被捕捉);
2)利用的 CapturePolicy 被设置为 AudioAttributes#ALLOW_CAPTURE_BY_ALL,有三种方法能够设置(以最严格的为准,目前微信内没有配置,默认为能够捕捉);
3)通过 manifest.xml 设置 android:allowAudioPlaybackCapture=”true”,其中,TargetApi 为 29 及以上的利用默认为 true,否则为 false;
4)api 29 及以上能够通过 setAllowedCapturePolicy 办法运行时设置;
5)api 29 及以上能够通过 AudioAttributes 针对每一个 Player 独自设置。
总的来说:Android 10 及以上能够应用 AudioPlaybackCapture 计划进行音频捕捉,但思考到 Android 10 这个零碎版本限度过高,最终咱们抉择了本人来采集并混合小游戏内播放的所有音频。

4.2 跨过程音频数据传输
当初,老问题又摆在了咱们眼前:小游戏混合后的音频数据在小游戏过程,而咱们须要把数据传输到主过程进行推流。

与个别的 IPC 跨过程通信用于办法调用不同:在这个场景下,咱们须要频繁地(40 毫秒一次)传输较大的数据块(16 毫秒内的数据量在 8k 左右)。

同时:因为直播的个性,这个跨过程传输过程的提早须要尽可能地低,否则就会呈现音画不同步的状况。

为了达到上述指标:咱们对 Binder、LocalSocket、MMKV、SharedMemory、Pipe 这几种 IPC 计划进行了测试。在搭建的测试环境中,咱们在小游戏过程模仿实在的音频传输的过程,每隔 16 毫秒发送一次序列化后的数据对象,数据对象大小分为 3k/4M/10M 三挡,在发送前贮存工夫戳在对象中;在主过程中接管到数据并实现反序列化为数据对象的时刻作为完结工夫,计算传输提早。

最终失去了如下后果:

注:其中 XIPCInvoker(Binder)和 MMKV 在传输较大数据量时耗时过长,不在后果中展现。

对于各个计划的剖析如下(卡顿率示意提早 >2 倍均匀提早且 >10 毫秒的数据占总数的比例):

能够看到:LocalSocket 计划在各个状况下的传输提早体现都极为优异。差别的起因次要是因为裸二进制数据在跨过程传输到主过程后,仍须要进行一次数据拷贝操作来反序列化为数据对象,而应用 LocalSocket 时能够借助于 ObjectStream 和 Serializeable 来实现流式的拷贝,相比与其余计划的一次性接收数据后再拷贝节约了大量的工夫(当然其余计划也能够设计成分块流式传输同时拷贝,但实现起来有肯定老本,不如 ObjectStream 稳固易用)。
咱们也对 LocalSocket 进行了兼容性与性能测试,未呈现不能传输或断开连接的状况,仅在三星 S6 上均匀提早超过了 10 毫秒,其余机型提早均在 1 毫秒左右,能够满足咱们的预期。

4.3 LocalSocket 的安全性
罕用的 Binder 的跨过程安全性有零碎实现的鉴权机制来保障,LocalSocket 作为 Unix domain socket 的封装,咱们必须思考它的安全性问题。

论文《The Misuse of Android Unix Domain Sockets and Security Implications》较为具体地剖析了 Android 中应用 LocalSocket 所带来的平安危险。

PS:论文原文附件下载(请从此链接的 4.3 节处下载:http://www.52im.net/thread-35…)

总结论文所述:因为 LocalSocket 自身不足鉴权机制,任意一个利用都能够进行连贯,从而截取到数据或是向接收端传递非法数据引发异样。

针对这个特点,咱们能够做的进攻办法有两种:

1)随机化 LocalSocket 的命名,例如应用以后直播的小游戏的 AppId 和用户 uin 等信息计算 md5 作为 LocalSocket 的名字,使得攻击者无奈通过固定或穷举名字的办法尝试建设连贯;
2)引入鉴权机制,在连贯胜利后发送特定的随机信息来验证对方的真实性,而后才启动真正的数据传输。
4.4 小结一下
为了兼容 Android 10 以下的机型也能直播,咱们抉择本人解决小游戏音频的采集,并通过比照评测,选用了 LocalSocket 作为跨过程音频数据传输的计划,在提早上满足了直播的需要。

同时,通过一些反抗措施,能够无效躲避 LocalSocket 的平安危险。

5、多过程带来的问题

回头来看,尽管整个计划看起来比拟通顺,然而在实现的过程中还是因为多过程的起因踩过不少坑,上面就分享其中两个比拟次要的。

5.1 glFinish 造成渲染推流帧率重大降落
在刚实现跨过程渲染推流的计划后,咱们进行了一轮性能与兼容性测试,在测试中发现,局部中低端机型上帧率降落十分重大(如下图所示)。

复现后查看小游戏过程渲染的帧率(即小游戏过程绘制到跨过程而来的 Surface 上的帧率)发现能够达到不开直播时的帧率。

而咱们所用的测试软件 PerfDog 所记录的是在屏 Surface 的绘制帧率,这就阐明性能降落不是直播开销过高引起的小游戏代码执行效率降落,而是主过程上屏 Renderer 效率太低。

于是咱们对主过程直播时运行效率进行了 Profile,发现耗时函数为 glFinish。

并且有两次调用:

1)第一次调用是 Renderer 将内部纹理转 2D 纹理时,耗时会达到 100 多毫秒;
2)第二次调用是腾讯云直播 SDK 外部,耗时 10 毫秒以内。
如果将第一次调用去掉,直播 SDK 外部的这次则会耗时 100 多毫秒。

为了弄清为什么这个 GL 指令耗时这么久,咱们先看看它的形容:

glFinish does not return until the effects of all previously called GL commands are complete.

形容很简略:它会阻塞直到之前调用的所有 GL 指令全副实现。

这么看来是之前的 GL 指令太多了?然而 GL 指令队列是以线程为维度隔离的,在主过程的 Renderer 线程中,glFinish 前只会执行纹理类型转换的十分大量的 GL 指令,和腾讯云的同学理解到推流接口也不会在本线程执行很多 GL 指令,如此大量的 GL 指令怎么会使 glFinish 阻塞这么久呢?等等,大量 GL 指令?小游戏过程此时不就正在执行大量 GL 指令吗,难道是小游戏过程的大量 GL 指令导致了主过程的 glFinsih 耗时过长?

这样的猜想不无道理:尽管 GL 指令队列是按线程隔离的,但解决指令的 GPU 只有一个,一个过程的 GL 指令过多导致另一个过程在须要 glFinish 时阻塞过久。Google 了一圈没找到有相干的形容,须要本人验证这个猜想。

从新察看一遍下面的测试数据:发现直播前能达到 60 帧的状况下,直播后也能达到 60 帧左右,这是不是就阐明在小游戏的 GPU 负载较低时 glFinish 的耗时也会降落呢?

在性能降落重大的机型上:管制其余变量不变尝试运行低负载的小游戏,发现 glFinsih 的耗时胜利降落到了 10 毫秒左右,这就印证了下面的猜想——的确是小游戏过程正在执行的大量 GL 指令阻塞了主过程 glFinish 的执行。

该如何解决呢?小游戏过程的高负载无奈扭转,那能让小游戏在一帧渲染实现当前停住等主过程的 glFinish 实现后再渲染下一帧吗?

这里通过了各种尝试:OpenGL 的 glFence 同步机制无奈跨过程应用;因为 GL 指令是异步执行的,通过跨过程通信加锁锁住小游戏的 GL 线程并不能保障主过程执行 glFinish 时小游戏过程的指令曾经执行完,而能保障这点只有通过给小游戏过程加上 glFinish,但这会使得双缓冲机制生效,导致小游戏渲染帧率的大幅降落。

既然 glFinish 所带来的阻塞无奈防止,那咱们回到问题的开始:为什么须要 glFinish?因为双缓冲机制的存在,一般来说并不需要 glFinish 来期待之前的绘制实现,否则双缓冲就失去了意义。两次 glFinish 中,第一次纹理解决的调用能够间接去掉,第二次腾讯云 SDK 的调用通过沟通,发现是为了解决一个历史问题引入的,能够尝试去掉。在腾讯云同学的帮忙下,去掉 glFinish 后,渲染的帧率终于和小游戏输入的帧率统一,通过兼容性和性能测试,没有发现去掉 glFinish 带来的问题。

这个问题最终的解法很简略:但剖析问题起因的过程实际上做了十分多的试验,同一个利用中一个高 GPU 负载的过程会影响到另一个过程的 glFinish 耗时的这种场景的确也十分少见,能参考的材料不多。这个过程也让我粗浅领会到了 glFinish 使得双缓冲机制生效所带来的性能影响是微小的,在应用 OpenGL 进行渲染绘制时对于 glFinish 的应用该当十分审慎。

5.2 后盾过程优先级问题
在测试过程中:咱们发现无论以多少的帧率向直播 SDK 发送画面,观众端看到的画面帧率始终只有 16 帧左右,排除后盾起因后,发现是编码器编码的帧率有余导致的。经腾讯云同学测试同过程内编码的帧率是能够达到设定的 30 帧的,那么阐明还是多过程带来的问题,这里编码是一个十分重的操作,须要耗费比拟多的 CPU 资源,所以咱们首先狐疑的就是后盾过程优先级的问题。

为了确认问题:

1)咱们找来了曾经 root 的手机,通过 chrt 命令进步编码线程的优先级,观众端帧率立马上到了 25 帧;
2)另一方面,经测试如果在小游戏过程上显示一个主过程的浮窗(使主过程具备前台优先级),帧率能够上到 30 帧。
综上:能够确认帧率降落就是因为后盾过程(以及其领有的线程)的优先级过低导致的。

进步线程优先级的做法在微信里比拟常见,例如:小程序的 JS 线程以及小游戏的渲染线程都会在运行时通过 android.os.Process.setThreadPriority 办法设置线程的优先级。腾讯云 SDK 的同学很快提供了接口供咱们设置线程优先级,但当咱们真正运行起来时,却发现编码的帧率仅从 16 帧进步到了 18 帧左右,是哪里出问题了呢?

后面提到:咱们通过 chrt 命令设置线程优先级是无效的,但 android.os.Process.setThreadPriority 这个办法设置的线程优先级对应的是 renice 这个命令设置的 nice 值。仔细阅读 chrt 的 manual 后,发现之前测试时的了解有误,之前间接用 chrt -p [pid] [priority]的命令设置优先级,却没有设置调度策略这个参数,导致该线程的调度策略从 Linux 默认的 SCHED_OTHER 改为了命令缺省设置的 SCHED_RR,而 SCHED_RR 是一种“实时策略”,导致线程的调度优先级变得十分高。

实际上:通过 renice(也就是 android.os.Process.setThreadPriority)设置的线程优先级,对于后盾过程所领有线程来说没有太大的帮忙。

其实早有人解释过这一点:

To address this, Android also uses Linux cgroups in a simple way to create more strict foreground vs. background scheduling. The foreground/default cgroup allows thread scheduling as normal. The background cgroup however applies a limit of only some small percent of the total CPU time being available to all threads in that cgroup. Thus if that percentage is 5% and you have 10 background threads all wanting to run and one foreground thread, the 10 background threads together can only take at most 5% of the available CPU cycles from the foreground. (Of course if no foreground thread wants to run, the background threads can use all of the available CPU cycles.)

对于线程优先级的设置,感兴趣的同学能够看看另一位大佬的文章:《Android 的离奇陷阱 — 设置线程优先级导致的微信卡顿惨案》。

最终:为了进步编码帧率并避免后盾主过程被杀,咱们最终还是决定直播时在主过程创立一个前台 Service。

6、总结与瞻望

多过程是一把双刃剑,在给咱们带来隔离性和性能劣势的同时也带来了跨过程通信这一难题,所幸借助零碎 Surface 的能力和多种多样的跨过程计划能够较好地解决小游戏直播中所遇到的问题。

当然:解决跨过程问题最好的计划是防止跨过程,咱们也思考了将视频号直播的推流模块运行在小游戏过程的计划,但出于革新老本的思考而没有抉择这一计划。

同时:这次对于 SurfaceView 跨过程渲染的实际也对其余业务有肯定参考价值——对于一些内存压力较大或是平安危险较高,又须要进行 SurfaceView 渲染绘制的场景,能够把逻辑放到独立的过程,再通过跨过程渲染的形式绘制到主过程的 View 上,在取得独立过程劣势的同时又防止了过程间跳转所带来的体验的割裂。

附录 1:无关直播技术的文章汇总

《挪动端实时音视频直播技术详解(一):开篇》
《挪动端实时音视频直播技术详解(二):采集》
《挪动端实时音视频直播技术详解(三):解决》
《挪动端实时音视频直播技术详解(四):编码和封装》
《挪动端实时音视频直播技术详解(五):推流和传输》
《挪动端实时音视频直播技术详解(六):提早优化》
《实践联系实际:实现一个简略地基于 html]5 的实时视频直播》
《实时视频直播客户端技术盘点:Native、html]5、WebRTC、微信小程序》
《Android 直播入门实际:入手搭建一套简略的直播零碎》
《淘宝直播技术干货:高清、低延时的实时视频直播技术解密》
《技术干货:实时视频直播首屏耗时 400ms 内的优化实际》
《新浪微博技术分享:微博实时直播答题的百万高并发架构实际》
《实时音频的混音在视频直播中的技术原理和实际总结》
《七牛云技术分享:应用 QUIC 协定实现实时视频直播 0 卡顿!》
《近期大热的实时直播答题零碎的实现思路与技术难点分享》
《P2P 技术如何将实时视频直播带宽升高 75%?》
《网易云信实时视频直播在 TCP 数据传输层的一些优化思路》
《首次披露:快手是如何做到百万观众同场看直播仍能秒开且不卡顿的?》
《浅谈实时音视频直播中间接影响用户体验的几项要害技术指标》
《技术揭秘:反对百万级粉丝互动的 Facebook 实时视频直播》
《挪动端实时视频直播技术实际:如何做到实时秒开、晦涩不卡》
《实现提早低于 500 毫秒的 1080P 实时音视频直播的实际分享》
《浅谈开实时视频直播平台的技术要点》
《直播零碎聊天技术 (一):百万在线的美拍直播弹幕零碎的实时推送技术实际之路》
《直播系聊天技术(二) 阿里电商 IM 音讯平台,在群聊、直播场景下的技术实际》
《直播零碎聊天技术(三):微信直播聊天室单房间 1500 万在线的音讯架构演进之路》
《直播零碎聊天技术(四):百度直播的海量用户实时音讯零碎架构演进实际》
《直播零碎聊天技术(五):微信小游戏直播在 Android 端的跨过程渲染推流实际》
《海量实时音讯的视频直播零碎架构演进之路(视频 +PPT)[附件下载]》
《YY 直播在挪动弱网环境下的深度优化实际分享(视频 +PPT)[附件下载]》
《从 0 到 1:万人在线的实时音视频直播技术实际分享(视频 +PPT) [附件下载]》
《在线音视频直播室服务端架构最佳实际(视频 +PPT) [附件下载]》

更多同类文章 ……

附录 2:微信团队分享的技术文章汇总

《微信朋友圈千亿访问量背地的技术挑战和实际总结》
《微信团队分享:微信挪动端的全文检索多音字问题解决方案》
《微信团队分享:iOS 版微信的高性能通用 key-value 组件技术实际》
《微信团队分享:iOS 版微信是如何避免特殊字符导致的炸群、APP 解体的?》
《微信团队原创分享:iOS 版微信的内存监控零碎技术实际》
《iOS 后盾唤醒实战:微信收款到账语音揭示技术总结》
微信团队分享:视频图像的超分辨率技术原理和利用场景》
《微信团队分享:微信每日亿次实时音视频聊天背地的技术解密》
《微信团队分享:微信 Android 版小视频编码填过的那些坑》
《微信手机端的本地数据全文检索优化之路》
《企业微信客户端中组织架构数据的同步更新计划优化实战》
《微信团队披露:微信界面卡死超级 bug“15。。。。”的前因后果》
《月活 8.89 亿的超级 IM 微信是如何进行 Android 端兼容测试的》
《一篇文章 get 微信开源挪动端数据库组件 WCDB 的所有!》
《微信客户端团队负责人技术访谈:如何着手客户端性能监控和优化》
《微信后盾基于工夫序的海量数据冷热分级架构设计实际》
《微信团队原创分享:Android 版微信的臃肿之困与模块化实际之路》
《微信后盾团队:微信后盾异步音讯队列的优化降级实际分享》
《微信团队原创分享:微信客户端 SQLite 数据库损坏修复实际》
《微信 Mars:微信外部正在应用的网络层封装库,行将开源》
《如约而至:微信自用的挪动端 IM 网络层跨平台组件库 Mars 已正式开源》
《开源 libo 库:单机千万连贯、撑持微信 8 亿用户的后盾框架基石 [源码下载]》
《微信新一代通信安全解决方案:基于 TLS1.3 的 MMTLS 详解》
《微信团队原创分享:Android 版微信后盾保活实战分享 (过程保活篇)》
《微信团队原创分享:Android 版微信后盾保活实战分享(网络保活篇)》
《Android 版微信从 300KB 到 30MB 的技术演进(PPT 讲稿) [附件下载]》
《微信团队原创分享:Android 版微信从 300KB 到 30MB 的技术演进》
《微信技术总监谈架构:微信之道——大道至简(演讲全文)》
《微信技术总监谈架构:微信之道——大道至简(PPT 讲稿) [附件下载]》
《如何解读《微信技术总监谈架构:微信之道——大道至简》》
《微信海量用户背地的后盾零碎存储架构(视频 +PPT) [附件下载]》
《微信异步化革新实际:8 亿月活、单机千万连贯背地的后盾解决方案》
《微信朋友圈海量技术之道 PPT [附件下载]》
《微信对网络影响的技术试验及剖析(论文全文)》
《一份微信后盾技术架构的总结性笔记》
《架构之道:3 个程序员成就微信朋友圈日均 10 亿发布量[有视频]》
《疾速裂变:见证微信弱小后盾架构从 0 到 1 的演进历程(一)》
《疾速裂变:见证微信弱小后盾架构从 0 到 1 的演进历程(二)》
《微信团队原创分享:Android 内存透露监控和优化技巧总结》
《全面总结 iOS 版微信降级 iOS9 遇到的各种“坑”》
《微信团队原创资源混同工具:让你的 APK 立减 1M》
《微信团队原创 Android 资源混同工具:AndResGuard [有源码]》
《Android 版微信安装包“减肥”实战记录》
《iOS 版微信安装包“减肥”实战记录》
《挪动端 IM 实际:iOS 版微信界面卡顿监测计划》
《微信“红包照片”背地的技术难题》
《挪动端 IM 实际:iOS 版微信小视频性能技术计划实录》
《挪动端 IM 实际:Android 版微信如何大幅晋升交互性能(一)》
《挪动端 IM 实际:Android 版微信如何大幅晋升交互性能(二)》
《挪动端 IM 实际:实现 Android 版微信的智能心跳机制》
《挪动端 IM 实际:WhatsApp、Line、微信的心跳策略剖析》
《挪动端 IM 实际:谷歌音讯推送服务(GCM) 钻研(来自微信)》
《挪动端 IM 实际:iOS 版微信的多设施字体适配计划探讨》
《IPv6 技术详解:基本概念、利用现状、技术实际(上篇)》
《IPv6 技术详解:基本概念、利用现状、技术实际(下篇)》
《微信多媒体团队访谈:音视频开发的学习、微信的音视频技术和挑战等》
《腾讯技术分享:微信小程序音视频技术背地的故事》
《腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面》
《微信多媒体团队梁俊斌访谈:聊一聊我所理解的音视频技术》
《腾讯音视频实验室:应用 AI 黑科技实现超低码率的高清实时视频聊天》
《腾讯技术分享:微信小程序音视频与 WebRTC 互通的技术思路和实际》
《手把手教你读取 Android 版微信和手 Q 的聊天记录(仅作技术钻研学习)》
《微信技术分享:微信的海量 IM 聊天音讯序列号生成实际(算法原理篇)》
《微信技术分享:微信的海量 IM 聊天音讯序列号生成实际(容灾计划篇)》
《腾讯技术分享:GIF 动图技术详解及手机 QQ 动静表情压缩技术实际》
《微信团队分享:Kotlin 渐被认可,Android 版微信的技术尝鲜之旅》
《社交软件红包技术解密(二):解密微信摇一摇红包从 0 到 1 的技术演进》
《社交软件红包技术解密(三):微信摇一摇红包雨背地的技术细节》
《社交软件红包技术解密(四):微信红包零碎是如何应答高并发的》
《社交软件红包技术解密(五):微信红包零碎是如何实现高可用性的》
《社交软件红包技术解密(六):微信红包零碎的存储层架构演进实际》
《社交软件红包技术解密(十一):解密微信红包随机算法(含代码实现)》
《微信团队分享:极致优化,iOS 版微信编译速度 3 倍晋升的实际总结》
《IM“扫一扫”性能很好做?看看微信“扫一扫识物”的残缺技术实现》
《微信团队分享:微信领取代码重构带来的挪动端软件架构上的思考》
《IM 开发宝典:史上最全,微信各种性能参数和逻辑规定材料汇总》
《微信团队分享:微信直播聊天室单房间 1500 万在线的音讯架构演进之路》

更多同类文章 ……
(本文同步公布于:http://www.52im.net/thread-35…)

退出移动版