概览
视频截帧是指从视频中提取出一帧或多帧静态图像,在视频处理中,截帧可以用于视频预览、封面生成、缩略图制作等多种应用场景。本文将着重介绍基于COS SDK 调用腾讯云数据万象(CI)视频截帧 API 实现图片截取功能,并提供多种截帧模式供开发者选择,助力用户快速应对实际应用场景需求。
使用场景
截取单张图片
提取视频中的特定的某一帧图片,可用于视频封面制作,视频文件预览和广告封面等场景。
截取多张图片
通过对截帧开始时间点、截帧间隔、截帧数量、输出图片尺寸、输出格式等进行自定义设置,提取视频中的一组图片,可用于视频采样分析、视频编辑、动图封面制作等场景。
雪碧图
将截取的多张图片按照一定的规律排列在一张图片上形成的一个大图。雪碧图可以通过一次请求加载多个图片,从而减少页面请求次数,提高网页性能。在视频播放器中,雪碧图可以用来实现视频预览功能,以便用户能够快速预览指定时间点的视频内容。雪碧图还可以用于游戏开发中的动画制作,将多个动画帧按照一定的规律排列在一张图片上,从而实现动画的展示。
执行方式
同步截帧
同步截帧可以获取媒体文件某个时间的截图,接口同步返回截图内容。此方式实现简单,能快速获取结果,但是仅支持截取单张图片。
异步截帧
异步截帧支持更多的参数配置,支持截取单张图片、多张图片和雪碧图。创建截帧任务后,异步处理视频文件,截图的结果在任务执行完成后通过消息回调或查询任务接口返回给用户。此方式支持更多的参数配置和处理方式,并且支持在工作流中使用,方便用户对新上传的文件和存量文件进行截帧处理。
前提条件
已创建和绑定 CI 存储桶,详情请参见 存储桶操作。
已 开通媒体处理 功能。
上传视频文件
初始化 COS Javascript SDK 并配置相关信息
<!--COS SDK--><script src="https://cdn.jsdelivr.net/npm/cos-js-sdk-v5/dist/cos-js-sdk-v5.min.js"></script>// 密钥请在访问管理控制台获取。https://console.cloud.tencent.com/cam/capiconst cos = new COS({SecretId: 'AKID*******',SecretKey: '**********',});// 存储桶配置请在cos控制台获取。https://console.cloud.tencent.com/cos/bucket// 格式参考:Bucket: 'abc-1250000000', Region: 'ap-shanghai'const config = {// 需要替换成您自己的存储桶信息Bucket: '***-125********' /* 存储桶,必须 */,Region: '**-*****' /* 存储桶所在地域,必须字段 */,FileName: 'demo.mp4' /* 视频文件名 */,};
同步截帧操作步骤
直接获取截图
cos.request({Bucket: config.Bucket,Region: config.Region,Method: 'GET',Key: config.FileName /* 存储桶内的媒体文件,必须字段 */,Query: {'ci-process': 'snapshot' /** 固定值,必须 */,time: 1 /** 截图的时间点,单位为秒,必须 */,// width: 0, /** 截图的宽,非必须 */// height: 0, /** 截图的高,非必须 */// format: 'jpg', /** 截图的格式,支持 jpg 和 png,默认 jpg,非必须 */// rotate: 'auto', /** 图片旋转方式,默认为'auto',非必须 */// mode: 'exactframe', /** 截帧方式,keyframe:截取指定时间点之前的最近的一个关键帧、exactframe:截取指定时间点的帧,默认为 exactframe ,非必须 */},RawBody: true,// 可选返回文件格式为blobDataType: 'blob',},function (err, data) {console.log(err || data);});
异步截帧操作步骤
步骤一:配置截帧参数
视频截帧任务接口详见 请求参数。
视频截帧模式配置详见 参数详情。
不同的使用场景需要使用不同的参数配置:
场景 1:截取单张图片
const snapshot = {Mode: 'KeyFrame' /* 表示关键帧模式 */,Start: '5' /* 截图开始时间,单位为秒 */,Count: '1' /* 截图数量,必须 */,};
场景 2:截取多张图片
支持不同的多帧截取方式,可以根据自己的使用场景来配置:
间隔模式,间隔固定的时间截取多帧
const snapshot = {Mode: 'Interval' /* 表示间隔模式 */,Start: '1' /* 截图开始时间,单位为秒 */,Count: '10' /* 截图数量,必须 */,TimeInterval: '5' /* 截图时间间隔,可选。未设置TimeInterval时表示截取所有帧共Count张图片 */,};
平均模式,按平均间隔截取共 X 张图片
const snapshot = {Mode: 'Average' /* 表示平均模式 */,Start: '1' /* 截图开始时间,单位为秒 */,Count: '10' /* 截图数量,必须 */,};
关键帧模式,截取 X 张关键帧,与其他帧相比,关键帧包含更多的信息,画质更好。
const snapshot = {Mode: 'KeyFrame' /* 表示关键帧模式 */,Count: '10' /* 截图数量,必须 */,};
场景 3:雪碧图
以下示例是截取25个关键帧,组合成一张 5 * 5 雪碧图:
const snapshot = {Mode: 'KeyFrame' /* 截图模式,interval 表示间隔模式 Average 表示平均模式 KeyFrame 表示关键帧模式 */,Start: '5' /* 开始时间,单位为秒 */,Count: '25' /* 截图数量,必须 */,SnapshotOutMode: 'OnlySprite' /* 截图输出模式参数, OnlySnapshot 表示仅输出截图模式 OnlySprite 表示仅输出雪碧图模式 SnapshotAndSprite 表示输出截图与雪碧图模式*/,SpriteSnapshotConfig: {Color: 'Black' /* 背景颜色,必须,支持颜色详见 https://www.ffmpeg.org/ffmpeg-utils.html#color-syntax */,Columns: '5' /* 雪碧图列数,必须*/,Lines: '5' /* 雪碧图行数,必须 */,},};
步骤二:创建视频截帧任务
//需在地址前拼接/jobs,即:`https://<BucketName-APPID>.ci.<Region>.myqcloud.com/jobsconst host = config.Bucket + '.ci.' + config.Region + '.myqcloud.com';const url = 'https://' + host + '/jobs';//使用cos sdk 发起视频截帧任务请求const body = COS.util.json2xml({Request: {Tag: 'Snapshot' /* 创建任务的 Tag:Snapshot ,必须*/,Input: {Object: `${config.FileName}` /* 需要截帧的视频文件,存储桶里的路径 */,},Operation: {Snapshot: snapshot /* 使用 ‘步骤 3’ 的参数配置 ,必须 */,Output: {Bucket: config.Bucket /* 存储结果的存储桶 ,必须 */,Region: config.Region /* 存储结果存储桶地域 ,必须 */,Object: `result-${Number}.jpg` /* 结果文件的名称,${Number}为多张截图的序号,必须 */,SpriteObject: `sprite.jpg` /* 雪碧图的名字 , 雪碧图模式下必须 */,},},},});cos.request({Bucket: config.Bucket,Region: config.Region,Method: 'POST',Url: url,Key: '/jobs' /** 固定值,必须 */,ContentType: 'application/xml' /** 固定值,必须 */,Body: body,},(err, data) => {console.log(err || data);});
请求方式为 POST,Content-Type 为 application/xml,Tag 为 Snapshot 视频截帧,Input.Object 为 准备工作中上传的 视频文件,Operation.Output 为结果输出地址,需要注意截取多张图片时, Output.Object 文件名称中需要包含${Number}作为截图序号。
接口返回参数参考响应参数,JobsDetail 节点下为任务接口响应信息。其中 JobId 为关键信息,步骤四中查询视频截帧任务结果时会用到。
步骤三:获取截帧文件
// 需在对象地址前面拼接 jobs/<jobId>,即:`https://<BucketName-APPID>.ci.<Region>.myqcloud.com/jobs/<jobId>`// jobId 即为刚刚创建的任务 IDconst host = config.Bucket + '.ci.' + config.Region + '.myqcloud.com';const url = 'https://' + host + '/jobs/' + JobId;cos.request({Bucket: config.Bucket,Region: config.Region,Method: 'GET',Url: url,Key: '/jobs/' + JobId /** 固定值,必须 */,ContentType: 'application/xml' /** 固定值,必须 */,},(err, data) => {if (err) {// 视频截帧任务查询失败,请在console查看报错信息;console.log(JSON.stringify(err));return;}const resp = data.Response || {};//判断视频截帧任务是否执行中if (resp.JobsDetail.State !== 'Success') {console.log('...视频截帧任务执行中');return;}//任务执行完成 截图文件地址为const srtUrl = `https://${config.Bucket}.cos.${config.Region}.myqcloud.com/result-0.jpg`;});
返回体 Content-Type 为 application/xml,其中 State 为 Success 代表已经完成视频截帧,读取到通过视频截帧的截图文件地址为 `https://${config.Bucket}.cos.${config.Region}.myqcloud.com/result-${Number}.jpg`。
若存在跨域问题,则需要进行存储桶跨域访问 CORS 设置,详情请参见 设置跨域访问 。
若存储桶为私有读写,则对象地址需要携带签名,详情请参见 请求签名 。
费用相关
视频截帧费用
对象存储相关费用
Demo 体验