ffmpeg生成缩略图
整个项目在https://github.com/ximikang/ffmpegThumbnail发布
生成缩略图的步骤
- 使用ffmpeg解码视频
- 帧格式转换
- 根据缩略图的数量从视频流中取帧
- 使用opencv建立画布并生成缩略图
ffmpeg解码视频
根据缩略图的数量从视频流中取帧
- 获取图片之间的时间间隔
// Read media file and read the header information from container formatAVFormatContext* pFormatContext = avformat_alloc_context();if (!pFormatContext) {logging("ERROR could not allocate memory for format context");return -1;}if (avformat_open_input(&pFormatContext, inputFilePath.string().c_str(), NULL, NULL) != 0) {logging("ERROR could not open media file");}logging("format %s, duration %lld us, bit_rate %lld", pFormatContext->iformat->name, pFormatContext->duration, pFormatContext->bit_rate);cout << "视频时常:" << pFormatContext->duration / 1000.0 / 1000.0 << "s" << endl;int64_t video_duration = pFormatContext->duration;int sum_count = rowNums * colNums;//跳转的间隔 msint64_t time_step = video_duration / sum_count / 1000;
- 设置跳转时间获取不同的视频Packet
for (int i = 0; i < sum_count ; ++i) {cv::Mat tempImage;// 每次读取相同时间间隔的图像并存入vImage中while (av_read_frame(pFormatContext, pPacket) >= 0) {if (pPacket->stream_index == video_stream_index) {response = decode_packet_2mat(pPacket, pCodecContext, pFrame, tempImage);// 返回}if (response == 0)// 成功读取一帧break;if (response < 0)continue;}vImage.push_back(tempImage);// 跳转视频av_seek_frame(pFormatContext, -1, ((double)time_step / (double)1000)* AV_TIME_BASE*(double)(i+1) + (double)pFormatContext->start_time, AVSEEK_FLAG_BACKWARD);}
3.获取Frame
在固定的时间点可能无法获取从当前时间点的Packet获取对应的Frame,所以需要对获取的Packet进行判断,如果没有获取到对应的Frame应该继续获取下一Packet直到获取到对应的Frame为止。
static int decode_packet_2mat(AVPacket* pPacket, AVCodecContext* pCodecContext, AVFrame* pFrame, cv::Mat& image) {int response = avcodec_send_packet(pCodecContext, pPacket);if (response < 0) {logging("Error while sending a packet to the decoder");return response;}while (response >= 0) {// return decoded out data from a decoderresponse = avcodec_receive_frame(pCodecContext, pFrame);if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {logging("averror averror_eof");break;}else if (response < 0) {logging("Error while receiving frame");return response;}if (response >= 0) {// 获取到Frameimage = frame2Mat(pFrame, pCodecContext->pix_fmt);} return 0;}
}
帧格式转换
由于从视频流获取的帧是YUV格式的Frame格式,后面使用opencv进行操作所以进行格式转换。
先使用ffmpeg中的SwsContext将从视频中抽取到的帧从YUV转换到BGR格式,再从BGRFrame中的内存中获取原始数据,并转换到opencv的Mat类型。
cv::Mat frame2Mat(AVFrame* pFrame, AVPixelFormat pPixFormat)
{// image initAVFrame* pRGBFrame = av_frame_alloc();uint8_t* out_buffer = new uint8_t[avpicture_get_size(AV_PIX_FMT_BGR24, pFrame->width, pFrame->height)];avpicture_fill((AVPicture*)pRGBFrame, out_buffer, AV_PIX_FMT_BGR24, pFrame->width, pFrame->height);SwsContext* rgbSwsContext = sws_getContext(pFrame->width, pFrame->height, pPixFormat, pFrame->width, pFrame->height, AV_PIX_FMT_BGR24,SWS_BICUBIC, NULL, NULL, NULL);if (!rgbSwsContext) {logging("Error could not create frame to rgbframe sws context");exit(-1);}if (sws_scale(rgbSwsContext, pFrame->data, pFrame->linesize, 0, pFrame->height, pRGBFrame->data, pRGBFrame->linesize) < 0) {logging("Error could not sws to rgb frame");exit(-1);}cv::Mat mRGB(cv::Size(pFrame->width, pFrame->height), CV_8UC3);mRGB.data = (uchar*)pRGBFrame->data[0];//注意不能写为:(uchar*)pFrameBGR->dataav_free(pRGBFrame);sws_freeContext(rgbSwsContext);return mRGB;
}
使用opencv建立画布并生成缩略图
通过画布需要的大小参数,画出白色画布,再对画布进行填充。
cv::Mat makeThumbnail(vector<cv::Mat> vImage, const unsigned int rowNums, const unsigned int colNums)
{// 判断图片时候满足条件if (vImage.size() != rowNums * colNums) {logging("Error image size not equal input size");logging("vImage length: %d, rowNums: %d, col number: %d", vImage.size(), rowNums, colNums);exit(-1);}int interval = 100;int height = vImage[0].size().height * rowNums + interval * (rowNums + 1);int width = vImage[0].size().width * colNums + interval * (colNums + 1);logging("thumbnail size: %d * %d", height, width);cv::Mat thumbnail(cv::Size(width, height), CV_8UC3);thumbnail.setTo(255);// 进行填充for (int i = 0; i < rowNums; ++i) {for (int j = 0; j < colNums; ++j) {int no = i * rowNums + j;int widthOffset = (vImage[0].size().width + interval) * j + interval;int heightOffset = (vImage[0].size().height + interval) * i + interval;vImage[no].copyTo(thumbnail(cv::Rect(widthOffset, heightOffset, vImage[0].size().width, vImage[0].size().height)));}}return thumbnail;
}
最后的效果
ffmpeg生成缩略图相关推荐
- 利用FFmpeg生成视频缩略图 2.1.8
1.下载FFmpeg文件包,解压包里的\bin\下的文件解压到 D:\ffmpeg\ 目录下.下载地址 http://ffmpeg.zeranoe.com/builds/win32/static/D: ...
- php 图片生成视频,PHP基于ffmpeg实现转换视频,截图及生成缩略图的方法
本文实例讲述了PHP基于ffmpeg实现转换视频,截图及生成缩略图的方法.分享给大家供大家参考,具体如下: 这里把ffmpeg 和 生成缩略图整合了一下: include("ImageRe ...
- FFmpeg截图以及生成缩略图
介绍:FFmpeg是用于录制.转换和流化音频和视频的完整解决方案,一套领先的音/视频编解码类库.官方正式版ffmpeg不支持rmvb和rm格式. 不过有很多解决方法 FFmpeg的官方网址是 http ...
- 极速生成缩略图,Serverless 支撑赛事转播锁定冬奥亮点
作者:西流.筱姜 "北京冬奥会在开赛的第四天便成为了历史上收视最高的一届冬奥会,其转播内容总生产量将达 6000 小时,超过平昌冬奥会的 5400 小时.关注北京冬奥会的人群比往届都多,北京 ...
- fastdfs上传文件资料(PDF,视频,图片,FileCaseUtil,FileUploadUtil)并生成缩略图
javacv里面有类型转换器的使用,对视频图片的处理工具等等 一.UML图 二.代码 pom依赖 <!-- fastdfs--><dependency><groupId& ...
- php 图片生成封面,ffmpeg生成视频封面图
ffmpeg 是一个视频处理软件 php-ffmpeg 是一个让 php 可以操作 ffmpeg 的 php插件,封装好了各种操作视频的名命令.直接调用对应的方法即可. 使用过程很曲折也很简单 曲折在 ...
- C#上传视频生成缩略图
注意:需要FFmpeg软件,用到ffmpeg.exe:FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频 ...
- C# webform上传图片并生成缩略图
其实里面写的很乱,包括修改文件名什么的都没有仔细去写,主要是想记录下缩略图生成的几种方式 ,大家明白就好! 1 void UpImgs() 2 { 3 if (FileUpload1.HasFile) ...
- C#编写的生成缩略图程序
if(fileupload.PostedFile!=null) { //addto为要添加的属性,aboutfile为文件说明 string nam = fi ...
- 使用FileUpload控件上传图片并自动生成缩略图、自动生成带文字和图片的水印图
本文借助vs2005中自带的FileUpload控件实现图片文件的上传并生成缩略图. 实现过程:选择图片上传成功后,取得已经存在服务器的文件生成缩略图,并且判断是否是图片类型的文件,这个的判断可以在程 ...
最新文章
- mySQL教程 第10章 事务和锁
- zookeeper实现分布式锁的原理及具体使用案例
- 科普: 中间件底层实现的分布式协议之Raft
- 基于netty的微服务架构
- 构成网络的多台计算机其硬件配置必须相同吗,计算机省一级2014年-2016年章节试题(答案).docx...
- SAP License:作业类型作为成本对象
- php url参数用–,php获取URL各部分参数
- 软考程序员2017下半年真题含答案解析
- ODBC、OLE DB、 ADO的区别
- 硬盘IDE模式与AHCI模式的区别
- ubuntu 安装音乐播放器
- SAP中由生产版本有误导致的生产报工时提示“错误确定成本核算”问题实例
- 掌握茼蒿施肥方式,想不高产都难。
- 克里奥服务器装系统,克里奥神模拟器
- 【Note】二十四节气英文表达(solar term)
- 在Unity中使用FFmpeg将视频绿色背景处理为透明背景
- Result统一响应数据
- 开一个水果店如何进货呢,水果店进货多少
- 【人工智能AI2.0】国产开源 ChatGPT: ChatGLM-6B 搭建属于你的永远免费的本地 ChatGPT
- Android 圆形停止按钮,跑步APP停止动画