这周周末尝试把我硬盘上面的视频文件压缩了一下,但是效果并不理想。其中主要有两个原因,

  • 视频本来就是h264的编码,再重新编码也没啥用,因为限制大小的主要是码率
  • ffmpeg GPU加速版的h265编码器有些问题

导致有些文件使用hevc_nvenc编码器会编码失败,最终不能播放。所以最终还是重新压制了h264,但是这么干最终只是把码率降了下来。最终使用命令如下

ffmpeg -i 1.mp4 -c:v xlib264_nvenc -y 2.mp4

经过各种查询资料之后发现默认的参数就差不多是最适合我的了,如果要指定码率,那就需要考虑每个原文件的码率都不一样,这样的话压缩之后的目标码率也不一样。而ffmpeg的默认参数把码率都放到了2300左右,能看到有损失画质,但是大概可以接受吧 (手机播放的话)

首先说明一个困惑我的问题

AVC 就是h264

HEVC 就是h265

一些比较重要的参数举例

首先举个例子,这个例子里面就包含了几个比较常用的参数

ffmpeg -i a.mp4 -c:v libx264 -preset veryslow -crf 18 -c:a copy b.mp4

ffmpeg

这个也算哈,去这里下载Download FFmpeg,然后为了方便起见我会把这个文件放到我的用户目录,也就是Users\Administrator\然后添加系统变量,让我哪里都能用。

-i

它后面的a.mp4就是输入的文件,最后面b.mp4是输出的文件

-c:v

这个是重点,后面的参数表示使用什么编码器,具体有什么编码器使用ffmpeg -codecs 看所有编码,比如说h264的条目

DEV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_qsv h264_cuvid ) (encoders: libx264 libx264rgb h264_amf h264_nvenc h264_qsv nvenc nvenc_h264 )
  • 最前面表示的是属性,有以下几个属性

     D..... = Decoding supported	// 支持解码
    .E.... = Encoding supported // 支持编码
    ..V... = Video codec // 视频编码
    ..A... = Audio codec // 音频编码
    ..S... = Subtitle codec // 字幕编解码器 (没用过不清楚)
    ...I.. = Intra frame-only codec// 仅帧内编解码器 (没用过不清楚)
    ....L. = Lossy compression // 有损压缩
    .....S = Lossless compression // 无损压缩
  • h264是编码名称,后面H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 应该都是别称

  • decoders 是解码器 (h264 h264_qsv h264_cuvid)

  • encoders 是编码器 (libx264 libx264rgb h264_amf h264_nvenc h264_qsv nvenc nvenc_h264)

后面这个编码器是比较重要的属性,就是可以跟在-c:v参数后面的值,比如我想压缩成h264编码,可以写libx264,如果是h264_nvenc 表示使用GPU加速,需要注意的是英伟达的显卡是h264_nvenc如果是AMD的显卡应该是h264_amf 其他的几个选项不清楚,没有使用过。

通过上面的内容就知道了编码器有什么了,接下来优化参数怎么写呢?

-preset

这个是编码器的参数,一般来说有以下取值

preset值 释义
ultrafast 极快
superfast 超快
veryfast 非常快
faster 更快
fast
medium
slow
slower 更慢
veryslow 非常慢
placebo 超慢

但是好像不同的版本支持是不一样的,所以,需要自行查看取值,通过ffmpeg -h encoder=libx264 查看编码器的帮助

如果选择特别慢,那么编码就会很慢,但是文件会相对小一点 (是这么说,但是我似乎把一个2GB的文件编码成了36GB码率124M,还不是很清楚为啥)

比如我执行完毕之后可以知道下面的信息

  -preset            <string>     E..V....... Set the encoding preset (cf. x264 --fullhelp) (default "medium")
-tune <string> E..V....... Tune the encoding params (cf. x264 --fullhelp)
-profile <string> E..V....... Set profile restrictions (cf. x264 --fullhelp)
-fastfirstpass <boolean> E..V....... Use fast settings when encoding first pass (default true)
-level <string> E..V....... Specify level (as defined by Annex A)
-passlogfile <string> E..V....... Filename for 2 pass stats
-wpredp <string> E..V....... Weighted prediction for P-frames
-a53cc <boolean> E..V....... Use A53 Closed Captions (if available) (default true)
-x264opts <string> E..V....... x264 options
-crf <float> E..V....... Select the quality for constant quality mode (from -1 to FLT_MAX) (default -1)
-crf_max <float> E..V....... In CRF mode, prevents VBV from lowering quality beyond this point. (from -1 to FLT_MAX) (default -1)
-qp <int> E..V....... Constant quantization parameter rate control method (from -1 to INT_MAX) (default -1)

