前言
在视频处理中,截图的功能很常见。不管是用于视频分析、视频审核还是进度条的缩略图显示,都离不开截图功能。最近有客户反馈,对视频文件指定时间点截图,没有获取到任何图片,也没有相关报错提示。图片不知道去哪了。
是截取的图片丢失了?还是没有截取到图片?下面以腾讯云点播为例来看下这个问题。
问题定位
客户使用云点播的指定时间点截图功能,未获取到图片,也没有收到报错信息。接下来我们看一下是什么原因导致的。
首先我们遇到此类问题时要先确认模板设置是否正确,可以到云点播控制台检查截图模板和任务流的配置。
很显然截图模板与任务流设置都是OK的。
接下来再看看操作过程和步骤是否正确。
控制台如上操作是完全正确的,如果是调用的API发起任务,可以通过在线工具进行验证,输入对应的参数,然后点击在线调用即可,返回taskid和requestid就说明任务发起成功了。
https://console.cloud.tencent.com/api/explorer?Product=vod&Version=2018-07-17&Action=ProcessMediaByProcedure&SignVersion=
目前来看也没有操作不当的情况,这时该怎么办呢?
在确认好以上两点没问题之后,我们可以让工程师看下任务的具体执行情况,发现截图任务失败,具体的报错信息为“invalid parameter TimeOffset value larger than media duration”,截图时间点大于视频时长。这是我们恍然大悟,需要用ffmpeg命令来验证下视频时长。
ffmpeg -i “视频文件全路径”
结果显示视频时长是9.63s,而我们设置的截图时间点是10s,超过了视频时长导致截图失败。
解决方案
既然原因已经确认到了,我们来修改指定时间点为9.63s,继续发起截图任务,结果这个调皮的图片还是没有出现,它是在跟我们玩捉迷藏吗。其实根本原因还是我们的姿势不对,该视频总时长是9.63s,设置的指定时间等于视频时长,也有可能导致获取不到截图数据(这是为什么呢?我们在后面的原理分析中会详细解释。)
再次修改指定时间为9.6s,重新发起任务,图片就这样被截取了出来,成功的喜悦难以言表。
原理解析
截图是截取视频特定位置的图像并生成图片的过程,是一种离线任务。指定时间点截图就是截取时间点后面的第一帧图像(I、B、P帧都有可能),并把图片保存在指定位置。那么我们也就明白设置指定时间为10s截图,是因为超过了视频总时长导致没有视频数据而失败了。
那么问题又来了,设置指定时间点与视频时长一致为什么也失败呢,这时我们还要继续用ffmpeg分析下视频,这次我们来看下源文件视频帧的分布情况。
ffprobe -of compact -show_frames "视频文件全路径"
通过打印出来的视频帧信息,我们可以清楚的看到该文件最后一帧是P帧,而且时间点刚好是9.6s,也就是说在9.6s以后并没有视频帧,对于该视频文件我们要想正确的截取出图片,那么设置的截图时间点就必须要早于9.6s才可以。
如果业务有需要,对最后的视频帧进行截图,可以在截图任务下发之前,用上述ffmpeg命令分析下最后一帧的时间点,设置的截图时间早于最后一帧时间即可。
扩展
云点播提供以下类型的截图:
1、指定时间点截图:指定一组时间点,截取视频在这些时间点的图像。
2、采样截图:按相同的时间间隔对视频截取多张图。
3、截取一张图作封面:指定一个时间点截图,将其 URL 作为媒资系统中该视频的封面。
4、截雪碧图:按相同的时间间隔对视频截取多张小图,然后组装成若干大图(即雪碧图)。
当截图的宽高比与原始视频的宽高比不一致时,对截图的处理方式,即为“填充”。一般有以下几种填充方式:
1、 拉伸:对图片进行拉伸,填满整个图片,可能导致图片被“压扁”或者“拉长”。
2、留黑:保持图片宽高比不变,边缘剩余部分使用黑色填充。
3、留白:保持图片宽高比不变,边缘剩余部分使用白色填充。
4、高斯模糊:保持图片宽高比不变,边缘剩余部分使用高斯模糊化后填充。
大家可以根据业务实际需求,选择对应的截图和填充方式。