一、啰嗦几句

好几年不写博客了,一是工作计算机都加密了没法编辑提交;二是各种语言混用,什么都会就是什么都不会,delphi、c#、vb、python、c++要说我精通啥,啥也不精,所以不敢乱写。

最近做一个关于视频处理的项目,用到ffmpeg,实在是憋不住,在此记录一下摸索的过程。可以毫不夸张的说,网上关于ffmpeg的使用,大部分用命令行方式,调用api方式的很少,而且盲目抄袭甚盛,斗胆妄言,罪过罪过。

二、感谢

我是通过学习雷神的博客逐渐掌握了ffmpeg的一些东西,好歹把项目做完了,效果很好,在此向雷神由衷的表示感谢。雷神由浅入深的介绍了ffmpeg的使用方法,有理论有实践,可以说网上的很多文章很难与雷神媲美,而且国内这方面的文章太少了,这么多做视频方面的,怎么就没有这方面的优质文章,在此是个疑点。可惜的是雷神花费了大量时间开放自己的学习探索的心得,当逐步的到达核心地带时,戛然而止,雷神去世了,天妒英才呐。在此沉痛缅怀并致以崇高的敬意!

在本文中,没有直接可运行的代码,一是加密,无法拷贝;二是提倡动手实践,先把雷神的实例代码挨个学习调试,自会有极大的提高;

三、项目背景

核心一句话:接收高清视频流(H264+mp3 TS流),每30分钟存储一个mp4文件,相邻两个文件的播放要顺畅不能丢帧。为啥说是高清呢,30分钟文件就有5个G。

编程语言c++

四、踩过的坑

4.1进程方式

网上很多文章都是用命令行的,这种方式只能说测试还行,真正项目应用差点意思了,因为你要管理这个进程,他是个什么状态,你不知,但你又不能不管,关键做不到前后两个视频无缝衔接,咋整,鸡肋啊,做个测试、验证等可以,做项目不行。用api吧,资料太少,项目组意见不一,最后举个例子达成一致了,前面有个碉堡,我们明知道用手榴弹不行,还坚持让大家扔手榴弹,这是瞎耽误工夫;拿zha yao肯定行,但是有人得牺牲(扔手榴弹站在远处扔就行,zha yao包得有人扛到跟前),要想彻底解决就得用彻底的办法。所以很多时候我们缺少的就是沉下心的耐力和扛zha yao包的勇气,溃痈虽痛胜于养毒,把雷神用api的例子全部从头调试一遍,总结出流程,都需要哪些要素,时间基、采样率、音视频流是啥用来做啥,搞明白就完事了。

4.2 ffmpeg rtp

ffmpeg可以直接接收RTP,也有提供转换MP4的方法,要注意的是接收和处理放在一个线程中有问题,容易丢帧,因为UDP通信必须设置缓存大小,但是一旦处理堵住了,数据绝对会丢失。程序在现场长时间不间断运行,很难保证不出现丢帧的情况,经简单测试,直接抛弃该方式。

五、我的实现方法

1、使用UDP方式接收组播视频流,并写入文件中,文件按时间命名。

2、当检测到够30分钟时,停止写入当前文件,开始写入另一个文件。

3、通知视频转换线程,处理当前写完的文件。

4、视频转换线程,读取文件,

打开输入文件流(avformat_open_input),

创建输出上下文(avformat_alloc_output_context2),我们要根据文件转成mp4。

查找视频信息(avformat_find_stream_info),查找输入的码流:视频流、音频流、字幕流。

根据输入码流创建输出码流,流的参数拷贝就行(avcodec_parameters_copy),特别要注意的是输入输出流的时间基(time_base)。

打开输出流,写入文件头,设定一个文件结尾的阈值,当输入流剩余字节数小于该值时并且找到最后一个关键帧,则写入到输出流后,将剩余输入文件的结尾置换到下一个文件的开头中,这样前后两个文件无缝衔接,第一个文件最后一个关键帧是第二个文件开头的第一帧,所以无缝衔接了。

循环读取输入流(av_read_frame)根据流索引确定是音频还是视频流,如果是视频流写入文件的第一帧必须是关键帧。写入时特别注意音频和视频的pkt的时间(pts、dts、duration)需要根据自己的时间基重新换算(av_rescale_q_rnd),并记录第一帧的时间戳pts,换算后的pts和dts要减去第一帧的pts,这样每个文件播放就是从头开始了。写入输出流用av_interleaved_write_frame。

读取文件转换成mp4,在现场机器(高速缓存设备)上总共需要不到15秒钟。

六、最终效果

项目部署5个多月,内存(103M左右,峰值180M)、cpu(3%--8%),非常稳定,无异常崩溃退出,视频无马赛克、前后视频衔接很棒。

七、总结

坚持实践就是硬道理,无论什么职位、角色都不能眼高手低。

抄别人代码一千遍不如自己动手调一遍。

