首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >流媒体技术基础

流媒体技术基础

作者头像
Cellinlab
发布2023-05-17 20:45:44
发布2023-05-17 20:45:44
2.6K0
举报
文章被收录于专栏:Cellinlab's BlogCellinlab's Blog

# 直播推流

# FFmepeg 推流

通常,推流服务器会提供一个收流的 RTMP 服务器地址,还会提供一个直播流的流名称,也叫串流密钥。如推流的 RTMP 服务器地址是 rtmp://publish.x.com/live,串流密钥是 stream,那么最后组成的推流地址就是 rtmp://publish.x.com/live/stream

模拟画面推流:

代码语言:javascript
复制
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 指定输出地址

# OBS 推流

Open Broadcaster Software (opens new window),简称 OBS,是一款开源的视频录制、直播软件,支持 Windows、macOS 和 Linux。

# ffprobe 分析音视频

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:输出格式,可以是 csvjsonxmlflatdefault,默认为 default
    • 输出内容
      • codec_type 流类型
      • stream_index 流索引
      • pts 时间戳

# 音视频帧分析

  • ffprobe -show_frames -i <file>:将音视频所有帧列出来

音视频封装容器、音视频流、音视频包、音视频帧之间对应的关系:

以 MPEGTS 封装为例,封装里面包含 3 个流,分别是视频流,音频流,字幕流,视频流中需要存储对应的视频编码参数信息,用来在解码器解码时使用,而视频、音频和字幕流在存储或者传输的时候是一一对应的,如果偏差太大的话会造成音视频不同步问题。

# FFmpeg 常用参数

# FFmpeg 输入输出

FFmepeg 不用指定输出:

代码语言:javascript
复制
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 的命令行参数分布:

代码语言:javascript
复制
ffmpeg [第一个输入文件对应解析参数] -i [第一个输入文件] [第二个输入文件对应解析参数] -i [第二个输入文件] ... [输出文件对应解析参数] [输出文件]

# 模块参数帮助

  • ffmpeg --help:查看所有模块的帮助信息
    • 常用参数
      • -h:查看模块的简单帮助信息
      • -long:查看模块的更多高级操作
      • -full:查看模块的所有帮助信息
      • [type]=[name] 查看指定模块的帮助信息
        • ffmpeg -h muxer=mp4 查看 mp4 封装的帮助信息
        • ffmpeg -h encoder=libx264 查看 libx264 编码器的帮助信息

# FFmpeg 公共基础参数

  • 公共操作部分
    • -report:输出日志
    • -v:设置日志级别
      • quiet:不输出任何日志
      • panic:输出错误日志
      • fatal:输出错误日志
      • error:输出错误日志
      • warning:输出警告日志
      • info:输出信息日志
      • verbose:输出详细日志
      • debug:输出调试日志
      • trace:输出跟踪日志
  • 每个文件主要操作部分
    • -i:输入文件
    • -f:输出文件格式
    • -y:覆盖输出文件
    • -ss:指定开始时间
      • 注意 -ss 指定的位置最好是关键帧位置
      • -ss 参数放在 -i 参数左侧来定位开始的位置会比放在右侧快很多,但是需要注意使用关键帧位置,否则会不准确
    • -t:指定持续时间
    • -codec:指定编码器
      • -codec:v copy -an:去掉音频流(-anaudio none
    • -metadata:指定元数据,如标题、作者等
  • 视频操作部分
    • -r 指定帧率
    • -vb 指定视频码率
    • -vframes 指定帧数
    • -s 指定分辨率
    • -aspect 指定宽高比
    • -vn 去掉视频流
    • -vf 给视频做简单滤镜处理
  • 音频操作部分
    • -ar 指定采样率
    • -ab 指定音频码率
    • -aframes 指定帧数
    • -ac 指定声道数
    • -an 去掉音频流
    • -af 给音频做简单滤镜处理
    • -vol 指定音量

# FFmpeg 公共高级参数

  • -filter_complex:可以将音视频混合在一条参数字符串里进行操作,可以输入、输出多个视频流和音频流
    • -filter_script:当命令行参数过长的时候,可以使用外挂脚本来进行操作
  • -copytb:设定 timebase 与输入的相同,确保时间戳不会跳变,有一定风险
  • -force_key_frames:强制关键帧设定,支持表达式

# FFmepeg 处理 MP4

MP4 标准非常灵活,可扩展性比较好,有很多常见的格式是基于 MP4 做了一些扩展,然后被应用到比较广的范围,比如 CMAF、DASH、HLS。而且 MP4 的参考标准是一个开放的标准,通常以编号为 ISO-14496-12 来查找标准文档。

# FFmepeg 生成 MP4 文件

查看 MP4 的 muxer 对应的参数:

代码语言:javascript
复制
ffmpeg -h muxer=mp4

常见参数:

faststart:将 moov box 放在文件头部,方便播放器快速开始播放

代码语言:javascript
复制
ffmpeg -i input.flv -c copy -f mp4 -movflags faststart output.mp4

DASH 参数:生成 DASH 格式时,里面有特殊 MP4 格式,可以理解为 MP4 切片

代码语言:javascript
复制
ffmpeg -i input.flv -c copy -f mp4 -movflags dash output.mp4
  • 应用场景
    • HLS/DASH 直播
    • 生成点播内容
    • MP4 上传云端实时转码

# FFmepeg 解析 MP4 文件

FFmpeg 在解析 MP4 文件格式的时候,可能会因为 MP4 的内容生成得不标准产生一些奇奇怪怪的问题,如音视频不同步或者视频抖动等问题。FFmpeg 针对出现的这类问题也做了格式上的兼容,但用户可能需要自己手动设置一些参数,定制一下,才可以解决这些问题。

查看 MP4 的 demuxer 对应的参数:

代码语言:javascript
复制
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 文件可能不统一,存在一定的差异,这个差异就可能引起兼容性问题。

# GPAC

Modular Multimedia framework for packaging, streaming and playing your favorite content, see http://netflix.gpac.io (opens new window).

# Shaka-Packager

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).

