目录
-
一.简介
, Download FFmpeg 官网地址
FFmpeg全称为Fast Forward Moving Picture Experts Group(mpeg:动态图像专家组),于2000年诞生,是一款免费,开源的音视频编解码工具及开发套件。它的功能强大,用途广泛,大量用于视频网站和商业软件(比如 Youtube 和 iTunes)。
FFmpeg 本身是一个庞大的项目,包含许多组件和库文件,最常用的是它的命令行工具,FFmpeg既是一款音视频编解码工具,同时也是一组音视频编解码开发套件,作为编解码开发套件,它为开发者提供了丰富的音视频处理的调用接口。FFmpeg提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种色彩格式转换、多种采样率转换、多种码率转换等;FFmpeg框架提供了多种丰富的插件模块,包含封装与解封装的插件、编码与解码的插件等。
FFmpeg是一个很全面的图像处理套件。
-
FFmpeg框架的基本组成包含:
各个函数库的作用
libavcodec:编解码库。支持MPEG4、AAC、MJPEG等自带的媒体编解码格式等 * 支持第三方的编解码器:H.264(AVC)编码,需要使用x264编码器;H.265(HEVC)编码,需要使用x265编码器;MP3(mp3lame)编码,需要使用libmp3lame编码器 如果希望增加自己的编码格式,或者硬件编解码,则需要在AVCodec中增加相应的编解码模块
libavformat:音视频容器格式以及所支持的协议的封装和解析。文件封装格式:MP4、FLV、KV、TS等 * 网络协议封装格式:RTMP、RTSP、MMS、HLS等
libavutil:提供了一些公共函数,工具库。
libavfilter:音视频的滤镜库,如视频加水印、音频变声等。
libavdevice:支持众多设备数据的输入与输出,如读取摄像头数据、屏幕录制。
libswresample, libavresample:提供音频的重采样工具库。
libswscale:提供对视频图像进行色彩转换、缩放以及像素格式转换,如图像的 YUV 转换。
libpostproc:多媒体后处理器。
-
二. FFmpeg框架梳理音视频的流程
基本概念:
容器(Container) 容器就是一种文件格式,比如flv,mkv等。包含下面5种流以及文件头信息。
流(Stream) 是一种视频数据信息的传输方式,5种流:音频,视频,字幕,附件,数据。
帧(Frame) 帧代表一幅静止的图像,分为I帧,P帧,B帧。
编解码器(Codec) 是对视频进行压缩或者解压缩,CODEC =Code (编码) +DECode(解码)
复用/解复用(mux/demux) 把不同的流按照某种容器的规则放入容器,这种行为叫做复用(mux) 把不同的流从某种容器中解析出来,这种行为叫做解复用(demux),FFmpeg是否支持某种媒体封装格式,取决于编译时是否包含了该格式的封装库。根据实际需求,可进行媒体封装格式的扩展,增加自己定制的封装格式,即在AVFormat中增加自己的封装处理模块
-
三.ffmpeg、ffplay、ffprobe区别
4.1 ffmpeg是用于转码的应用程序
4.2 fffplay是用于播放的应用程序
4.3 ffprobe是用于查看文件格式的应用程序
五.常见的文件格式、编码
5.1 常见的视频格式、文件格式
5.2 常见的编码音频转码格式
-
MP4封装:H264视频编码+AAC音频编码(比较成熟)
-
WebM封装:VP8视频编码+Vorbis音频编码(谷歌方案)
-
OGG封装:Theora视频编码+Vorbis音频编码(开源)
六,编译ffmepg脚本
#!/bin/bash
# 以下路径需要修改成自己的NDK目录
TOOLCHAIN=/Users/lh/Library/Android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64
# 最低支持的android sdk版本
API=21
function build_android
{
echo "Compiling FFmpeg for $CPU"
./configure \
--prefix=$PREFIX \
--disable-shared \
--enable-static \
--disable-avdevice \
--enable-small \
--disable-muxers \
--disable-filters \
--enable-gpl \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-mno-stackrealign -Os $OPTIMIZE_CFLAGS -fPIC" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make -j16
make install
echo "The Compilation of FFmpeg for $CPU is completed"
}
# armv8-a
ARCH=arm64
CPU=armv8-a
# r21版本的ndk中所有的编译器都在/toolchains/llvm/prebuilt/darwin-x86_64/目录下(clang)
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
# NDK头文件环境
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
# so输出路径
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
build_android
# 交叉编译工具目录,对应关系如下
# armv8a -> arm64 -> aarch64-linux-android-
# armv7a -> arm -> arm-linux-androideabi-
# x86 -> x86 -> i686-linux-android-
# x86_64 -> x86_64 -> x86_64-linux-android-
# CPU架构
# armv7-a
ARCH=arm
CPU=armv7-a
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
build_android
运行./buildsh.sh
编译成功以后的产物
6.1 ffmpeg核心工具
ffmpeg提供了以下三个工具
____ffmpeg # 用于音视频编解码等等
| |____ffplay # 用于播放音视频文件、流媒体数据等等
| |____ffprobe # 用于查看文件封装格式、音视频编码格式等等详细信息
# ffmpeg [全局参数] [[输入文件参数] -i 输入文件]... {[输出文件参数] 输出文件}...
$ ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...
获取视频信息
./ffmpeg -i /Users/lh/Downloads/test.mp4
这部分信息表明了该文件的
Metadata信息:
major_brand字段表示该文件的封装格式为mp42(MP4格式的子规范),文件创建时间为 2023-07-21T03:32:06.000000Z,视频持续时间为00:00:07.86(71秒86),开始播放的时间是从0.000300ms,文件的比特率是1457 kb/s
第一路视频信息:
在介绍该部分信息之前,需要先知道几个专业术语,即关于时间基相关的定义:
tbr 表示帧率,该参数倾向于一个基准,往往tbr跟fps相同
tbn 表示视频流 timebase(时间基准),比如ts流的timebase 为90000,flv格式视频流timebase为1000
tbc 表示视频流codec timebase ,对于264码流该参数通过解析sps间接获取(通过sps获取帧率)
这部分信息表示文件的第一股流是视频流,编码方式是H264的格式,封装格式是AVC1,帧的数据格式是yuv420p,分辨率是480x640,比特率是1450 kb/s
6.2转换视频
把mp4格式的视频,转化成flv格式
./ffmpeg -i /Users/lh/Downloads/test.mp4 /Users/lh/Downloads/aaa.flv
下面列举出了具体的转换过程
6.3转换裁剪
./ffmpeg -ss 00:00:03 -i /Users/lh/Downloads/test.mp4 -vcodec copy -acodec copy -t 00:00:6 /Users/lh/Downloads/output.mp4
把test.mp4从第三秒开始裁剪到第六秒,下面是裁剪过程
6.3 视频静音
./ffmpeg -i /Users/lh/Downloads/210710171112971120.mp4 -af "volume=enable='between(t,5,10)':volume=0" /Users/lh/Downloads/output.mp4
说明:该命令的作用是将210710171112971120.mp4视频按照指定时间静音,生成一个新的output.mp4视频。volume=enable='between(t,5,10)':volume=0 静音从第5秒到第10秒,这个命令可以写多个,即多处静音,中间逗号隔开
6.4 视频添加水印
./ffmpeg -i /Users/lh/Downloads/210710171112971120.mp4 -vf "movie=/Users/lh/Downloads/shuiyin.jpeg,colorchannelmixer=aa=0.4,scale=300:300 [watermark]; [in][watermark] overlay" /Users/lh/Downloads/output.mp4
说明:
该命令的作用是将input.mp4视频按照指定命令,打上水印,生成一个新的output.mp4视频。
movie=input.png 水印图片、
colorchannelmixer=aa=0.4 水印透明度(如果不需要更改透明度,则把该段去掉)
scale=300:300 水印的大小(如果用原水印大小,则把该段去掉)
overlay 水印的位置,默认为左上角
overlay=W-w 右上角
overlay=0:H-h 左下角
overlay=W-w:H-h 右下角
ps:如果水印不需要贴边显示,稍微更改W和H的值即可
视频添加水印的效果
如果要放在左下角
./ffmpeg -i /Users/lh/Downloads/210710171112971120.mp4 -vf "movie=/Users/lh/Downloads/shuiyin.jpeg,colorchannelmixer=aa=0.4,scale=300:300 [watermark]; [in][watermark] overlay=W-w:H-h" /Users/lh/Downloads/output.mp4
效果图下图
6.5 视频变速
./ffmpeg -i /Users/lh/Downloads/210710171112971120.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" /Users/lh/Downloads/output.mp4
说明:
该命令的作用是将210710171112971120.mp4 视频按照指定倍速,生成一个新的output.mp4视频。setpts=0.5*PTS 视频加速(默认为1,现在是0.5。变成2倍速了)
atempo=2.0 音频加速(默认为1,现在是0.5.变成2倍速了)
ps:视频加速和音频加速,倍速需要一致,否则声音视频会不同步
其实就是相当于我们在快进视频2倍速的速度播放视频,比如我们经常会在有些视频网站看到x1.2,x1.5,x2倍速播放视频
6.6 视频增加马赛克
如果需要给视频或图片添加马赛克,可以使用 boxblur
滤镜。该滤镜将指定区域变成模糊效果,从而达到马赛克的效果。以下是一个简单的例子:
./ffmpeg -i /Users/lh/Downloads/210710171112971120.mp4 -filter_complex "[0:v]boxblur=10[blur];[blur]crop=200:200:300:300,boxblur=10[cropped];[0:v][cropped]overlay=300:300" /Users/lh/Downloads/output.mp4
说明
其中 -i 210710171112971120.mp4 表示指定输入文件。[0:v]boxblur=10[blur] 表示对视频画面进行模糊处理,模糊半径为 10 像素,保存为一个中间变量 blur。[blur]crop=200:200:300:300,boxblur=10[cropped] 表示对模糊后的视频画面进行裁剪,只保留左上角起始坐标为 (300, 300),宽高为 200 的区域,并再次进行模糊处理,保存为一个中间变量 cropped。最后使用 overlay 滤镜将原始视频和裁剪后的带马赛克画面叠加在一起,生成新的视频文件 output.mp4。
如果需要调整马赛克的大小、位置、形状等属性,可以加入不同的参数进行设置。
如果视频中的水印和马赛克无法通过软件工具进行剔除,可以尝试使用 FFmpeg 或类似的工具,在视频上添加其他的图层来遮盖住这些区域
下面是打码效果
6.7 视频截图
./ffmpeg -i /Users/lh/Downloads/210710171112971120.mp4 -y -f mjpeg -ss 30 -t 1 /Users/lh/Downloads/test1.jpg
说明:
-f mjpeg 指定格式化的格式为mjpeg,
-ss 30 从第30秒开始截取
-t 1 截取一帧
效果如下图
6.8 图片添加水印
./ffmpeg -i /Users/lh/Downloads/test1.jpg -i /Users/lh/Downloads/shuiyin.jpeg -filter_complex "overlay=W-w-10:H-h-10:alpha=0.5" /Users/lh/Downloads/output.jpg
说明:
其中 W
和 H
表示视频画面的宽度和高度,w
和 h
分别表示水印图片的宽度和高度。alpha=0.5
表示设置水印透明度为 0.5
效果如下图
6.9 图片合成视频
/ffmpeg -i /Users/lh/Downloads/imgs/img_%1d.jpeg /Users/lh/Downloads/out.mp4
把/Users/lh/Downloads/imgs/这个目录下面的6张图片合并成一个视频
输出结果:
6.10 视频添加字幕
首先创建字幕文件
cat zimu.srt
1
00:00:01,000 --> 00:00:02,000
大家好,我是测试ffmepg的开发人员,这是第一条字幕
2
00:00:02,000 --> 00:00:05,000
本次我想和大家分享利用ffmpeg制作字幕的方法
3
00:00:05,000 --> 00:00:10,000
本次我想和大家分享利用ffmpeg制作字幕的方法
4
00:00:10,000 --> 00:00:20,000
本次我想和大家分享利用ffmpeg制作字幕的方法
./ffmpeg -i /Users/lh/Downloads/210710171112971120.mp4 -lavfi "subtitles=/Users/lh/Downloads/zimu.srt :force_style='Alignment=2,MarginV=5'" -y /Users/lh/Downloads/output.mp4
效果如下
6.11 播放网络视频并且设置窗口标题为http stream
./ffplay -window_title "http stream" http://vfx.mtime.cn/Video/2021/07/10/mp4/210710171112971120.mp4
效果如下
6.12 ffplay播放网络视频并且强制解码器
./ffplay -vcodec h264 -window_title "http stream" http://vfx.mtime.cn/Video/2021/07/10/mp4/210710171112971120.mp4
强制解码器为h264
效果如下
6.13 ffplay播放网络视频并且旋转视频
./ffplay -window_title "http stream" http://vfx.mtime.cn/Video/2021/07/10/mp4/210710171112971120.mp4 -vf transpose=1
6.14 ffplay播放网络视频并且仅音频变速
./ffplay -window_title "http stream" http://vfx.mtime.cn/Video/2021/07/10/mp4/210710171112971120.mp4 -af atempo=2
6.15 ffplay播放网络视频并且仅视频变速
./ffplay -window_title "http stream" http://vfx.mtime.cn/Video/2021/07/10/mp4/210710171112971120.mp4 -vf setpts=PTS/2
6.16 ffplay播放网络视频并且音视频同时变速
./ffplay -window_title "http stream" http://vfx.mtime.cn/Video/2021/07/10/mp4/210710171112971120.mp4 -vf setpts=PTS/2 -af atempo=2
上述这个操作也就是我们经常说的seek视频
6.17 ffprobe以json格式显示每个流的信息
./ffprobe -print_format json -show_streams ~/Downloads/out.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/lh/Downloads/out.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf60.10.100
Duration: 00:00:00.12, start: 0.000000, bitrate: 12170 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt470bg/unknown/unknown, progressive), 1080x1080 [SAR 1:1 DAR 1:1], 12110 kb/s, 25 fps, 25 tbr, 12800 tbn (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
encoder : Lavc60.22.100 libx264
"streams": [
{
"index": 0,//多媒体的stream索引;
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "High",
"codec_type": "video", //多媒体类型,例如视频包,音频包等
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 1080,
"height": 1080,
"coded_width": 1080,
"coded_height": 1080,
"closed_captions": 0,
"film_grain": 0,
"has_b_frames": 2,
"sample_aspect_ratio": "1:1",
"display_aspect_ratio": "1:1",
"pix_fmt": "yuvj420p",
"level": 32,
"color_range": "pc",
"color_space": "bt470bg",
"chroma_location": "center",
"field_order": "progressive",
"refs": 1,
"is_avc": "true",
"nal_length_size": "4",
"id": "0x1",
"r_frame_rate": "25/1",
"avg_frame_rate": "25/1",
"time_base": "1/12800",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 1536,
"duration": "0.120000",
"bit_rate": "12110800",
"bits_per_raw_sample": "8",
"nb_frames": "3",
"extradata_size": 53,
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0,
"captions": 0,
"descriptions": 0,
"metadata": 0,
"dependent": 0,
"still_image": 0
},
"tags": {
"language": "und",
"handler_name": "VideoHandler",
"vendor_id": "[0][0][0][0]",
"encoder": "Lavc60.22.100 libx264"
}
}
]
}
6.18 ffprobe以json格式显示帧信息
./ffprobe -print_format json -show_frames ~/Downloads/out.mp4
"frames": [
{
"media_type": "video",
"stream_index": 0,
"key_frame": 1,
"pts": 0,
"pts_time": "0.000000",
"pkt_dts": 0,
"pkt_dts_time": "0.000000",
"best_effort_timestamp": 0,
"best_effort_timestamp_time": "0.000000",
"pkt_duration": 512,
"pkt_duration_time": "0.040000",
"duration": 512,
"duration_time": "0.040000",
"pkt_pos": "48",
"pkt_size": "112313",
"width": 1080,
"height": 1080,
"crop_top": 0,
"crop_bottom": 0,
"crop_left": 0,
"crop_right": 0,
"pix_fmt": "yuvj420p",
"sample_aspect_ratio": "1:1",
"pict_type": "I",
"coded_picture_number": 0,
"display_picture_number": 0,
"interlaced_frame": 0,
"top_field_first": 0,
"repeat_pict": 0,
"color_range": "pc",
"color_space": "bt470bg",
"chroma_location": "center",
"side_data_list": [
{
"side_data_type": "H.26[45] User Data Unregistered SEI message"
}
]
},
{
"media_type": "video",
"stream_index": 0,
"key_frame": 0,
"pts": 512,
"pts_time": "0.040000",
"best_effort_timestamp": 512,
"best_effort_timestamp_time": "0.040000",
"pkt_duration": 512,
"pkt_duration_time": "0.040000",
"duration": 512,
"duration_time": "0.040000",
"pkt_pos": "112361",
"pkt_size": "35468",
"width": 1080,
"height": 1080,
"crop_top": 0,
"crop_bottom": 0,
"crop_left": 0,
"crop_right": 0,
"pix_fmt": "yuvj420p",
"sample_aspect_ratio": "1:1",
"pict_type": "P",
"coded_picture_number": 1,
"display_picture_number": 0,
"interlaced_frame": 0,
"top_field_first": 0,
"repeat_pict": 0,
"color_range": "pc",
"color_space": "bt470bg",
"chroma_location": "center"
},
{
"media_type": "video",
"stream_index": 0,
"key_frame": 0,
"pts": 1024,
"pts_time": "0.080000",
"best_effort_timestamp": 1024,
"best_effort_timestamp_time": "0.080000",
"pkt_duration": 512,
"pkt_duration_time": "0.040000",
"duration": 512,
"duration_time": "0.040000",
"pkt_pos": "147829",
"pkt_size": "33881",
"width": 1080,
"height": 1080,
"crop_top": 0,
"crop_bottom": 0,
"crop_left": 0,
"crop_right": 0,
"pix_fmt": "yuvj420p",
"sample_aspect_ratio": "1:1",
"pict_type": "P",
"coded_picture_number": 2,
"display_picture_number": 0,
"interlaced_frame": 0,
"top_field_first": 0,
"repeat_pict": 0,
"color_range": "pc",
"color_space": "bt470bg",
"chroma_location": "center"
}
]
}