昨天,有个朋友给我出了个难题:他手上有一个视频,1080P的,49秒,200多兆;要求在确保质量的情况下把文件压缩到10M以内。

这是什么概念呢?按照文件大小10M来计算,码率是:10 x 8 / 49 = 1.6 Mbps。也就比VCD的质量略好一点(注:VCD的标准码率是1150 Kbps)。谈何“确保质量”?mission impossible啊!

咱还是现实一点吧。在不明显损失画质的前提下,看看使用FFmpeg能够帮到多少忙。用iPhone拍了一个1920 x 1080的视频,33秒,46.3 MB,编码格式是H.264。考虑到H.264目前尚是主流的视频格式,为了播放的兼容性,我们在使用FFmpeg转码时同样选择H.264。

命令行参数-crf

在优先保证画面质量(也不太在乎转码时间)的情况下,使用-crf参数来控制转码是比较适宜的。这个参数的取值范围为0~51,其中0为无损模式,数值越大,画质越差,生成的文件却越小。从主观上讲,18~28是一个合理的范围。18被认为是视觉无损的(从技术角度上看当然还是有损的),它的输出视频质量和输入视频相当。

我们的策略是,在保证可接受视频画质的前提下,选择一个最大的crf值——如果输出视频质量很好,那就尝试一个更大的值;如果看起来很糟,那就尝试一个小一点的值。

让我们先执行下面这条命令(关于FFmpeg运行环境的配置,请参阅这篇文章):

ffmpeg -i D:\src.mov -c:v libx264 -preset veryslow -crf 18 -c:a copy D:\dest1.mp4

意思是:将D盘的源文件src.mov,以“非常慢”的速度重新编码成H.264格式,保存为D:\dest1.mp4。其中,-preset指定的编码速度越慢,获得的压缩效率就越高。而-c:a copy又是什么意思呢?因为音频的码率一般都比较小,我们就不折腾它了,况且解码后重新编码也会损害音质,于是,就将音频数据从源文件中以原有编码格式直接拷入目标文件吧。

小提示:想知道-c:v 后面的参数值怎么填吗?或者说FFmpeg到底支持哪些音视频编码格式?执行ffmpeg –encoders看一下吧。另外,执行ffmpeg -i D:\src.mov -c:v libx264 -preset -tune D:\dummy.mp4可以看到-preset参数的取值范围,如下:

有个小疑问:既然不在乎等待时间,为什么不给-preset指定一个最慢的placebo呢?那是因为:与 veryslow相比,placebo以极高的编码时间为代价,只换取了大概1%的视频质量提升。这是一种收益递减准则:slow 与 medium相比提升了5%~10%;slower 与 slow相比提升了5%;veryslow 与 slower相比提升了3%。

另外,针对特定类型的源内容(比如电影、动画等),还可以使用-tune参数进行特别的优化。但如果你不确定该用哪个选项,还是忽略这个参数吧。

对比效果

执行完一条转码命令之后,调整-crf参数值,分别设为19、20、28、51,重新转码输出为不同的MP4文件。记录数据,对比如下:

 

crf = 18

crf = 19

crf = 20

crf = 28

crf = 51

文件大小(MB)

46.3

36.7

31.2

26.5

7.95

1.25

缩减比率

21%

33%

43%

83%

97%

尝试播放这些文件。发现crf取值为18~28的情况下生成的文件,其画质没有明显的差异,而以-crf 51生成的视频画质已经惨不忍睹了!在实际应用中,多试几个crf值,在画质和压缩比之间找到一个你能接受的平衡点即可。

参考文章:ffmpeg与x264编码指南

