
通常,推流服务器会提供一个收流的 RTMP 服务器地址,还会提供一个直播流的流名称,也叫串流密钥。如推流的 RTMP 服务器地址是 rtmp://publish.x.com/live,串流密钥是 stream,那么最后组成的推流地址就是 rtmp://publish.x.com/live/stream。
模拟画面推流:
ffmpeg -re -f lavfi -i testsrc=s=1280x720:r=25 -pix_fmt yuv420p -vcodec libx264 -f flv rtmp://publish.x.com/live/stream
# -re 控制输入包的读取速度
# -f lavfi 从虚拟输入设备读取
# -i testsrc=s=1280x720:r=25
# s 设置画面大小
# r 设置帧率
# -pix_fmt yuv420p 指定像素格式,将读取的图像像素点颜色格式转换为 yuv420p
# -vcodec libx264 指定编码器
# -f flv 指定输出格式
# rtmp://publish.x.com/live/stream 指定输出地址Open Broadcaster Software (opens new window),简称 OBS,是一款开源的视频录制、直播软件,支持 Windows、macOS 和 Linux。
ffprobe 是 FFmpeg 提供的一个工具,能用来分析音视频容器格式、音视频流信息、音视频包以及音视频帧等信息。
ffprobe -show_format -i <file>filename 文件名nb_streams 流数量nb_programs 程序数量,常见于广电用的 mpegts 流中,如卫视频道节目format_name 容器格式名称format_long_name 容器格式详细信息start_time 容器中正常的显示开始时间duration 容器文件时长size 文件大小bit_rate 文件总比特率(码率)probe_score 探测分数,越大越准确,用于确定使用哪个容器模块来解析 probe 文件tags 容器格式的元数据信息 major_brand 主要的容器格式minor_version 容器格式的版本compatible_brands 兼容的容器格式creation_time 文件创建时间encoder 文件编码器ffprobe -show_streams -i <file>index 流索引codec_name 流的编码名codec_long_name 流编码详细描述profile 编码器配置文件codec_type 流类型,音频流或视频流codec_time_base 流的时间基codec_tag_string 流的标签codec_tag 流的标签,十六进制存储width 视频流的宽度height 视频流的高度coded_width 视频流的编码宽度,用于对齐coded_height 视频流的编码高度has_b_frames 是否有 B 帧sample_aspect_ratio 视频流的采样比例display_aspect_ratio 视频流的显示图像比例pix_fmt 视频流的像素点格式level 视频流的级别color_range 视频流的颜色范围color_space 视频流的色域color_transfer 视频流的色彩转换color_primaries 视频流的原色参数chroma_location 视频流的色度位置field_order 扫描方式refs 视频流的参考帧数is_avc 是否是 AVC 视频流nal_length_size NAL 长度r_frame_rate 视频流的实际帧率avg_frame_rate 视频流的平均帧率time_base 视频流的时间基,通常与帧率有关start_pts 视频流的开始时间戳start_time 视频流的开始时间duration_ts 视频流的时长(以时间戳为单位)duration 视频流的时长bit_rate 视频流的比特率max_bit_rate 视频流的最大比特率bits_per_raw_sample 原始视频采样占位nb_frames 视频流的帧数extradata_size 视频流的附加数据大小disposition 描述视频流的标志位 default 当前是默认流dub 当前是重配音流original 当前是原始流comment 当前流含有注释lyrics 当前流含有歌词karaoke 当前流含有卡拉 OK 信息forced 当前流含强制字幕流hearing_impaired 当前流含有听觉障碍信息visual_impaired 当前流含有视觉障碍信息clean_effects 当前流已经清除了特效attached_pic 当前流含有附加图片tags 流的元数据信息 creation_time 流的创建时间language 流的语言handler_name 流的处理器名称vendor_id 编码器厂商encoder 流的编码器ffprobe -show_packets -i <file>:将音视频所有包列出来 select_streams:选择流,可以是流索引,也可以是流类型,如 select_streams=v:0 表示选择视频流索引为 0 的流,select_streams=a 表示选择所有音频流sohw_entries:指定输出的内容of:输出格式,可以是 csv、json、xml、flat、default,默认为 defaultcodec_type 流类型stream_index 流索引pts 时间戳ffprobe -show_frames -i <file>:将音视频所有帧列出来音视频封装容器、音视频流、音视频包、音视频帧之间对应的关系:

