基于FFMPEG的音视频截取(C++Qt 版)

这篇博客是基于上篇博客的:

https://blog.csdn.net/liyuanbhu/article/details/121744275

上篇博客实现了文件封装转换。我们在这个基础上再加一点功能。实现可以任意截取一段时间范围内的音视频。

下面是代码:

QlyAVFormatContext inFile, outFile;
inFile.openFile(QString("D:\\AV36_1.avi"));
inFile.dumpFormat();
QSet<AVMediaType> type;    type << AVMEDIA_TYPE_VIDEO << AVMEDIA_TYPE_AUDIO;
QVector<QlyAVStream> inStreams = inFile.findStreams(type);qDebug() << inStreams[0].m_stream->time_base;
outFile.createFile(QString(), QString("D:\\AV36_1-qt-15.mkv"));
outFile.setStreams(inStreams);
outFile.writeHeader();inFile.seekFrame(10.0, -1, AVSEEK_FLAG_BACKWARD);QlyAVPacket pkt;
while(inFile.readFrame(pkt, type))
{AVRational in_tb = inFile.rawStream(pkt.streamIndex())->time_base;if(pkt.compare_ts(25.0) >= 0){pkt.unref();break;}pkt.adjustTime(10.0);outFile.writeFrame(pkt, in_tb, true);pkt.unref();
}
outFile.writeTrailer();

这个代码从10s开始截取音视频,一直截取到25s。也就是截取了 15s 的音视频。我不会从头解释这个代码,只是讲讲这个代码与上篇博客代码的区别。首先,增加了这么一行代码:

inFile.seekFrame(10.0, -1, AVSEEK_FLAG_BACKWARD);

这里 seekFrame 的定义如下:

/*** @brief seekFrame 移动媒体文件的帧指针* @param time      时间,以秒为单位* @param stream_index -1 表示不局限于某个流* @param seekFlag  可以是 AVSEEK_FLAG_BACKWARD*                        AVSEEK_FLAG_BYTE*                        AVSEEK_FLAG_ANY*                        AVSEEK_FLAG_FRAME* @return true 表示找到了,false 表示出错*/
bool QlyAVFormatContext::seekFrame(double time, int stream_index, int seekFlag)
{int64_t timestamp = 0;if(stream_index == -1){timestamp = time * AV_TIME_BASE;}else{AVStream *in_stream = pFormatCtx->streams[stream_index];timestamp =  time / av_q2d(in_stream->time_base);}errorcode = av_seek_frame(pFormatCtx, stream_index, timestamp, seekFlag);return (errorcode >= 0);
}

可以看到,内部其实是调用了 av_seek_frame() 函数。但是为了使用方便,time 是以秒为单位的,而且是 double 型,也就是可以分辨更精细的时间单位(比如毫秒、微秒)。

另外,代码里的 av_q2d 可以将 AVRational 转换为 浮点数。方便我们运算。

timestamp = time * AV_TIME_BASE;

这行代码值得讲讲,AV_TIME_BASE 是 ffmpeg 默认的时间单位,表示的是1秒分成多少份。如果我们没有指定某一个特定的流,那么就用这个时间单位。在现在的 ffmpeg 版本中,AV_TIME_BASE =1000000。也就是说基本的时间单位是微秒。如果我们制定了某个流,就要用那个流的时间单位。所以:

timestamp =  time / av_q2d(in_stream->time_base);

下面再讲讲另一个函数:

if(pkt.compare_ts(25.0) >= 0)

compare_ts() 函数比较当前帧的时间和函数参数表示的时间的前后关系。

/*** @brief compare_ts* @param timestamp* @return  -1 表示当前帧的时间小于 timestamp, 1 表示大于, 0 表示相等*/int compare_ts(double timestamp)

实现代码很简单,用到了 av_compare_ts() 函数:

int QlyAVPacket::compare_ts(double timestamp)
{AVRational av_time_base_q = {1, AV_TIME_BASE};return av_compare_ts(m_packet.pts, m_timeBase, timestamp * AV_TIME_BASE, av_time_base_q);
}

这里我没有用 AV_TIME_BASE_Q,是因为 AV_TIME_BASE_Q 的定义不符合 C++ 的语法(是符合C 语言语法的)。没办法,我自己搞了个 av_time_base_q。

再往下,还有个地方需要解释:

pkt.adjustTime(10.0);

这个函数是把时间往前调10s。否则用播放器播放时我们看到的时间不是从0开始的。这是函数实现代码也非常简单。说实话,adjustTime 这个函数名起的不太好。不过我也没想到更好的名字。大家要是有更贴切的名字可以给我留言。

void QlyAVPacket::adjustTime(double timestamp)
{int64_t ts = timestamp * m_timeBase.den / m_timeBase.num;m_packet.pts = m_packet.pts - ts;m_packet.dts = m_packet.dts - ts;
}

