当前位置: 首页 > news >正文

做网站的必要性北京百度快速优化排名

做网站的必要性,北京百度快速优化排名,直客通产品如何上线,互联网中厂有哪些公司Qt 基于FFmpeg的视频转换器 - 转GIF动图 引言一、设计思路二、核心源码三、参考链接 引言 gif格式的动图可以通过连续播放一系列图像或视频片段来展示动态效果,使信息更加生动形象,可以很方便的嵌入到网页或者ppt中。上图展示了视频的前几帧转为gif动图的…

Qt 基于FFmpeg的视频转换器 - 转GIF动图

  • 引言
  • 一、设计思路
  • 二、核心源码
  • 三、参考链接

引言

在这里插入图片描述 在这里插入图片描述

gif格式的动图可以通过连续播放一系列图像或视频片段来展示动态效果,使信息更加生动形象,可以很方便的嵌入到网页或者ppt中。上图展示了视频的前几帧转为gif动图的效果 (转了7%直接取消了)。

之前写过一个基于python的 MP4视频转GIF动图,速度略慢且不容易打包 (体积很大),故基于c++写一个小程序,方便日常使用. (这里推荐几个gif生成的小工具 - GifCamScreenGif.exeLICEcap.exe等等 or 直接使用ffmpeg提供的小工具)

  • 本文思路:基于FFmpeg进行视频的读取解码成一张张图片,调用gif.h将图片写入gif

gif-h官方git地址:https://github.com/charlietangora/gif-h

一、设计思路

可参考之前的博客:Qt 基于FFmpeg的视频播放器 - QtFFmpegPlayer

    1. 和之前的视频播放器play()函数类似,实现savetoGif()函数,将视频的一帧解码成图片后,立即写入gif文件
       GifWriteFrame(&writer, image.bits(),static_cast<uint32_t>(avcodec_context->width),static_cast<uint32_t>(avcodec_context->height),static_cast<uint32_t>(100/this->m_fps),        // 单位是1/100秒,即10ms8, true);frame_id++;qDebug()<<QString("当前转换第 %1 帧").arg(frame_id);emit sig_SendFrameNum(frame_id);
    1. 创建新的FFmpegVideo类和新的处理线程,避免与播放线程冲突
m_FFmpegProcessing = new FFmpegVideo();
m_ProcessingThread = new QThread(this);
m_FFmpegProcessing->moveToThread(m_ProcessingThread);  // 移动到线程中
    1. 创建非模态的进度条,发送sig_SendFrameNum帧数信号设置进度条进度 同时判断是否点击了进度条的按钮 (稳妥起见此连接设置为Qt::BlockingQueuedConnection - 确定同步执行对m_stopProcessing 及时赋值)
    // 进度条progressDialog = new QProgressDialog();progressDialog->setMinimumWidth(300);               // 设置最小宽度progressDialog->setWindowModality(Qt::NonModal);    // 非模态,其它窗口正常交互  Qt::WindowModal 模态progressDialog->setMinimumDuration(0);              // 等待0秒后显示progressDialog->setWindowTitle(tr("进度条框"));      // 标题名progressDialog->setLabelText(tr("正在转换"));        // 标签的progressDialog->setCancelButtonText(tr("放弃"));    // 取消按钮progressDialog->setRange(0, static_cast<int>(m_FFmpegProcessing->m_frame_num));    // 考虑是否移换种方式显示进度条进度... 不使用帧数
// 进度条绑定
connect(m_FFmpegProcessing, &FFmpegVideo::sig_SendFrameNum, this, [&](int num){if(progressDialog->wasCanceled()){    // 弹窗的取消按钮m_FFmpegProcessing->m_stopProcessing = true;return;}progressDialog->setValue(num);}, Qt::BlockingQueuedConnection);  // 发送信号后,先执行此内容 再继续执行线程,保证线程可以及时推出

使用lambda表达式接收信号,需要注意其默认参数… 建议写完整防止奇奇怪怪的问题
Qt使用connect连接信号与lambda表达式需要注意:https://blog.csdn.net/qq_17769915/article/details/132609165
qt 如何使用 lamda 表达式接收线程中发射的数据,并在里面更新 UI ?https://www.cnblogs.com/cheungxiongwei/p/10895172.html

    1. 子线程中会判断m_stopProcessing - 是否点击了进度条的退出按钮. 如果点击了按钮,最后也会执行GifEnd生成一个不完整的gif
while(this->m_stopProcessing == false)
GifEnd(&writer);   // 取消之后是否需要保存不完整的gif?  暂时保存

使用事件循环,信号,stop变量,sleep阻塞,QWaitCondition+QMutex条件变量,退出子线程工作:https://blog.csdn.net/u012999461/article/details/127204493

    1. 进度条在函数中new的,子线程结束之后需释放deleteLater。 还有一些小问题… 比如点两次另存为gif,可以同时弹出两个进度条等等 - 进度条没必要每次都new… 后续继续改进
// 开始转换  在这里连接需注意Qt::UniqueConnection 使得连接唯一
connect(m_ProcessingThread, SIGNAL(started()), m_FFmpegProcessing, SLOT(savetoGif()), Qt::UniqueConnection);
connect(m_ProcessingThread, &QThread::finished, progressDialog, &QProgressDialog::deleteLater, Qt::UniqueConnection);
m_ProcessingThread->start();
m_ProcessingThread->quit();

二、核心源码

其他源码可参考我之前的博客:Qt 基于FFmpeg的视频播放器 - QtFFmpegPlayer

  1. FFmpegVideo::savetoGif()
void FFmpegVideo::savetoGif()
{qDebug()<<"savetoGif";//avformat_seek_file()GifWriter writer = {};GifBegin(&writer, this->m_outfilename.toStdString().c_str(),static_cast<uint32_t>(avcodec_context->width),static_cast<uint32_t>(avcodec_context->height),static_cast<uint32_t>(100/this->m_fps),        // 单位是1/100秒,即10ms8, true );// 初始化临时变量AVPacket* av_packet = static_cast<AVPacket*>(av_malloc(sizeof(AVPacket)));AVFrame *pFramein = av_frame_alloc();   //输入和输出的帧数据AVFrame *pFrameRGB = av_frame_alloc();uint8_t * pOutbuffer = static_cast<uint8_t *>(av_malloc(      //缓冲区分配内存static_cast<quint64>(av_image_get_buffer_size(AV_PIX_FMT_RGBA,avcodec_context->width,avcodec_context->height,1))));// 初始化缓冲区av_image_fill_arrays(pFrameRGB->data,pFrameRGB->linesize,pOutbuffer,AV_PIX_FMT_RGB32,avcodec_context->width, avcodec_context->height, 1);// 格式转换SwsContext* pSwsContext = sws_getContext(avcodec_context->width,    // 输入宽avcodec_context->height,   // 输入高avcodec_context->pix_fmt,  // 输入格式avcodec_context->width,    // 输出宽avcodec_context->height,   // 输出高AV_PIX_FMT_RGBA,           // 输出格式SWS_BICUBIC,               ///todonullptr,nullptr,nullptr);int ret=0;int frame_id = 0;this->m_stopProcessing = false;// 开始循环while(this->m_stopProcessing == false){if (av_read_frame(avformat_context, av_packet) >= 0){if (av_packet->stream_index == av_stream_index){avcodec_send_packet(avcodec_context, av_packet);        // 解码ret = avcodec_receive_frame(avcodec_context, pFramein); // 获取解码输出if (ret == 0){sws_scale(pSwsContext,  //图片格式的转换static_cast<const uint8_t* const*>(pFramein->data),pFramein->linesize, 0, avcodec_context->height,pFrameRGB->data,  pFrameRGB->linesize);QImage  *tmpImg  = new QImage(static_cast<uchar *>(pOutbuffer),avcodec_context->width,avcodec_context->height,QImage::Format_RGBA8888);QImage image = tmpImg->copy();GifWriteFrame(&writer, image.bits(),static_cast<uint32_t>(avcodec_context->width),static_cast<uint32_t>(avcodec_context->height),static_cast<uint32_t>(100/this->m_fps),        // 单位是1/100秒,即10ms8, true);frame_id++;qDebug()<<QString("当前转换第 %1 帧").arg(frame_id);emit sig_SendFrameNum(frame_id);//break;}}}}GifEnd(&writer);   // 取消之后是否需要保存不完整的gif?  暂时保存av_packet_unref(av_packet);
}
    1. MainWindow::saveVideo()
void MainWindow::saveVideo()
{if(!m_FFmpegVideo){return;}m_FFmpegProcessing->loadVideoFile(m_FFmpegVideo->m_filename);  // 读取视频QFileInfo fileInfo(m_FFmpegProcessing->m_filename);QString filePath = QFileDialog::getSaveFileName(this, QObject::tr("Open File"),fileInfo.completeBaseName() + ".gif",QObject::tr("gif (*.gif) ;; All Files (*)"));m_FFmpegProcessing->m_outfilename = filePath; // 输出文件fileInfo.setFile(filePath);// 转GIF ------------int ret = fileInfo.suffix().compare(QString("gif"), Qt::CaseInsensitive);// 进度条progressDialog = new QProgressDialog();progressDialog->setMinimumWidth(300);               // 设置最小宽度progressDialog->setWindowModality(Qt::NonModal);    // 非模态,其它窗口正常交互  Qt::WindowModal 模态progressDialog->setMinimumDuration(0);              // 等待0秒后显示progressDialog->setWindowTitle(tr("进度条框"));      // 标题名progressDialog->setLabelText(tr("正在转换"));        // 标签的progressDialog->setCancelButtonText(tr("放弃"));    // 取消按钮progressDialog->setRange(0, static_cast<int>(m_FFmpegProcessing->m_frame_num));    // 考虑是否移换种方式显示进度条进度... 不使用帧数// 转换if(ret == 0){// 进度条绑定connect(m_FFmpegProcessing, &FFmpegVideo::sig_SendFrameNum, this, [&](int num){if(progressDialog->wasCanceled()){    // 弹窗的取消按钮m_FFmpegProcessing->m_stopProcessing = true;return;}progressDialog->setValue(num);}, Qt::BlockingQueuedConnection);  // 发送信号后,先执行此内容 再继续执行线程,保证线程可以及时推出// 开始转换  在这里连接需注意Qt::UniqueConnection 使得连接唯一connect(m_ProcessingThread, SIGNAL(started()), m_FFmpegProcessing, SLOT(savetoGif()), Qt::UniqueConnection);connect(m_ProcessingThread, &QThread::finished, progressDialog, &QProgressDialog::deleteLater, Qt::UniqueConnection);m_ProcessingThread->start();m_ProcessingThread->quit();}
}

三、参考链接

    1. 直接调用工具:

用ffmpeg提供的工具将视频转成gif动图:https://blog.csdn.net/xindoo/article/details/127603896
Android录屏并利用FFmpeg转换成gif:https://blog.csdn.net/MingHuang2017/article/details/79186527

    1. 代码实现:

Qt项目中,实现屏幕截图并生成gif的详细示例:https://www.zhihu.com/tardis/bd/art/194303756
Qt编写自定义控件35-GIF录屏控件:https://developer.aliyun.com/article/712842
ffmpeg生成gif动图:https://www.jianshu.com/p/d9652fc2e3fd
FFmpeg进阶: 截取视频生成gif动图:https://zhuanlan.zhihu.com/p/628705382

http://www.15wanjia.com/news/21197.html

相关文章:

  • 免费中文wordpress主题下载地址网络优化工程师有多累
  • 页面设计培训学什么云南网络营销seo
  • 制作网站软件用什么语言百度竞价排名的利与弊
  • 网站建设的关键技术免费b站推广网站下载
  • wordpress 索引百度推广优化排名怎么收费
  • 有哪些做特卖的网站引擎优化seo怎么做
  • 帮别人做app网站门户的兼职广告软文怎么写
  • 外贸网站模板哪里下载电子报刊的传播媒体是什么
  • 做商城网站需要备案什么域名网络营销的特点
  • 装修网站怎么做兰州网络seo
  • 购买域名如何建设网站在线搭建网站
  • wordpress友情链接做导航谷歌搜索引擎seo
  • 诏安网站建设怎样做网站推广啊
  • 做元器件上什么网站想在百度上推广怎么做
  • 又一个 wordpress 站点运营推广是做什么的
  • 网站建设方案书的内容seo网络推广是什么意思
  • wordpress编辑器添加代码工具seo 工具分析
  • 网站运营经验分享ppt模板产品推广介绍怎么写
  • 做网站的可以黑客户的网站吗seo广告优化
  • iis服务器怎么部署php网站广告的六种广告形式
  • 网站培训费用百度手机快速排名点击软件
  • 网站建设 中企动力厨具全国疫情高峰感染高峰进度
  • 如何搭建网站赚钱seo关键词选择及优化
  • 有没有做a的电影网站站长工具ip地址
  • 网站为什么显示正在建设中网络营销竞价推广
  • 如何做汽车的创意视频网站交换友情链接的条件
  • 装饰工程施工方案苏州seo排名公司
  • 做python项目的网站哈尔滨推广优化公司
  • flask网站开发怎么创建自己的游戏网站
  • 找人做一个网站要多少钱百度客服中心