黄聪:FFmpeg视频转码技巧之-crf参数(H.264篇)的更多相关文章

  1. C#实现 ffmpeg视频转码、播放

    近来公司项目要求实现全景相机的视频截取,但是截取的视频需求转码上传.经过研究采用ffmpeg转码,奉上一个详细介绍的博文: 最简单的基于FFMPEG的转码程序 主要是转码的操作过程,能够实现了从相机获 ...

  2. 【视频编解码·学习笔记】6. H.264码流分析工程创建

    一.准备工作: 新建一个VS工程SimpleH264Analyzer, 修改工程属性参数-> 输出目录:$(SolutionDir)bin\$(Configuration)\,工作目录:$(So ...

  3. 【视频编解码·学习笔记】4. H.264的码流封装格式

    一.码流封装格式简单介绍: H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通 ...

  4. 【视频编解码·学习笔记】4. H.264的码流封装格式 & 提取NAL有效数据

    一.码流封装格式简单介绍: H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通 ...

  5. 新手学习FFmpeg - 调用API完成录屏并进行H.264编码

    Screen Record H.264 目前在网络传输视频/音频流都一般会采用H.264进行编码,所以尝试调用FFMPEG API完成Mac录屏功能,同时编码为H.264格式. 在上一篇文章中,通过调 ...

  6. 【视频编解码·学习笔记】3. H.264视频编解码工程JM的下载与编解码

    一.下载JM工程: JM是H.264标准制定团队所认可的官方参考软件.网址如下 http://iphome.hhi.de/suehring/tml/ 从页面中可找到相应的工程源码,本次选择JM 8.6 ...

  7. 【视频编解码·学习笔记】2. H.264简介

    一.H.264视频编码标准 H.264视频编码标准是ITU-T与MPEG合作产生的又一巨大成果,自颁布之日起就在业界产生了巨大影响.严格地讲,H.264标准是属于MPEG-4家族的一部分,即MPEG- ...

  8. java运用FFMPEG视频转码技术

    基于windows系统安装FFMPEG转码技术 http://wenku.baidu.com/link?url=z4Tv3CUXxxzLpa5QPI-FmfFtrIQeiCYNq6Uhe6QCHkU- ...

  9. java ffmpeg视频转码(自测通过)

    import java.io.*; public class VideoTransfer { //ffmepg文件 安装目录 private static String ffmpeg = " ...

随机推荐

  1. 质因子分解(Pollard_Rho法)

    LL Pollard_Rho(LL n, LL c) { LL x, y, d; LL i = , k = ; x = y = rand() % n; do { i++; d = gcd(n + y ...

  2. SpringMVC整合Thymeleaf

    Thymeleaf的介绍 进行JavaWeb开发时主要用到的是JSP,传统的JSP需要在页面中加入大量的JSTL标签,这些标签只能运行在服务器中,前端开发人员维护这些页面比较困难,页面加载速度也比较慢 ...

  3. Python字符编码转换

    编码回顾 在备编码相关的课件时,在知乎上看到一段关于Python编码的回答这哥们的这段话说的太对了,搞Python不把编码彻底搞明白,总有一天它会猝不及防坑你一把.不过感觉这哥们的答案并没把编码问题写 ...

  4. 小白python 安装

    小白python 安装: https://blog.csdn.net/qq_36667170/article/details/79275605 https://blog.csdn.net/nmjuzi ...

  5. 【JVM】java对象

    一.对象内存布局 对象在内存中存储可分为3块区域:对象头,实例数据,对齐填充 1.对象头 对象头包含两部分内容. 第一部分:存储对象自身的运行时数据,哈希吗(hashCode),GC分代年龄,锁状态标 ...

  6. 【添加最新版本的mysql的jdbc连接jar包】java.math.BigInteger cannot be cast to java.lang.Long异常

    [问题描述] 从我的电脑把项目拷贝到guo小中的win8电脑,but出现了那个错误,估计他的mysql是最新版本的. [如何下载连接jar包] 链接:https://pan.baidu.com/s/1 ...

  7. 【jar包删除,再添加版本更高的jar】******.jar in project cnnot be read or is not a valid

    把4.2.0删除,然后添加其他版本的jar包

  8. go build Multiple main.go file

    golang 如何编译同目录下多个main文件? 多个go 文件在相同目录编译时候会报错, 可将文件放在不同的package下,结构如下: buidtest/├── a│   └── a.go└── ...

  9. Linux内核启动分析笔记

    一.驱动加载 1.驱动加载调用关系 start_kernel //init/main.c rest_init //最后执行它 kernel_init //使用kernel_thread创建一个进程执行 ...

  10. day43 数据库学习egon的博客 索引

    一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...