至此,这个代码就讲完了。

转封装问题基本就都讲完了,下一篇博客开始将音视频编码。

基于FFMPEG的音视频截取(C++Qt 版)相关推荐

  1. 基于ffmpeg的音视频转码、压制、录屏、裁切、合并、提取

    ffmpeg转码.压制.录屏.裁切.合并.提取 1.ffmpeg介绍 2.转换格式 3.音频转码 4.视频转码 5.码率控制模式 6.合并.提取音视频 7.截取.连接音视频 8.截图.水印.动图 9. ...

  2. 基于ffmpeg实现音视频转码

    一.背景 偶然的机会接触了ffmpeg,当时是从B站下载的视频转移到笔记本上看.使用b站手机客户端下载的视频格式为m4s的两个文件(video.m4s和audio.m4s),需要转成普通播放器支持的m ...

  3. 基于FFmpeg的Java视频Mp4转GIF初探

    背景 在一些业务场景中,会有如下的一些要求:比如有用户需要将Mp4视频转为Gif动图.当然有一些小伙伴说可以使用系统截图,然后使用之前提到过的技术:GIF图像动态生成-JAVA后台生成.需要处理的素材 ...

  4. 基于FFMPEG 的跨平台视频编解码研究

    第33卷 第11期 2011年11月 武 汉 理 工 大 学 学 报 JOURNALOF WUHANUNIVERSITYOFTECHNOLOGY Vol.33 No.11 췍췍췍췍췍췍췍췍췍췍췍췍췍췍 ...

  5. FFMPEG开源音视频项目学习汇总

    ~非常感谢雷霄骅老师的无私帮助,本文转载自:http://blog.csdn.net/leixiaohua1020/article/details/42658139~       本文汇总一下自己视音 ...

  6. 基于FFmpeg的运动视频分析

    本文来自英特尔资深软件工程师李忠,张华在LiveVideoStackCon 2018大会上的分享,由LiveVideoStack整理而成.分享中两位老师重点介绍了基于FFmpeg的运动视频分析技术架构 ...

  7. 使用FFMPEG进行音视频编解码(C++) 0.简介

    FFMPEG介绍 FFMPEG是一个开源的编解码软件,读作"ef ef em peg".官方网址是:http://ffmpeg.org/.FFMPEG几乎支持所有的格式,当然了像一 ...

  8. 【FFmpeg】使用 FFmpeg 处理音视频格式转换流程 ( 解复用 | 解码 | 帧处理 | 编码 | 复用 )

    FFmpeg 系列文章目录 [FFmpeg]Windows 搭建 FFmpeg 命令行运行环境 [FFmpeg]FFmpeg 相关术语简介 [FFmpeg]FFmpeg 相关术语简介 二 [FFmpe ...

  9. 使用ffmpeg打印音视频的详细信息

    使用ffmpeg打印音视频的详细参数非常简单,仅仅需要三个函数接口实现: /*所有进行操作前,先执行以下,否则需要自己制定类型*/av_register_all/*Open an input stre ...

最新文章

  1. Cassandra读写性能测试
  2. Hibernate QBC 分页
  3. iSCSI故障查询列表
  4. 实现框架页面iframe的背景透明方法
  5. webstorm php文件高亮,webStorm支持.wxml文件高亮显示
  6. python 利用pyttsx3文字转语音
  7. QT学习:视图(View)练习
  8. composer 笔记
  9. 关于keil环境的 三个红点(备忘)
  10. LeetCode 1668. 最大重复子字符串
  11. urdf与xacro的使用方法 机械臂模型仿真示例
  12. 计算机仿真技术物流,基于计算机仿真技术的物流实验室建设
  13. 基于51单片机的循迹小车
  14. 计算机操作系统第四版知识点总结(详细版一)
  15. 综合评价指标权重方法汇总
  16. hibernate还有人用吗
  17. 图灵在计算机科学方面主要贡献,图灵在计算机理论方面的贡献
  18. 【BZOJ】3613: [Heoi2014]南园满地堆轻絮-贪心
  19. java计算机毕业设计企业物资管理系统源代码+数据库+系统+lw文档
  20. 国内部分视频剪辑软件使用总结

热门文章

  1. qt+opencv调用笔记本摄像头
  2. 51单片机c语言延时时间计算,单片机定时器延迟时间计算
  3. ISFJ型人格的性格缺陷和心理问题分析
  4. SOLIDWORKS官网如何下载SOLIDWORKS安装程序?
  5. SAP MTS/ATO/MTO/ETO专题之五:E+M模式前后台操作,自定义策略
  6. Java 实现小游戏双人匹配机制
  7. 一个答案不唯一的数独问题
  8. 【CPU风扇不转怎么办】
  9. 红油面皮撑起10亿营收,阿宽冲刺A股“方便食品第一股”
  10. hdu6208 The Dominator of Strings(AC自动机)