# FFmepeg 转码

# CPU 转码

使用 CPU 转码,通常是用 CPU 解码,然后用 libx264、libx265、librav1e 之类的编码器编码,也叫软编码。

转码的基本操作流程:解封装 -> 解码 -> 原始数据 -> 编码 -> 封装

libx264 在 FFmepeg 中支持的参数:

代码语言:javascript
复制
# 查看 libx264 支持的参数
ffmpeg -h encoder=libx264

通常统一编码成 yuv420p ,如果确定播放器可以支持 HDR 的话,也可以考虑用 yuv420p10le。但是如果想要在 Web 浏览器上正常播放出来的话,yuv420p 是最稳定的格式。

为了解决设置编码参数时参数太多、太琐碎的问题,libx264 提供了预置模板 preset,在 FFmpeg 里默认用的是 medium 模板,也就是平衡画质与编码速度的最优选择。

除了 preset 模板,还有调优类型的模板 tune,包括 filmanimationgrainstillimagepsnrssimfastdecodezerolatency 等不同的模版。

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

宏块树是一种视频编码结构,在编码时它可以增加 slice 处理的层数,降低视频编码的码率,但是复杂度会略有提升,所以耗时也会增加一些。

slice 的的意思是将一帧图像切成多个切片,然后将多个片放到多个线程里处理,从而达到并发处理的的目的。因为 lookahead 是 0,不需要提前预存多个帧做缓存,也没有双向参考帧 B 帧,不需要预读多个帧做缓存,所以最大限度地降低了帧缓存引起的画面延迟。

在给视频转码做转码的时候,有时也会被要求转成恒定码率的视频流,即 CBR ,它可以通过参数 nal-hrd cbr 来设置,但是实际的码率不一定能够控制得很好,所以通常会搭配 FFmpeg 的 maxrateminratebufsize 来精确地控制码率,一般 bufsize 控制比 maxrate 小大概 1/3 ~ 1/2 即可。

如果使用当前 FFmpeg 里面的 libx264 参数无法达到要求,但用 x264 没问题的话,可以通过 FFmpeg 预留的 x264opts 来设置更多 x264 的参数。

# GPU 转码

用 CPU 转码的话,对 CPU 的消耗会比较高,用 GPU 转码可以节省一些 CPU 计算资源。

FFmpeg 支持的硬件加速方案:

  • 操作系统:包括 Windows、Linux、macOS /iOS、Android 等
  • 芯片厂商的特定方案:包括 Intel、AMD、Nvidia 等
  • 行业标准或事实标准:包括 OpenMAX 和 OpenCL、Vulkan、OpenGL 还有 cuda 等

# HandBrake 转码

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.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022/8/28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • # 直播推流
    • # FFmepeg 推流
    • # OBS 推流
  • # ffprobe 分析音视频
    • # 音视频容器格式分析
    • # 音视频流分析
    • # 音视频包分析
    • # 音视频帧分析
  • # FFmpeg 常用参数
    • # FFmpeg 输入输出
    • # 模块参数帮助
    • # FFmpeg 公共基础参数
    • # FFmpeg 公共高级参数
  • # FFmepeg 处理 MP4
    • # FFmepeg 生成 MP4 文件
    • # FFmepeg 解析 MP4 文件
  • # GPAC
  • # Shaka-Packager
  • # FFmepeg 转码
    • # CPU 转码
    • # GPU 转码
    • # HandBrake 转码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档