Yet another otaku

某ロリコン的自白


  • 首頁
  • 歸檔
  • 分類
  • 標籤
  • 連結
  • 關於
  •    

© 2023 SgDylan

Theme Typography by Makito

Proudly published with Hexo

自建直播平台

發佈於 2022-12-14 評論 笔记  DIY Live OBS ffmpeg zlmediakit 

由于政策及版权的限制,很多内容是无法在串流平台上直播分享。
为了与朋友分享内容,自建直播平台被提上了日程。

需求

搭建自己的平台自然是能有的尽量都上,简单列举一下大概有这些:

  1. 可以通过 OBS/ffmpeg 推流(必须);
  2. 支持跨平台,包括 iOS;
  3. 支持对直播进行自动录像;
  4. 可以对观众鉴权;
  5. 可以对推流进行鉴权;
  6. 支持 SRT 推流;
  7. 支持 HEVC 推流/分发;
  8. 支持 CDN 分发;
  9. 支持推流协议分发;
  10. 延迟尽可能低。

选型

大概试用一圈开源的解决方案之后,得到了以下结论:

  1. 支持 rtmp -> HLS 转换即可支持 iOS 观看,由于基于 HTTP 因此同时支持 CDN 分发;
  2. 支持 rtmp 即可支持 OBS/ffmpeg 等直播软件的推流;
  3. OBS 推流 HEVC 目前不支持 SRT/rtmp,ffmpeg 推流可以用 SRT 或修改后使用 rtmp;
  4. HEVC 分发需要使用 DASH/HLS 等可承载 MPEG-TS 流的协议;
  5. 自动录像、鉴权需二次开发。

总结下来,比较常见的 nginx-rtmp 及已经被咱用了很久的 node-media-server 虽然用法已经很熟悉了,但由于对 SRT 的支持缺失以及二次开发较为吃力只能放弃了。

在很长的时间里,咱实际使的是 SRS (可能有数月之久),最初目的是实现 SRT->RTMP/HLS 的转换分发。
在此期间,发现存在两个无法绕过的 BUG:

  • 启动超过一定时间(一天左右)无法接收 SRT 推流
  • 主线版本不支持 HEVC 分发

于是放弃了 SRS,选择了起初看起来很乱但实际功能完善的 zlmediakit,并经过简单的二次开发最终实现全部需求。

使用

编译

zlmediakit 没有提供二进制程序,因此需要自行从源码编译。
好在编译的过程非常简单,您仅需要有 build-essential 以及 libssl-dev 即可直接编译:

mkdir build
cd build
cmake ..
make

安装

编译结束后,可以在某个路径下看到一个名为 MediaServer 的可执行文件。
同一文件夹下还可以找到 config.ini、default.pem 以及 www 文件夹,将这三样连同可执行文件拷贝到安装目录下即可结束安装。
安装结束后的目录应有这些文件/文件夹:

www/
config.ini
default.pem
MediaServer

如有需要可以再创建一个 log 目录用于存放日志文件,具体路径在 config.ini 中配置。以及如需要使用 zlmediakit 拉流实时转码,需要在当前路径下放置一个 ffmpeg(硬链接也行)。

配置

zlmediakit 的配置在其 GitHub 的 wiki 上有较多介绍,此处仅对没有提到的部分记录:

  1. 如有不需要启用的直播协议,将其监听端口号设置为 0 即可;
  2. 启用 Cluster 模式后,推流的视频也将应用全局的无人观看等待时间,进行常规直播推流需修改 streamNoneReaderDelayMS 避免推流被关闭,此时需手动关闭转发拉流;
  3. 对 RTMP 转发可以使用 addStreamProxy 接口,对 RTSP 流转发无法观看时需使用 addFFmpegSource 接口。

其余的配置选项可以依据需要进行配置,此时除鉴权外均已经实现。
按需录像需要继续二次开发,对所有直播流进行录像已经包含在配置选项中。