以 MPEGTS 封装为例,封装里面包含 3 个流,分别是视频流,音频流,字幕流,视频流中需要存储对应的视频编码参数信息,用来在解码器解码时使用,而视频、音频和字幕流在存储或者传输的时候是一一对应的,如果偏差太大的话会造成音视频不同步问题。
FFmepeg 不用指定输出:
ffmpeg -i a.mp4 b.mp4 -vcodec mpeg4 c.mp4
# b.mp4 没有指定 vcodec 采用 a.mp4 的编码
# c.mp4 指定了 vcodec 采用 mpeg4 编码如果想要指定编码,每个输出格式都需要输出对应的编码,如果不想重新编码,可以使用 -vcodec copy,-acodec copy、-scodec copy,来只转封装不转码(做解码后再编码)的操作。不做视频转码操作的话,会节省 CPU 的计算资源,CPU 占用率会降低很多,但是如果输入的视频码率特别高的话,文件也会特别大,这种情况做一下转码还是有必要的。
FFmpeg 的命令行参数分布:
ffmpeg [第一个输入文件对应解析参数] -i [第一个输入文件] [第二个输入文件对应解析参数] -i [第二个输入文件] ... [输出文件对应解析参数] [输出文件]ffmpeg --help:查看所有模块的帮助信息 -h:查看模块的简单帮助信息-long:查看模块的更多高级操作-full:查看模块的所有帮助信息[type]=[name] 查看指定模块的帮助信息 ffmpeg -h muxer=mp4 查看 mp4 封装的帮助信息ffmpeg -h encoder=libx264 查看 libx264 编码器的帮助信息-report:输出日志-v:设置日志级别 quiet:不输出任何日志panic:输出错误日志fatal:输出错误日志error:输出错误日志warning:输出警告日志info:输出信息日志verbose:输出详细日志debug:输出调试日志trace:输出跟踪日志-i:输入文件-f:输出文件格式-y:覆盖输出文件-ss:指定开始时间 -ss 指定的位置最好是关键帧位置-ss 参数放在 -i 参数左侧来定位开始的位置会比放在右侧快很多,但是需要注意使用关键帧位置,否则会不准确-t:指定持续时间-codec:指定编码器 -codec:v copy -an:去掉音频流(-an,audio none)-metadata:指定元数据,如标题、作者等-r 指定帧率-vb 指定视频码率-vframes 指定帧数-s 指定分辨率-aspect 指定宽高比-vn 去掉视频流-vf 给视频做简单滤镜处理-ar 指定采样率-ab 指定音频码率-aframes 指定帧数-ac 指定声道数-an 去掉音频流-af 给音频做简单滤镜处理-vol 指定音量-filter_complex:可以将音视频混合在一条参数字符串里进行操作,可以输入、输出多个视频流和音频流 -filter_script:当命令行参数过长的时候,可以使用外挂脚本来进行操作-copytb:设定 timebase 与输入的相同,确保时间戳不会跳变,有一定风险-force_key_frames:强制关键帧设定,支持表达式MP4 标准非常灵活,可扩展性比较好,有很多常见的格式是基于 MP4 做了一些扩展,然后被应用到比较广的范围,比如 CMAF、DASH、HLS。而且 MP4 的参考标准是一个开放的标准,通常以编号为 ISO-14496-12 来查找标准文档。