总之是相当多,每个编码器不同,支持的选项都不一样,最好通过ffmpeg -h encoder=libx264 查看一下,否则等了很久转码完毕之后发现参数不对就很浪费时间。

-crf

是用来控制码率的,一般取值是在0-51,据说18-28是比较常见的取值范围,数字越小质量越好。

我编码的时候-crf 25码率好像在2000k左右,具体不知道它怎么确定码率的。

使用GPU加速

需要说明的是GPU加速是编码器的功能,通过ffmpeg -codecs列出所有的编码器,然后找有nvenc字样的编码器,比如h264_nvenc 这个编码器就是使用了GPUh264编码器,要注意这个编码器和libx264的优化参数不一样,需要去专门看它的优化参数。

可以通过 ffmpeg -codecs | grep nvenc找出来,windows使用ffmpeg -codecs | findstr nvenc 命令 (我看好像就h265h264有对应的GPU加速版本 分别是hevc_nvench264_nvenc)

python获取视频码率

首先需要把ffprobe.exe的路径添加到系统变量里面,基本思想是通过ffprobe命令得到视频信息,通过参数指定输出结果是json格式,通过管道拿到结果,然后json.loads()得到字典。

import os,json
import shlex
from subprocess import Popen, PIPE def getJsonString(strFileName):
strCmd = 'ffprobe.exe -v quiet -print_format json -show_format -show_streams -i "' + strFileName + '"'
# print (strFileName)
cmd = shlex.split(strCmd)
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
o, e = p.communicate()
# print(o.decode("utf-8")) mystring = o.decode("utf-8")
# mystring = os.popen(strCmd).read().encode('gbk')
# mystring = os.popen(strCmd).read().decode('gbk')
# mystring = os.popen(strCmd).buffer.read().decode(encoding='utf-8') return mystring def get_rate(file_name):
info = getJsonString(file_name)
info = json.loads(info)
# print (info["format"]["bit_rate"])
return int(info["format"]["bit_rate"]) print(get_rate(r"C:\Users\Administrator\Documents\1\视频\001.mp4"))

上面代码是能运行的,其中我使用了os.popen()但是如果命令执行结果返回了中文,就会出现编码错误。所以根据网上建议使用了subprocess里面的管道。

压缩图片

ffmpeg -i p.jpg -q 1000 p2.jpg

目前测试只有jpg文件可以压缩,-q参数约大压缩程度越高


总之,ffmpeg的使用是一个相当复杂的事情,需要花很久去研究参数,上面只是一些简单的参数,执行了ffmpeg -h encoder=libx264这样的帮助命令之后就知道其内容有多恐怖了,而这个命令显示的还只是一个编码器的参数。。。


相关参考

[win10] ffmpeg gpu加速_THE XING-CSDN博客_ffmpeg gpu加速

ffmpeg参数中文详细解释_雷霄骅(leixiaohua1020)的专栏-CSDN博客_ffmpeg参数详解

ffmpeg 码率控制(总结篇)_隔壁老王呀的专栏-CSDN博客_ffmpeg 码率

最好的帮助是帮助命令

