移动测试开发 视频流画质检测的自动化测试探索
一、背景
在媒体处理过程中,直播视频源经过媒体服务转码后,需要拉流校验转码后视频画面。考虑接入自动化检测方式进行输出画面的画质检测,弥补人工校验易受环境干扰无法逐帧或逐画面校验的问题。
二、核心流程
媒体处理针对直播转码过程的一次用例任务执行过程大致如下:
第一步:获取直播源流,经媒体服务转码后推至 CDN,形成拉流地址,用户拉取转码后的拉流地址观看视频:
1.视频源转推至 CDN,对于媒体服务而言是一个一个独立的转码任务,每个任务处理时长有上层业务传参控制。任务处理过程中需要实时监测任务的处理状态直至任务结束,此为检测主流程,每条用例都按此流程执行。
2.典型的视频源分为:直播流和点播流
●直播源即源是视频流,典型特征是具有时效性,过期即无用,一般无法复用业务给的源流地址,需要使用 ffmpeg 或其他工具本地转推形成直播流(本地转推过程作为独立的进程,应不阻塞主流程执行过程)
●点播源即源是视频文件(如 mp4、ts 等),一般放在远端服务器上,可以直接访问。
3.任务处理过程中使用本地 FFplay 拉流播放校验过程,也需要作为独立的进程单独进行,不阻塞主流程执行过程
第二步:图片采集形成待检图片序列
第三步:获取截图图片,进行花屏、黑屏画质检测
以上流程中,第一步属于常规自动化测试流程,这里不进行扩展说明。第二、三步属于画质检测特有流程,下文针对此进行具体说明。
三、画质检测流程
目前画质检测方案是:针对视频源(转码后的源)进行分帧截图,形成图片序列,然后接入我司开测平台的画质检测服务,针对不同的图片进行画面花屏、黑屏检测。涉及图像采集 - 图像检测 - 图像存储几个方面。
图像采集
画质检测前提需要现有图片,即图像采集过程。图像采集过程基于 CDN 侧形成的视频流(拉流端),采集起点应该是拉流播放起始时间点。
项目初期考虑直接使用 ffmpeg 媒体库进行截图:
在应用过程中上述截图方式会受业务流程影响:业务流程中的直播转推过程基于 ffmpeg 库实现,通过独立进程进行(下图为 ffmpeg 推流命令):
为保证每个用例执行的独立性,在用例执行开始和结束时都会 kill 系统中 ffmpeg 进程,同时会 kill 用于图像采集的 ffmpeg 进程,导致图像采集过程中断(用例执行过程中很可能出现主流程执行完成,但采集或质检过程仍在继续现象)。
基于上述考虑,图像采集过程最终通过引入 OpenCV 图像库实现:
画质检测接入
整个画质检测过程对接的是我司开测平台服务,通过 API 对接方式引入。图片需要 base64 编码后传入,编码方式基于 URLSafe 模式:
远端 S3 存储共享
采集后的图片序列逐一进行画质检测后,形成一组花屏及图像打分检测结果序列,结果需要收录至测试报告。对于测试报告:
●html 测试报告一般需要分享给研发或项目组人员,支持远程查看;
●测试报告中收集的质检结果应与视频流中的图片序列进行一一对应,需要反馈待解图片地址,用于图片源追溯或问题图片的主观核对。
从而引入问题:采集的或用于质检的图片一般存储在本地,测试报告远程查看时无法访问,导致无法追溯或核对。针对此现象,考虑将图片存储至公司 S3 环境,便于远程访问。S3 地址获取过程涉及 bucket 和文件路径(关于 bucket 涉及用户隐私及权限问题,不进行展开)。
至此,画质检测过程接入媒体服务转码测试工程基本流程走通;为保障画质检测不影响主流程执行过程,图像采集及画质检测均采用了线程方案。但在实际用例执行过程中还会出现质检过程获取不到、质检过程慢等问题,需要进一步优化处理。
测试报告展示
html 报告会直接将控制台 print 打印都代入到测试报告用例详情中,为方便查看质检结果,将视频源 - 图片地址 - 质检结果 - 质检耗时等关联展示,实现过程是直接在项目代码中使用
标签进行表格嵌入 (需要准备对应的表格模板)。最终测试报告展示效果如下:画质检测效率优化
线程回调获取画质检测结果
一张图片调用质检服务的检测时间大概如下:
●29s~5 张图片,平均耗时 5.8s/张
♢图像采集耗时:3.5s,平均耗时 0.7s/张
♢质量检测耗时:25.5s,平均耗时 5.1s/张
以典型的一转一(一路输入流,一路输出流)业务场景为例,直播任务时长 t=30s,帧率 frame=15,共计会产生 450 张图片。按每 frame 帧采集一张图片 (确保每一个画面都有采样),共计采集 30 张图片,画质检测耗时约为 30*5.8s=174s
基于此,当用例主流程执行完成时,质检过程仍在继续执行中,但主流程需要回收质检结果,故需要等待质检执行完成才能终止当前用例的执行过程,对应主线程等待子线程执行结果,故在启动质检线程后,增加 thread.join() 阻塞主线程。
上文提到,图片质检过程结果需要反馈给主流程,但图片质检过程在线程中进行,故需要线程回调。这里通过重构 threading.Thread 类实现:
主流程中通过 thread.get_result() 结果获取质检结果:
多线程优化画质检测效率
针对上述质检过程慢现象,考虑每张图片处理过程独立进行,可以将画质检测过程分摊在多个线程中进行,以此提高质检速度。
确定线程数量
对于图像采集过程,采集图像数量一是取决于任务时长,二是取决于转码任务中包含的输入、输出流的数量:
媒体服务转码过程按视频流数量分为一转一、一转多、多转一、多转多应用场景:
① 一转一场景:一个转码任务中包含一路输入流,一路输出流,对应一路推流进程和一路拉流进程;
② 一转多场景:一个转码任务包含一路输入流,多路输出流,对应一路推流进程和多路拉流进程;
③ 多转一场景:一个转码任务包含多路输入流,一路输出流,对应多路推流进程和一路拉流进程;
④ 多转多场景:一个转码任务包含多路输入流,多路输出流,对应多路推流进程和多路拉流进程。
采集过程基于视频输出路数,由上知,采集过程相对较快,一路视频采用一个线程即可满足:
对于画质检测过程,以上文 30s 转码任务时长质检耗时为基准,每个线程处理图片数量按 10 张计算 (数据根据当前系统环境及实际测试效果得到),基于此,质检过程启动的线程数量=图片数量/10+1。
检测方案优化
确定采集和检测的线程数量后,根据数据处理的顺序可以分为:先采集 - 后检测和边采集 - 边检测两种方案。
图像采集 - 质检过程共享图片数据,属于典型的生产者 - 消费者模型线程案例,可以将采集的图片放在全局队列(实际应用中,接口存在跨多个文件或模块,全局变量使用易受限制,后将队列转为入参传递),质检过程从队列中取出图片数据进行处理。利用队列的 “先进先出” 特性解决多线程数据同步问题。
先采集 - 后检测方案
先采集后检测方案即等待图像采集完成后再启动画质检测过程,无需考虑队列是否为空场景。先采集 - 后检测方案采用多线程优化前后的质检效率对比如下:
从上结果,按主流程 30s 任务时长,单线程耗时 5.8s*30=114s,主流程阻塞过程过长;多线程耗时 3.8s*10=38s,比主流程耗时稍长,需要主流程等待一段时间。
边采集 - 边检测方案
基于队列 + 多线程方式搭建的 “生产者 - 消费者” 模型可以很方便的实现边采集 - 边检测过程。但画质检测过程需要考虑队列为空场景,防止取不到图片情况:
边采集 - 后检测方案采用多线程优化后的质检效率对比如下(主流程按 30s 任务时长,质检时长为 2.8s*10=28s,比主流程耗时略短,符合预期)。
综上,通过多线程方式实现了画质检测的效率优化,对比单线程质检效率提升 21%;通过队列 + 多线程方式搭建的 “生产者 - 消费者” 模型可以快速实现边采集 - 边质检过程,将采集过程耗时直接降至 0s,进一步提高了检测效率(对比单线程检测效率提升 42%),且随着转码任务时长增加,效率提升更加明显。
总结
本文通过引入画质检测自动化检测方案解决人工检测的问题并进行了工程化落地实践。针对实际测试中遇到的检测过程慢、数据回收问题进行了画质检测效率优化方案探索,通过队列 + 多线程方式搭建 “生产者 - 消费者” 模型实现了边采集 - 边质检过程,使画质检测效率提升了 42%,为后续相关方案的接入提供了参考。