音视频转码功能 - xia-chu/zlmediakit-pro GitHub Wiki

一、概述

zlmediakit pro版本支持基于ffmpeg的转码能力,在开源版本强大功能的基础上,新增支持如下能力:

  • 1、音视频间任意转码(包括h265/h264/opus/g711/aac/g722/g722.1/mp3/svac。
  • 2、基于配置文件的转码,支持设置比特率,codec类型等参数。
  • 3、基于http api的动态增减转码,支持设置比特率,分辨率倍数,codec类型、滤镜等参数。
  • 4、支持硬件、软件自适应转码。
  • 5、支持按需转码,有人观看才转码。
  • 6、支持负载过高时,转码主动降低帧率且不花屏。
  • 7、支持滤镜,支持添加osd文本以及logo角标等能力。
  • 8、支持全GPU硬件编解码与滤镜,防止显存与内存频繁拷贝。

二、转码实现原理

  • 视频转码原理
  • 音频转码原理

三、使用方法

目前zlmediakit pro转码能力支持两种使用方式,第一种是基于配置文件方式,在设置好配置文件后,所有流都支持转码为目标编码格式直播流,第二种模式基于http api方式,此方式更灵活,功能强大,可以指定更多转码相关参数。

3.1 基于配置文件的转码

[transcode]
#是否开启ffmpeg日志
enable_ffmpeg_log=0

#转码stream_id后缀,为空时关闭转码,为null时为透明/替换转码模式,转码流id与原始流一致
suffix=null
#是否强制转码,开启后就算目标编码格式一样也会解码再编码,开启滤镜或插件功能时,相当于强制开启转码
force=0
#开启转码的流的百分比,默认全部流开启转码,50时一半流转码,一半不转码
percent=100

#视频转码目标codec,支持H264/H265/JPEG/copy
video_codec=H264
#视频转码后的目标比特率,默认为0(如果是h265转码h264,bitrate默认翻倍否则相等)
video_bitrate=4000000
#视频编码器设置选项
video_encoder_opt=zerolatency=1,preset=ultrafast,profile=main,tune=zerolatency,nal-hrd=vbr
#视频解码器设置选项,用法与video_encoder_opt类似
video_decoder_opt=

#音频转码目标codec,支持mpeg4-generic/PCMA/PCMU/opus/copy
audio_codec=mpeg4-generic
#转码后音频比特率
audio_bitrate=32000
#转码后音频采样率率
audio_samplerate=8000
#转码后音频通道数
audio_channel=1

#avfilter滤镜参数,用法与ffmpeg -vf 参数一致
filter=
#视频滤镜线程数
filter_threads=4

#是否启用硬件解码器
hw_encoder=1
#是否启用硬件编码器
hw_decoder=1

#解码线程数,最大32个,音频强制为1个,视频默认2个
decoder_threads=4
#编码线程数,最大32个,音频强制为1个,视频默认4个
encoder_threads=4

# h264解码器白名单,前面的优先级更高
decoder_h264=h264_cuvid,h264_qsv,h264_videotoolbox,h264_nvmpi,h264_bm,libopenh264
# h265解码器白名单,前面的优先级更高
decoder_h265=hevc_cuvid,hevc_qsv,hevc_videotoolbox,hevc_nvmpi,hevc_bm
# h264编码器白名单,前面的优先级更高
encoder_h264=h264_nvenc,h264_qsv,h264_videotoolbox,h264_nvmpi,h264_bm,libx264,libopenh264
# h265编码器白名单,前面的优先级更高
encoder_h265=hevc_nvenc,hevc_qsv,hevc_videotoolbox,hevc_nvmpi,hevc_bm,libx265

#全硬件转码开关,开启后,解码->编码之间传递显存类AVFrame,不经过内存中转,大幅提高性能
#支持cuda/qsv/videotoolbox/ascend等
hwaccel=

#是否按需转码,开启后,如果无人观看,会暂停转码
demand=1
#如果音频转码生效了,是否根据pcm数据量重新计算音频时间戳
modify_audio_stamp=1
#每张编解码器最大通道数,限制每张显卡最多编解码实例数,只对ascend显卡生效
max_channel=256
#视频处理插件文件夹路径,里面存放so/dll 插件文件,不可存放非插件文件(插件依赖的so/dll应当存放其他路径)!
pluginDir=
#转码时,是否经过插件处理AVFrame视频帧,处理顺序为解码->滤镜->插件->编码,在pluginDir设置并加载插件后,此参数可以选择特定的插件
plugin=
#插件并发线程数,建议设置为0(同步输入插件),特定插件加大此参数能提高性能
plugin_threads=0
#插件处理后,视频帧数据是否重绘,开启后会重新编码视频
#否则只解码并输入插件,不重新编码(适用于纯视频分析类插件)
#此参数设置为0时,可以节省视频编码开销
paint=1

在上述配置文件中,如果用户配置好suffix,那么zlmediakit将统一把所有直播流转码为目标编码格式,用户通过访问新的流地址即可确保为预期编码格式视频。

例如源视频地址为:rtmp://127.0.0.1/live/test, 那么转码后地址即为:rtmp://127.0.0.1/live/test_H264。

当配置文件修改为suffix=null时,转码后流会直接替换原始流(不会有_suffix后缀),如果需要播放原始流,可以在url上加上?origin_stream=1后缀 ;替换模式下,建议rtsp.directProxy/rtmp.directProxy都设置为0。

如果源视频编码格式与目标编码格式一致,那么zlmediakit为了确保性能最优,将直接拷贝流数据(不会编码)。

基于配置文件方式的转码使用最简单,可以使用于安防行业H265视频无法webrtc/mse播放的场景。

3.2 多转码配置方案

基于配置文件的转码方案,同时支持多种转码预设方案,用户可以通过播放不同的url后缀来实现选择播放不同转码流,例如原始流、1080P、720P:

[transcode]
#默认转码切记务必关闭
suffix=

[transcode_1080p]
filter=scale=1920:1080
# 4Mb/s
video_bitrate=4000000
#其他转码参数如果未指定,则使用[transcode]域下的,请参考3.1

[transcode_720p]
filter=scale=1280:720
# 1Mb/s
video_bitrate=1000000
#其他转码参数如果未指定,则使用[transcode]域下的,请参考3.1

如果原始流id为test, 那么播放test_1080p时,zlm会自动采用[transcode_1080p]下的转码参数转码并生成test_1080p转码流, [transcode_720p]以此类推,当该转码流无人观看时,则会自动关闭转码,如果需要无人观看时保持一直转码,可以在[transcode]下新增配置项const_transcode=1080p,720p

3.3 基于http api的转码

zlmediakit同时还提供基于http api的转码方式,这种方式支持的功能更强大,使用更灵活,同时支持一个流转码成多个目标流( 比如说不同分辨率的场景)。

  • 请求地址:/index/api/setupTranscode

  • 说明:该接口支持所有protocol转协议相关参数,转协议参数如果不指定则采用配置文件protocol域下同名配置参数;转码相关参数支持所有transcode相关参数,如果不指定则采用配置文件transcode域下同名配置参数。

  • 请求参数:

参数 参数类型 释意 是否必选
secret string api操作密钥(配置文件配置) Y
vhost string 流的虚拟主机,例如__defaultVhost__ Y
app string 流的应用名,例如live Y
stream string 流的id名,例如test Y
name string 转码名(后缀),功能类似配置文件transcode.suffix Y
add int 1:添加转码; 0: 删除转码 Y
video_codec string 视频转码的codec,支持H264/H265/JPEG/copy Y
video_bitrate int 转码后视频的比特率 N
video_decoder_opt string 视频解码器配置参数 N
video_encoder_opt string 视频编码器配置参数,例如preset=ultrafast,profile=high,tune=zerolatency N
audio_codec string 音频转码codec,支持mpeg4-generic/PCMA/PCMU/opus/copy Y
audio_bitrate int 转码后音频比特率 N
audio_samplerate int 转码后音频采样率率 N
audio_channel int 转码后音频通道数 N
filter string avfilter滤镜参数,用法与ffmpeg -vf 参数一致 N
filter_threads int 视频滤镜线程数
force bool 是否强制转码,强制转码时不管目标编码是否一致,默认否 N
decoder_threads int 解码线程数,默认2个,最大32个,音频强制为1个 N
encoder_threads int 编码线程数,默认4个,最大32个,音频强制为1个 N
hw_decoder bool 是否启用硬件解码器,默认启用 N
hw_encoder bool 是否启用硬件编码器,默认启用 N
decoder_list string 视频ffmpeg解码器列表,例如: h264_cuvid,h264_qsv N
encoder_list string 视频ffmpeg编码器列表,例如: hevc_nvenc,hevc_qsv N
enable_hls bool 转码后是否转换成hls-mpegts协议 N
enable_hls_fmp4 bool 转码后是否转换成hls-fmp4协议 N
enable_mp4 bool 转码后是否允许mp4录制 N
enable_rtsp bool 转码后是否转rtsp协议 N
enable_rtmp bool 转码后是否转rtmp/flv协议 N
enable_ts bool 转码后是否转http-ts/ws-ts协议 N
enable_fmp4 bool 转码后是否转http-fmp4/ws-fmp4协议 N
hls_demand bool 转码后该协议是否有人观看才生成 N
rtsp_demand bool 转码后该协议是否有人观看才生成 N
rtmp_demand bool 转码后该协议是否有人观看才生成 N
ts_demand bool 转码后该协议是否有人观看才生成 N
fmp4_demand bool 转码后该协议是否有人观看才生成 N
enable_audio bool 转码后转协议时是否开启音频 N
add_mute_audio bool 转码后无音频是否添加静音aac音频 N
mp4_save_path string 转码后mp4录制文件保存根目录,置空使用默认 N
mp4_max_second int 转码后mp4录制切片大小,单位秒 N
mp4_as_player bool 转码后MP4录制是否当作观看者参与播放人数计数 N
hls_save_path string 转码后hls文件保存保存根目录,置空使用默认 N
modify_stamp int 转码后该流是否开启时间戳覆盖(0:绝对时间戳/1:系统时间戳/2:相对时间戳) N
auto_close bool 转码后无人观看是否自动关闭流(不触发无人观看hook) N
  • 响应:

    {
       "code" : 0,
       "msg" : "success"
    }
    

3.4 使用http api获取转码信息

  • 请求接口:/index/api/getMediaInfo
  • 请求回复:请查看transcode字段
{
  "aliveSecond": 88,
  "app": "live",
  "bytesSpeed": 330246,
  "code": 0,
  "createStamp": 1691902256,
  "isRecordingHLS": true,
  "isRecordingMP4": false,
  "originSock": {
    "identifier": "2-51",
    "local_ip": "192.168.31.101",
    "local_port": 8000,
    "peer_ip": "192.168.31.101",
    "peer_port": 61801
  },
  "originType": 8,
  "originTypeStr": "rtc_push",
  "originUrl": "rtc://127.0.0.1/live/test?app=live&stream=test&type=push&session=1-50",
  "readerCount": 0,
  "schema": "rtsp",
  "stream": "test",
  "totalReaderCount": 0,
  "tracks": [
    {
      "codec_id": 0,
      "codec_id_name": "H264",
      "codec_type": 0,
      "fps": 30.0,
      "frames": 2648,
      "gop_interval_ms": 2012,
      "gop_size": 60,
      "height": 556,
      "key_frames": 51,
      "loss": 0.0,
      "ready": true,
      "width": 990
    },
    {
      "channels": 1,
      "codec_id": 4,
      "codec_id_name": "PCMU",
      "codec_type": 1,
      "frames": 4434,
      "loss": 0.0,
      "ready": true,
      "sample_bit": 16,
      "sample_rate": 8000
    }
  ],
  "transcode": [
    {
      "name": "codec",
      // 转码名称
      "setting": {
        // 转码配置信息
        "adecoder_threads": 1,
        // 音频解码器线程数
        "aencoder_threads": 1,
        // 音频编码器线程数
        "hw_decoder": true,
        // 启动硬件解码器
        "hw_encoder": true,
        // 启动硬件编码器
        "target_acodec": "mpeg4-generic",
        // 目标音频编码格式
        "target_vcodec": "H265",
        // 目标视频编码格式
        "vdecoder_threads": 4,
        // 视频解码器线程数
        "vencoder_threads": 8,
        // 视频编码器线程数
        "force": false,
        // 是否强制转码
        "filter": "",
        // 滤镜参数
        "decoder_list": [
          "h264_cuvid",
          "h264_qsv"
        ],
        // 解码器列表
        "encoder_list": [
          "hevc_nvenc",
          "hevc_qsv"
        ]
        // 编码器列表
      },
      "adec": "pcm_mulaw",
      // 音频解码器名称
      "aenc": "aac",
      // 音频编码器名称
      "aenc_ctx": {
        // 音频AVCodecContext信息
        "bit_rate": 32000,
        // 比特率
        "channels": 1,
        // 通道数
        "frame_number": 4055,
        // 已编码帧数
        "frame_size": 1024,
        // 每帧采样数
        "sample_fmt": "fltp",
        // 音频编码输入格式
        "sample_rate": 48000
        // 编码器采样率
      },
      "vdec": "h264",
      // 视频解码器名称
      "venc": "hevc_videotoolbox",
      // 视频编码器名称
      "venc_ctx": {
        // 视频AVCodecContext信息
        "bit_rate": 1000000,
        // 比特率
        "fps": 20,
        // 帧率
        "frame_number": 2595,
        // 已编码帧数
        "gop": 60,
        // gop大小
        "has_b_frames": 0,
        // 是否编码b帧
        "height": 556,
        // 视频高度
        "pix_fmt": "nv12",
        // 编码器输入图片格式
        "width": 990
        // 视频宽度
      }
    }
  ],
  "vhost": "__defaultVhost__"
}