查看 MP4 的 muxer 对应的参数:
ffmpeg -h muxer=mp4
常见参数:
faststart:将 moov box 放在文件头部,方便播放器快速开始播放
ffmpeg -i input.flv -c copy -f mp4 -movflags faststart output.mp4DASH 参数:生成 DASH 格式时,里面有特殊 MP4 格式,可以理解为 MP4 切片
ffmpeg -i input.flv -c copy -f mp4 -movflags dash output.mp4FFmpeg 在解析 MP4 文件格式的时候,可能会因为 MP4 的内容生成得不标准产生一些奇奇怪怪的问题,如音视频不同步或者视频抖动等问题。FFmpeg 针对出现的这类问题也做了格式上的兼容,但用户可能需要自己手动设置一些参数,定制一下,才可以解决这些问题。
查看 MP4 的 demuxer 对应的参数:
ffmpeg -h demuxer=mp4
# Demuxer mov,mp4,m4a,3gp,3g2,mj2 [QuickTime / MOV]:
# Common extensions: mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v.
# mov,mp4,m4a,3gp,3g2,mj2 AVOptions:
# -use_absolute_path <boolean> .D.V....... allow using absolute path when opening alias, this is a possible security issue (default false)
# -seek_streams_individually <boolean> .D.V....... Seek each stream individually to the closest point (default true)
# -ignore_editlist <boolean> .D.V....... Ignore the edit list atom. (default false)
# -advanced_editlist <boolean> .D.V....... Modify the AVIndex according to the editlists. Use this option to decode in the order specified by the edits. (default true)
# -ignore_chapters <boolean> .D.V....... (default false)
# -use_mfra_for <int> .D.V....... use mfra for fragment timestamps (from -1 to 2) (default auto)
# auto -1 .D.V....... auto
# dts 1 .D.V....... dts
# pts 2 .D.V....... pts
# -export_all <boolean> .D.V....... Export unrecognized metadata entries (default false)
# -export_xmp <boolean> .D.V....... Export full XMP metadata (default false)
# -activation_bytes <binary> .D......... Secret bytes for Audible AAX files
# -audible_key <binary> .D......... AES-128 Key for Audible AAXC files
# -audible_iv <binary> .D......... AES-128 IV for Audible AAXC files
# -audible_fixed_key <binary> .D......... Fixed key used for handling Audible AAX files
# -decryption_key <binary> .D......... The media decryption key (hex)
# -enable_drefs <boolean> .D.V....... Enable external track support. (default false)FFmpeg 为什么会给 MP4 的 demuxer 加这么多兼容性的参数呢?
因为可以生成和处理 MP4 文件的工具不止 FFmpeg,还有其他的工具,例如 GPAC、Shaka-Packager。因此,生成出来的 MP4 文件可能不统一,存在一定的差异,这个差异就可能引起兼容性问题。
Modular Multimedia framework for packaging, streaming and playing your favorite content, see http://netflix.gpac.io (opens new window).
A media packaging and development framework for VOD and Live DASH and HLS applications, supporting Common Encryption for Widevine and other DRM Systems, see https://shaka-project.github.io/shaka-packager/html/ (opens new window).
使用 CPU 转码,通常是用 CPU 解码,然后用 libx264、libx265、librav1e 之类的编码器编码,也叫软编码。
转码的基本操作流程:解封装 -> 解码 -> 原始数据 -> 编码 -> 封装。
libx264 在 FFmepeg 中支持的参数:
# 查看 libx264 支持的参数
ffmpeg -h encoder=libx264通常统一编码成 yuv420p ,如果确定播放器可以支持 HDR 的话,也可以考虑用 yuv420p10le。但是如果想要在 Web 浏览器上正常播放出来的话,yuv420p 是最稳定的格式。
为了解决设置编码参数时参数太多、太琐碎的问题,libx264 提供了预置模板 preset,在 FFmpeg 里默认用的是 medium 模板,也就是平衡画质与编码速度的最优选择。
除了 preset 模板,还有调优类型的模板 tune,包括 film、animation、grain、stillimage、psnr、ssim、fastdecode、zerolatency 等不同的模版。

不同的模板支持的参数也略有差别,比如视频编码想做画面延迟低的直播流的话,可以考虑设置 tune 为 zerolatency。因为 zerolatency 模板里已经包含了低延迟编码的参数。

宏块树是一种视频编码结构,在编码时它可以增加 slice 处理的层数,降低视频编码的码率,但是复杂度会略有提升,所以耗时也会增加一些。
slice 的的意思是将一帧图像切成多个切片,然后将多个片放到多个线程里处理,从而达到并发处理的的目的。因为 lookahead 是 0,不需要提前预存多个帧做缓存,也没有双向参考帧 B 帧,不需要预读多个帧做缓存,所以最大限度地降低了帧缓存引起的画面延迟。
在给视频转码做转码的时候,有时也会被要求转成恒定码率的视频流,即 CBR ,它可以通过参数 nal-hrd cbr 来设置,但是实际的码率不一定能够控制得很好,所以通常会搭配 FFmpeg 的 maxrate、minrate 与 bufsize 来精确地控制码率,一般 bufsize 控制比 maxrate 小大概 1/3 ~ 1/2 即可。
如果使用当前 FFmpeg 里面的 libx264 参数无法达到要求,但用 x264 没问题的话,可以通过 FFmpeg 预留的 x264opts 来设置更多 x264 的参数。
用 CPU 转码的话,对 CPU 的消耗会比较高,用 GPU 转码可以节省一些 CPU 计算资源。
FFmpeg 支持的硬件加速方案:
HandBrake (opens new window) is a open-source tool, built by volunteers, for converting video from nearly any format to a selection of modern, widely supported codecs.