关于使用ffmpeg的一些牢骚的更多相关文章

  1. FFmpeg学习6:视音频同步

    在上一篇文章中,视频和音频是各自独立播放的,并不同步.本文主要描述了如何以音频的播放时长为基准,将视频同步到音频上以实现视音频的同步播放的.主要有以下几个方面的内容 视音频同步的简单介绍 DTS 和 ...

  2. FFmpeg 中AVPacket的使用

    AVPacket保存的是解码前的数据,也就是压缩后的数据.该结构本身不直接包含数据,其有一个指向数据域的指针,FFmpeg中很多的数据结构都使用这种方法来管理数据. AVPacket的使用通常离不开下 ...

  3. FFmpeg + SoundTouch实现音频的变调变速

    本文使用FFmpeg + SoundTouch实现将音频解码后,进行变调变速处理,并将处理后的结果保存为WAV文件. 主要有以下内容: 实现一个FFmpeg的工具类,保存多媒体文件所需的解码信息 将解 ...

  4. 用ffmpeg快速剪切和合并视频

    如果直接找视频剪切和合并视频的软件,通常出来的都是大的视频编辑软件或者是有图形界面的剪切软件,大型一点的功能太多安装麻烦,小型一点的功能可能不齐全. 只是简单的剪切或者一下合并一下,还是ffmpeg这 ...

  5. ffmpeg用法及如何使用fluent-ffmpeg

    http://ffmpeg.org/ 官网 ffmpeg(命令行工具) 是一个快速的音视频转换工具. 1.分离视频音频流 ffmpeg -i input_file -vcodec copy -an o ...

  6. FFmpeg学习4:音频格式转换

    前段时间,在学习试用FFmpeg播放音频的时候总是有杂音,网上的很多教程是基于之前版本的FFmpeg的,而新的FFmepg3中audio增加了平面(planar)格式,而SDL播放音频是不支持平面格式 ...

  7. FFmpeg学习5:多线程播放视音频

    在前面的学习中,视频和音频的播放是分开进行的.这主要是为了学习的方便,经过一段时间的学习,对FFmpeg的也有了一定的了解,本文就介绍了 如何使用多线程同时播放音频和视频(未实现同步),并对前面的学习 ...

  8. FFmpeg数据结构:AVPacket解析

    本文主要从以下几个方面对AVPacket做解析: AVPacket在FFmpeg中的作用 字段说明 AVPacket中的内存管理 AVPacket相关函数的说明 结合AVPacket队列说明下AVPa ...

  9. FFmpeg学习3:播放音频

    参考dranger tutorial,本文将介绍如何使用FFmpeg解码音频数据,并使用SDL将解码后的数据输出. 本文主要包含以下几方面的内容: 关于播放音频的需要的一些基础知识介绍 使用SDL2播 ...

随机推荐

  1. 刨根问底系列(1)——虚假唤醒(spurious wakeups)的原因以及在pthread_cond_wait、pthread_cond_singal中使用while的必要性

    刨根问底之虚假唤醒 1. 概要 将会以下方式展开介绍: 什么是虚假唤醒 什么原因会导致虚假唤醒(两种原因) 为什么系统内核不从根本上解决虚假唤醒这个"bug"(两个原因) 开发者如 ...

  2. mysql截取函数常用方法 即mysql 字符串 截取-- - 最后带上java字符串截取规则比较

    常用的mysql截取函数有:left(), right(), substring(), substring_index() 下面来一一说明一下: 1.左截取left(str, length) 说明:l ...

  3. java 方法 在jvm中的调用

    java 某个类的几个对象,这些对象调用类中一个函数,是各自拥有自己的函数代码还是使用同一段代码?30 1.java 某个类的几个对象,这些对象调用类中一个函数(普通的函数),是各自拥有自己的函数代码 ...

  4. 浅谈Vector

    浅谈Vector 在之前的文章中,我们已经说过线程不安全的ArrayList和LinkedList,今天我们来讲讲一个线程安全的列表容器,他就是Vector,他的底层和ArrayList一样使用数组来 ...

  5. react性能优化最佳实践

    1.PureComponent 的使用场景 PureComponent 和 Component 的区别是,PureComponent 自带 shouldComponentUpdate 生命周期函数,会 ...

  6. Sprint 3 : oxford project API 尝试

    本次Sprint我们大家主要在调研和尝试阶段,主要是对photo experience 中的语音接口部分进行相应的调研和分析. 工作进度: 1. 图像界面设计兆阳和敏龙的工作进一步推进,除去之前介绍的 ...

  7. 计算机系统基础学习笔记(1)-基本GCC,objdump,GBD命令的使用

    基本GCC命令的使用 GCC是一套由GNU项目开发的编程语言编译器,可处理C语言. C++.Fortran.Pascal.Objective-C.Java等等.GCC通常是 跨平台软件的编译器首选.g ...

  8. SpringCloud-Ribbon负载均衡机制、手写轮询算法

    Ribbon 内置的负载均衡规则 在 com.netflix.loadbalancer 包下有一个接口 IRule,它可以根据特定的算法从服务列表中选取一个要访问的服务,默认使用的是「轮询机制」 Ro ...

  9. [XML] XML格式【有道翻译】API 的数据转化输出

    <?php header("content-type:text/html;charset=utf-8"); //echo "飞飞仔超级智障"; $cont ...

  10. MVC-路由扩展-限制浏览器

    根据路由原理,MVC每次都会走获取路由上下文数据. 自定义Route 调用,以及完善其他代码 运行结果,当在谷浏览器执行时: