吃鸡决赛圈直播却卡屏的我心好痛,立马找来开发刚了一波

41次阅读

共计 3495 个字符,预计需要花费 9 分钟才能阅读完成。

欢迎大家前往腾讯云 + 社区,获取更多腾讯海量技术实践干货哦~
本文由腾讯云视频发表于云 + 社区专栏

关注公众号“腾讯云视频”,一键获取 技术干货 | 优惠活动 | 视频方案
本是一名佛性型吃鸡选手,自从被三个妹子带着躺尸吃鸡之后,便立志要成为一名吃鸡高手,一大早便沉迷于各大网站的吃鸡直播中,正看到决赛圈激动人心的时刻,直播花屏了?然后游戏结束了?我的天,我是谁?我在哪?我错过了什么?
作为一名有强迫症的 IT 小哥哥,怎能让直播花屏现象存在呢?一方面,为了自己能成为一名吃鸡高手。另一方面,不能错过每一个升职加薪的机会。就这样开始了一段漫长的长征之路……
对于直播业务,” 秒开、卡顿、时延、进房成功率 ” 是我们经常关注的几个指标,这些指标可以说是从 ” 一个用户能够优雅地进入直播间 ” 的角度来考量的,然而进入直播间后 ” 用户究竟看到的什么内容 ” 也是很关键的一环,内容上除了涉及安全的一些指标外,还可能会有内容是否有花屏、绿屏等其他异常内容,这时我们便会考虑如何衡量和发现外网的花屏情况。
本文主要针对花屏提出了一种基于 CNN 网络的检测方案。
01
花屏检测能力构建
无论是视频还是直播,都是由一帧帧图像组成的,之所以会以一种动态的形式展现到我们眼前,是因为了人类的视觉暂留现象。
物体在快速运动时, 当人眼所看到的影像消失后,人眼仍能继续保留其影像 0.1-0.4 秒左右的图像,这种现象被称为视觉暂留现象。
既然如此,检测直播中是否存在花屏,其实可以转换为检测直播中的帧画面是否是花屏的画面,即一个图像识别问题。那么如何识别一个图像是否是花屏呢?
通常图像识别总是以特征为基础的,我们会先根据所设定的目标来提取相应的特征,用于我们后面来制定策略。不过好在现在的深度学习卷积神经网络 CNN 将提取特征和制定决策策略都帮我们完成了。
而使用深度学习 CNN 网络则绕不开数据集和模型训练两大块
1.1 数据集准备
困难
要使用深度学习网络,一个门槛是需要足够的带有标签的数据集,否则学习出的网络很容易过拟合,从而泛化能力不强。说其是门槛是因为实际业务中更多情况是缺少数据集,就以现在的花屏为例,目前直播发生花屏的案例非常少,想要通过实际案例来收集足够的花屏图片作为训练集显得异常困难。因此必须探寻其他的路子来收集训练集。
人类之所以能够分辨出花屏,是因为人类眼睛能够找到花屏图像的特征,虽然这些特征我们可能用语言都描述不出来,事实上,如果我们能用语言描述出特征,我们也很容易将其翻译成代码来找到花屏图像的特征。
制作训练集
机器学习其实也是通过特征来工作的,既然如此,我们可以制作一些花屏图像出来,让 CNN 网络找到它们区别于正常图片的特征,从而学习到花屏图片的检测能力。
在使用 YUVviewer 工具时,发现当设置错误的分辨率来播放视频文件时会出现花屏情况。灵感来源于此,我们完全可以通过使用错误的分辨率从 YUV 文件中抽取帧,从而拿到花屏图片。整体流程如下:

这里需要了解 YUV 文件的存储格式,从而根据格式来进行抽取对应的帧:
YUV,分为三个分量,“Y”表示明亮度(Luminance 或 Luma),也就是灰度值;而“U”和“V”表示的则是色度(Chrominance 或 Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
YUV 采样样式有一下几种,以黑点表示采样该像素点的 Y 分量,以空心圆圈表示采用该像素点的 UV 分量,一般情况下我们都使用的是 YUV420 格式

YUV420 格式存储方式如下所示:

按照上面存储方式编写代码来提取帧,代码如下:
def get_frames_from_YUV(filename, dims, numfrm, startfrm, frmstep):
“””
从给定的 YUV 文件中抽取对应的帧数据,帧数据格式仍然为 YUV

:param filename: YUV 文件路径
:param dims: YUV 文件的分辨率
:param numfrm: 要提取帧的数量
:param startfrm: 从哪一帧开始提取
:param frmstep: 抽取帧的帧间隔,即每隔几帧抽一帧
:return: 返回抽取帧的 Y 列表,U 列表,V 列表
“””
filesize = os.path.getsize(filename)
fp = open(filename, ‘rb’)
blk_size = prod(dims) * 3 / 2 # 计算每帧大小
if (startfrm+1+(numfrm-1)*frmstep)*blk_size > filesize:
numfrm = (filesize/blk_size – 1 – startfrm)/frmstep +1
util.log(‘ 文件读取越界 – 修改为 %d’%numfrm)
fp.seek(blk_size * startfrm, 0) # 跳转到指定开始帧
Y, U, V= [],[],[]
d00 = dims[0] / 2
d01 = dims[1] / 2
for i in range(numfrm):
util.log(‘ 文件读取第 %d 帧 ’ % i)
Yt = zeros((dims[1], dims[0]), uint8, ‘C’)
Ut = zeros((d01, d00), uint8, ‘C’)
Vt = zeros((d01, d00), uint8, ‘C’)
for m in range(dims[1]):
for n in range(dims[0]):
# print m,n
Yt[m, n] = ord(fp.read(1))
for m in range(d01):
for n in range(d00):
Ut[m, n] = ord(fp.read(1))
for m in range(d01):
for n in range(d00):
Vt[m, n] = ord(fp.read(1))
Y = Y + [Yt]
U = U + [Ut]
V = V + [Vt]
fp.seek(blk_size * (frmstep – 1), 1) # 跳出间隔帧
fp.close()
return (Y, U, V)
这里对分辨率错误的多种情况也做了下研究,发现如下规律:
1)分辨率正确

2)分辨率 width+ 1 情况

3)分辨率 width+ n 情况

4)分辨率 width- 1 情况

5)分辨率 width- n 情况

上面只是针对图片宽来进行错误干扰,可以看出宽变小花屏条纹方向是左下的,宽变大花屏条纹方向时右下的。
所以我们队宽和高分别设置不同的错误值,会造成不同类型的花屏,于是可以用这种策略构造大量的花屏。
我们用 800 多个视频,每个视频以一定的间隔来抽 10 帧,获得了 8000 多张花屏图片。

这些图片标签为花屏,也就是我们的正样本,负样本可选取实际直播中的正常截图。
至此,数据集准备差不多了。
1.2 模型和训练
模型上使用网上一些知名模型即可,这里我们使用了轻量的 mobilenet 模型,模型结构如下图所示:

训练采用基于用 imagenet 已经训练好的模型来进行 finetune 训练,最后一层使用随机超参数来训练(这一层也无法读取 pretrained 模型的超参数,因为分类数不一致)。训练可以快速收敛,因为特征太明显了,而且测试集准确率很高。
其实这里训练是一个不断迭代的过程,因为机器学习模型是一张白纸,它要具有怎样的能力完全是你教它的,而教的方式就是通过训练集(数据和标签),而想要让它能够应对更多的情况,你的训练集就要尽可能涵盖各种情况。
而我们的训练集总是不足的,你总会有 care 不到的地方。训练集不足的情况会怎样?举个例子
你训练个识别飞机的模型,而大部分关于飞机的图片都有天空,这样你给张天空的图片到模型,它也可能会认为是飞机,因为其实模型很可能学到的是天空的特征。而怎么让模型学到飞机的特征呢,当然需要调整训练集,让训练集里不仅包含背景为天空的飞机,还有陆地上的飞机等等。
通过不断低迭代调优,我们在空间场景下检测准确率已经可以达到 94%,NOW 直播场景检测准确率也已达到 90%。
02
直播检测方案
检测能力具备后想要真正地接入直播业务,还需要将直播流进行分帧,然后把对应的帧图片进行花屏检测。
后台整体框架
采用分帧截屏的手段,如果每天需要检测 2000 万张截图,即 10s 会有一张截图需要检测,而考虑花屏总是出现在很长的一段时间内,因此这里希望能够以更长的时间来抽样从而避免浪费算力。

附一张目前业务检测花屏结果的截图:

作为一名热爱工作的 IT 小哥哥,花了一个星期的时间,总算把基于 CNN 网络的直播花屏检测的工作告一段落了。
工作使我开心,游戏使我快乐,终于可以再次流畅的游走在各大网址的吃鸡直播中啦~

问答游戏体系结构相关阅读团战开黑必备“良药”了解一下!再也不用担心网吧开黑队友听不清了!3 行代码,为 QQ 轻游戏加上语音互动能力【每日课程推荐】机器学习实战!快速入门在线广告业务及 CTR 相应知识

正文完
 0