二次开发

zlmediakit 的二次开发非常轻松,在配置文件中设置好 secret 以及 admin_params 后,配置对应的 hook 接口即可将对应事件托管。

例如启用推流鉴权,仅需自建一个 API Server,在配置文件中修改:

# 推流鉴权事件,置空则关闭鉴权
on_publish=http://127.0.0.1:9999/on_publish

当用户发起推流时,zlmediakit 会向上述接口发起一个 POST 请求,推流地址中的参数会包含在请求 JSON 的 params 值中。

可以借助这一值传递鉴权信息,例如推流地址为:
rtmp://127.0.0.1:1935/live/test?token=114514&user=yjsnpi

params 值为 token=114514&user=yjsnpi

这一接口需要返回如下 JSON:

{
    "code" : 0,            # 0 表示允许推流
    "msg" : "success",     # 返回的消息
    "enable_mp4" : False,  # 是否进行录像
    "enable_hls" : True,   # 是否转换 HLS
    "enable_rtsp": False,  # 是否转换 RTSP
    "enable_ts": True,     # 是否转换 TS
    "enable_fmp4": True,   # 是否转换 HLS-LL
    "enable_audio": False, # 是否转换纯音频
    "add_mute_audio": True # 添加静音音频
}

咱使用的是 CherryPy 搭建 API Server,这里也可以使用您顺手的任意方式实现:

zlm_dvr_api = "http://127.0.0.1:12345/index/api/"
zlm_secret = "secret=1145141919810"

@cherrypy.expose
@cherrypy.tools.json_in()
@cherrypy.tools.json_out()
def on_publish(self):
    sip = cherrypy.request.remote.ip
    if sip != "127.0.0.1":
        return {}
    # return json
    req = cherrypy.request.json
    ret = {
        "code" : 0,
        "msg" : "success",
        "enable_hls" : True,
        "enable_mp4" : False,
        "enable_rtsp": False,
        "enable_ts": True,
        "enable_fmp4": True,
        "enable_audio": False,
        "add_mute_audio": True
    }
    # split params
    params = {}
    for i in req.get("params", "").split("&"):
        [k, v] = i.split("=", 2)
        params[k] = v
    # check token vaild
    token = params.get("token", "")
    raw = self.sess.get(f"http://token.valid.site?token={token}")
    if raw.status_code != 200 and req.get("ip", "") != "127.0.0.1":
        ret["code"] = -1
        return ret
    # check record flag
    if params.get("dvr", "no") == "yes":
        params["enable_mp4"] = True
    api = f"{zlm_dvr_api}startRecord?type=1&vhost=__dvr__&{zlm_secret}"
    api += f'&app={req.get("app", "")}&stream={req.get("stream", "")}'
    sess.get(api)
    return ret

如此一来即可实现推流鉴权以及设置自动录像。
观看鉴权以及观众控制均可使用类似方法进行二次开发实现。

后记

zlmediakit 依然在快速迭代中,每周都有新的提交。遇到 BUG 时不妨翻翻看 issue,说不定已经排上日程了。

zlmediakit 目前支持绝大多数的公开推流/分发协议,但并不能用于广播级的直播,对于 MPEG-TS 流的特性支持是相当缺乏的。例如 TS 中的数据流和字幕目前是完全不支持的。

对于延迟的控制,前文中一直没有提及。这是因为延迟控制是一个系统工程,需要推流端、分发端、观众端三者的共同配合。
目前基于 zlmediakit 可支持的最低延迟在 100ms 以内,需要使用 WebRTC 协议。
其他直播协议最低延迟在 3s 左右,需要使用 CBR 硬件编码 + RTMP 推流 + RTMP 低延迟参数 + 低延迟大带宽 + mpv 播放器。

以上。

分享到 

 上一篇: 二〇二二 𝄇 下一篇: 四疊半后日谈 

© 2023 SgDylan

Theme Typography by Makito

Proudly published with Hexo