文章目录
- 一、ffmpeg
-
- [1.1 安装](#1.1 安装)
- [1.2 基本参数](#1.2 基本参数)
- 二、ffprobe
-
- [2.1 查编码格式](#2.1 查编码格式)
- [2.2 查视频时长](#2.2 查视频时长)
- 五、视频转流
-
- [5.1 MP4转H264](#5.1 MP4转H264)
- [5.2 H264转MP4](#5.2 H264转MP4)
- [5.3 AVI转MP4](#5.3 AVI转MP4)
- [5.4 MP4转H265](#5.4 MP4转H265)
- 六、视频文件
-
- [6.1 播放](#6.1 播放)
- [6.2 filter 过滤器](#6.2 filter 过滤器)
-
- [6.2.1 crop](#6.2.1 crop)
- [6.3 视频截取](#6.3 视频截取)
- [6.4 视频拼接](#6.4 视频拼接)
- [6.5 获取分辨率](#6.5 获取分辨率)
- 七、视频和图
-
- [7.1 视频抽帧](#7.1 视频抽帧)
- [7.2 视频加图片水印](#7.2 视频加图片水印)
- [7.3 生成 gif](#7.3 生成 gif)
- [7.4 视频帧预览](#7.4 视频帧预览)
- 八、视频和音频
-
- [8.1 音量](#8.1 音量)
一、ffmpeg
bash
ffmpeg -h
ffmpeg -h long
ffmpeg -h full #可重定向到文件查看
ffmpeg -h full | grep h264 # 按关键字grep
ffmpeg -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter/bsf/protocol
1.1 安装
ffmpeg 的 release 是 Linux Static Build ,即静态库(各库已被打包到可执行程序中),而不是动态链接库(共享机器上的 so),所以非常方便部署(sqlite 也是这样),这是ffmpeg官网下载地址
1.2 基本参数
bash
-threads 并行线程数(如ffmpeg -threads 4 -i input.mp4 output.mp4)
二、ffprobe
2.1 查编码格式
bash
ffprobe a.mp4 -show_streams -select_streams v -print_format json | jq
{
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264/AVC/MPEG-4 AVC/MPEG-4 part 10",
"profile": "Main",
"codec_type": "video"
}
]
}
2.2 查视频时长
bash
# 容器时长 container duration (和播放软件看到的时长一样)
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 -i input.mp4 # 输出单位是秒
# 音视频流时长 stream duration
ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
# 容器时长和音视频流时长略有差异
# 一个媒体文件里边有多个音视频流,各个流的时长也未必一样,一般播放器会以video stream的时长作为播放时长
# 另外,并不是所有格式的视频,会在音视频流级别保存了时长,这时可能会拿不到时长
# 解码后的文件播放时长(get duration by decoding), 是最准确的, 但因需解码所以耗时较长
ffmpeg -i input.mp4 -f null - | grep time # 输出形如time=00:02:02.33
五、视频转流
bash
ffmpeg -i a.mp4 -an -c h264 a_h264.mp4
ffplay 可播放本地文件
windows 下的格式工厂可修复视频文件格式
5.1 MP4转H264
bash
ffmpeg -i input.mp4 -vcodec copy -bf 0 -an -bsf: h264_mp4toannexb -f h264 input.h264 # mp4转h264
# -vcodec copy 使用原视频的编码
# -bf 0 移除b帧
# -an 移除音频
# -bsf bitstream_filters A comma-separated list of bitstream filters。其中 h264_mp4toannexb 是mp4解封装时必须加的参数(PS: 而封装为mp4时不需要加)
# -f h264 指定格式
注意,该命令会找时间点附近的 i 帧,所以如果视频本身有 i 帧丢失的话(警告如下),截取的视频会比期望的长:
按时间截取H264,且各段以i帧开头
bash
ffmpeg -i input.h264 -ss 0:05 -to 0:40 -c:v copy -c:a copy a.h264
查看首帧是否为i帧
bash
ffprobe -v quiet -show_frames -select_streams v a.h264 | grep pict_type
将各小h264拼接为大h264
bash
# 写程序实现,读各h264到内存,内存拼接,写文件
# 或者用 ffmpeg
echo "file '1.h264'\nfile '2.h264'" > videos.txt
ffmpeg -y -safe 0 -f concat -i videos.txt -c copy o.h264 # -y 无需交互式确认, -c copy指定不需重新编码, -safe 0 指定不检查各文件名称(防止报错无意义的Unsafe file name)
5.2 H264转MP4
bash
ffmpeg -f h264 -i a.h264 -vcodec copy output.mp4
如果报错Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly则无需理会,因为 ffmpeg 的这个警告不久以后将会被移除。参考
5.3 AVI转MP4
bash
ffmpeg -i 4k-01.avi -c:v h264 4k-01.mp4
5.4 MP4转H265
如果原始视频就是 H265,则我们通过 -v copy 沿用其视频编码格式,防止非常耗时的编解码,所以我们希望把 H265 编码的 MP4 直接转为 H265 裸流。
bash
ffmpeg -i a.mp4 -vcodec copy -bf 0 -an -bsf: hevc_mp4toannexb -f hevc input.h265
# -bsf: hevc_mp4toannexb: 从mp4拷贝到annexB封装
六、视频文件
6.1 播放
bash
ffplay -rtsp_transport tcp rtsp://192.168.2.99/mystream
6.2 filter 过滤器
bash
# 每个 filter 的各参数用冒号分隔。各 filter 之间用逗号分隔。形如下例:
-vf "scale=256:256,transpose=1"
6.2.1 crop
bash
ffmpeg -i a.mp4 -c:v libx264 -vf crop="400:400:100:100" output.mp4 # crop="w:h:x:y" 从视频的x,y处截取w和h的画面。-c:v libx264 是以 h264 重新编码视频
bash
ffmpeg -i a.mp4 -c:v libx264 -vf "crop=iw/3:ih/3" o.mp4 # iw指input width, 设置为了原视频的三分之一。ih 同理
6.3 视频截取
bash
ffmpeg -i input.mp4 -ss 1:05 -t 10 output.mp4
# -ss(即position) 5指定从输入视频第1:05秒开始截取,-t(即duration) 10指明最多截取10秒
# -ss在-i后则会精确定位到1:05秒开始,而且会播放到第1:05后才执行使得更慢运行完
# -t可使用秒数(如-t 10),也可用-t 02:00:10
ffmpeg -ss 1:05 -i input.mp4 -t 10 -c:v copy -c:a copy output.mp4
# 把-ss 1:05放到-i前面则会在第1:05附近的i帧开始,而且会直接找到1:05秒使得更快运行完
# -c:v 和 -c:a分别指定视频和音频的编码格式。
# -c:v copy -c:a copy标示视频与音频的编码不发生改变,而是直接复制,这样会大大提升速度。
6.4 视频拼接
bash
echo "file '1.mp4'\nfile '2.mp4'" > videos.txt
ffmpeg -f concat -i videos.txt -c copy o.mp4 # -c copy指定不需重新编码
6.5 获取分辨率
bash
ffmpeg -hide_banner -rtsp_transport tcp -i rtsp://192.168.2.99/a 2>&1 | grep Video: | grep -Po '\d{3,5}x\d{3,5}' #正则的{m,n}指: 最少匹配 n 次且最多匹配 m 次
# 可能的流分辨率如下:
1920*1080 或 1920 * 1088, 即200w(即1080P)
2560 * 2048, 即400w(即2K), 即2倍1080P的算力
3072 * 2048, 即3倍1080P的算力
3840 * 2160, 即800w(即4K), 即4倍1080P的算力
4096 * 2160, 即5倍1080P的算力
七、视频和图
7.1 视频抽帧
bash
ffmpeg -i a.mp4 -vf "fps=1/10,scale=-2:720" thumbnail-03%d.jpg
# -vf 指定过滤器(filter)
# fps设置输出帧率为十分之一,即每十秒输出一帧
# scale设置输出文件的大小,-2 即 width 自动计算出匹配的偶数, 720 即 指定的 height
ffmpeg -i 666051400.mp4 -r 1 -q:v 2 ./%08d.jpg # 指定帧率1
7.2 视频加图片水印
bash
ffmpeg -i a.mp4 -i lenna.png -filter_complex "overlay=100:100" output.mp4
# overlay=100:100 指定将 图放在视频的 100:100 像素的位置
7.3 生成 gif
注意:gif 自身格式限制了,视频不要太长
bash
ffmpeg -i a.mp4 -ss 0 -t 5 -acodec copy -vcodec copy output.mp4 # 截取视频
ffmpeg -i output.mp4 -s 640x480 -f gif output.gif # -s指定图片分辨率
7.4 视频帧预览
bash
# 预览首帧
ffmpeg -rtsp_transport tcp -i rtsp://192.168.2.99:3355/mystream -frames:v 1 -q:v 1 -y a.jpg
八、视频和音频
8.1 音量
bash
ffmpeg -i a.mp4 -an o.mp4 # 删除音频轨(-vn 删除视频轨、-sn 删除字幕、-db 删除数据流)
ffmpeg -i a.mp4 -af "volume=1.5" o.mp4 # 设置音量大小为 1.5 倍(亲测 99.0 倍也可生效)
ffmpeg -i a.mp4 -af "loudnorm=I=-5:LRA=1" o.mp4 # 统一视频音量
ffmpeg -i a.mp4 -af "equalizer=f=1000:width_type=h:width=200:g=-1" o.mp4 # 添加equalizer(均衡器)