ffmpeg 使用记录的更多相关文章

  1. FFmpeg: mac下手动编译android上使用的FFmpeg(支持x86、armeabi-v7a、arm64-v8a)

    之前一直在linux下编译FFmpeg,最近换电脑了,尝试了下在mac下编译ffmpeg,特记录之. 一. 准备工作 1. 下载FFmpeg.(http://ffmpeg.org/download.h ...

  2. FFmpeg 参数详解(二)

    https://blog.csdn.net/yizhizouxiaqu/article/details/52233673 5.参数选项 如果没有特殊声明,所有的数字参数都以一个字符串代表数字的形式作为 ...

  3. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  4. make V=1 查看完整的gcc编译信息

    Linux内核make命令选项 2012年5月28日lenky发表评论阅读评论6,289 次浏览   升级Linux内核的操作已经变得很简单,基本的几个命令即可搞定:make menuconfig.m ...

  5. Android达到什么水平才能顺利拿到 20k 无压力?

    程序员分很多种类和等级,如果要提高达到20k的概率,有两个条件如果满足的话,则很容易达到: 1.一线城市:北上广深杭 2.互联网行业 如果你非得抬杠,我要在三线城市,做外包要赚20k的话,很难,我自己 ...

  6. 月薪60k,仍无人问津,腾讯阿里到底有多缺这类程序员?

    不知道大家发现没,近几年,国内对音视频人才需求越来越大了,在某招聘网站上居然薪酬高达60k. 从未来的大趋势来看,随着5G时代的到来,音视频慢慢变成人们日常生活中的必须品.除了在线教育.音视频会议.即 ...

  7. Android开发音视频方向学习路线及资源分享,学完还怕什么互联网寒冬?

    接触Android音视频这一块已经有一段时间了,跟普通的应用层开发相比,的确更花费精力.期间为了学习音视频的录制,编码,处理也看过大大小小的几十个项目.总体感觉就是知识比较零散,对刚入门的朋友比较不友 ...

  8. Android音视频开发(1):H264 基本原理

    前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...

  9. 【Android】学习记录<1> -- 初识ffmpeg

    工作需要用到ffmpeg来进行Android的软编码,对这玩意儿一点都不了解,做个学习记录先. FFmpeg:http://www.ffmpeg.org Fmpeg is the leading mu ...

  10. ffmpeg, libav学习记录

    转载自:http://hi.baidu.com/y11022053/item/81f12035182257332e0f8196 一个偶然遇到了ffmpeg,看起来不多,而且通用性很强,算是一个扎实的技 ...

随机推荐

  1. 【VMware vSAN】使用命令行从vSAN集群中移除ESXi主机并加入到新的vSAN集群。

    说明 本文只是陈述了一种方法,不必评判谁对谁错谁好谁坏,选择适合自己的即可. 环境 站点名称 vCenter版本 vSAN集群 集群主机 主机版本 磁盘组 vcsa67.lab.com vCenter ...

  2. STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写

    1.准备材料 正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 ...

  3. 【4】jupyter notebook快速入门、以及常用快捷键使用

    相关文章: [1]Anaconda安装超简洁教程,瞬间学会! [2]Anaconda下:ipython文件的打开方式,Jupyter Notebook中运行.py文件,快速打开ipython文件的方法 ...

  4. 探索C语言中的Shellcode从提取到执行

    ShellCode是一种独立于应用程序的机器代码,通常用于实现特定任务,如执行远程命令.注入恶意软件或利用系统漏洞.在网络安全领域,研究Shellcode是理解恶意软件和提高系统安全性的关键一环.本文 ...

  5. Python PyWin32 模块

    Python的生产效率极高,通过使用pypiwin32模块可以快速调用windows API函数,结合Python的高效开发能力,同等时间内比C++能更快的达到目标,pypiwin32模块封装了Win ...

  6. 【scikit-learn基础】--『回归模型评估』之损失分析

    分类模型评估中,通过各类损失(loss)函数的分析,可以衡量模型预测结果与真实值之间的差异.不同的损失函数可用于不同类型的分类问题,以便更好地评估模型的性能. 本篇将介绍分类模型评估中常用的几种损失计 ...

  7. Spring一套全通3—AOP编程

    百知教育 - Spring系列课程 - AOP编程 第一章.静态代理设计模式 1. 为什么需要代理设计模式 1.1 问题 在JavaEE分层开发开发中,那个层次对于我们来讲最重要 DAO ---> ...

  8. 【栈和队列】纯C实现栈和队列以及其基本操作-宝藏级别数据结构教程【保姆级别详细教学】

    [栈和队列]栈和队列的C语言实现-宝藏级别数据结构教程-超详细的注释和解释 先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力 看完之后别忘记 ...

  9. Linux输出转换命令 xargs

    一.基本用法 xargs命令的作用,是将标准输入转为命令行参数. 原因:大多数命令都不接受标准输入作为参数,只能直接在命令行输入参数,这导致无法用管道命令传递参数 如下面 echo 不接受标准输出做参 ...

  10. 使用KVM创建OEL虚拟机

    在Linux工作站上使用KVM创建虚拟机. 首先说下我的需求: 1.其他LAN内的笔记本也可以连接到这些KVM的虚拟机,因此需要配置使用桥接网络 2.创建一个虚拟机,采用最小化安装系统,作为基础模版, ...