在 Ideal World TV 播出的最后几个月里,我们开展了一个项目,用现代化的解决方案取代老旧的视频编码和流媒体基础设施。我们的目标很简单:提高直播流媒体的质量,使我们能够向社交媒体网络提供纵向流媒体(9:16),并增加可同时运行的流媒体数量。
我喜欢挑战,因此很早就决定不购买新的硬件或商业软件解决方案,而是使用在现有基础设施上运行的开源软件来构建我们的新解决方案。
设置
我们决定为播放设备的每路输出创建低延迟、高比特率的 “夹层 “编码。这些是 50 Mbps 的 H.264 数据流,以我们本地的 1080i50 制作和播放格式编码,作为 UDP 组播 MPEG 传输流在内部分发。
对于公共直播流,我们使用 Restreamer 对夹层流(The mezzanine streams)进行转码,并将其发送到各个直播平台。
所有这些都在我们现有的编码器硬件上运行,这是两台标准的 Supermicro 40 核 Xeon 服务器。这两台服务器最初运行的是一个不支持的商业 “设备 “软件解决方案,使用 Blackmagic Decklink SDI 卡作为视频输入。
这些服务器被擦除并重新安装了 Ubuntu 22.04,同时安装了 Docker,并设置为相互复制以实现冗余。最初,我们保留了 Decklink SDI 卡。但是,由于我们的播出设备本机使用的是 SMPTE ST 2110 IP 流而不是 SDI,因此在新的 Decklink IP 卡上市后,我们将其替换成了新的 Decklink IP 卡,从而腾出了一些 IP/SDI 转换网关。
夹层流(The mezzanine streams)
夹层流选择 Gstreamer 作为编码软件。通常情况下,FFmpeg 会是我的首选工具,但由于夹层编码和 Restreamer 将在同一台服务器上运行,我需要将数据流同时作为单播 TCP 数据流(供 Restreamer 本地使用)和多播 UDP 数据流(供我们的视频点播工作流程使用)。我发现 Gstreamer 的流水线工作流程及其 tcpserversink 输出非常适合这种情况。
每个编码都在自己的 Gstreamer 实例中运行,该实例在一个带有主机网络的 Docker 容器中运行。我们使用 restream.io 构建的 GStreamer 映像,但这些映像没有 Blackmagic 驱动程序所需的 C++ 标准库。因此,要使用 Decklink 输入,我们必须以 restream.io 的镜像为基础,在其上安装 libc++1,并使用以下 Dockerfile 构建我们自己的镜像:
FROM restreamio/gstreamer:x86_64-latest-prod
RUN export DEBIAN_FRONTEND="noninteractive" && \
apt-get update && apt-get -y --no-install-recommends install libc++1 && \
rm -rf /var/lib/apt/lists/*
有了这些,我们就可以用以下命令启动 Gstreamer,将 Decklink 输入编码为 H.264 流,并将输出分割为 UDP 流和 TCP 服务器:
gst-launch-1.0 decklinkvideosrc device-number=0 mode=1080i50 video-format=8bit-yuv drop-no-signal-frames=true output-afd-bar=true ! videoconvert ! "video/x-raw, width=1920, height=1080, format=I420, colorimetry=bt709, framerate=25/1, interlace-mode=interleaved" ! x264enc bitrate=30000 interlaced=true tune=zerolatency speed-preset=superfast key-int-max=25 ! queue max-size-time=3000000000 ! mpegtsmux alignment=7 name=mux decklinkaudiosrc device-number=0 ! fdkaacenc bitrate=256000 ! queue max-size-time=3000000000 ! mux. mux. ! tee name=split ! queue ! udpsink port=5000 host=<put ip here> bind-address=<put ip here> split. ! queue ! tcpserversink host=<put ip here> port=6001
要自行使用该命令,您需要用要使用的多播组 IP 地址和要绑定的主机网络适配器 IP 地址替换 “put ip here”。您还需要设置 Decklink 设备编号。我们使用 239.10.x.x 来设置多播组,第一个 “x “表示服务器,第二个 “x “表示数据流编号(例如,239.10.1.1 表示来自服务器 1 的数据流 1)。对于 TCP 服务器,我们会递增每个流的端口号。
我们使用 Docker Compose 将所有 GStreamer 容器连同它们所需的命令和设置一起启动。夹层编码器的最终 Compose 文件与此非常相似:
services:
encoder1:
image: my-org/gstreamer:latest
restart: unless-stopped
network_mode: host
environment:
TZ: Europe/London
volumes:
- /usr/lib/libDeckLinkAPI.so:/usr/lib/libDeckLinkAPI.so:ro
- /usr/lib/libDeckLinkPreviewAPI.so:/usr/lib/libDeckLinkPreviewAPI.so:ro
devices:
- /dev/blackmagic:/dev/blackmagic
command: gst-launch-1.0 decklinkvideosrc device-number=0 mode=1080i50 video-format=8bit-yuv drop-no-signal-frames=true output-afd-bar=true ! videoconvert ! "video/x-raw, width=1920, height=1080, format=I420, colorimetry=bt709, framerate=25/1, interlace-mode=interleaved" ! x264enc bitrate=30000 interlaced=true tune=zerolatency speed-preset=superfast key-int-max=25 ! queue max-size-time=3000000000 ! mpegtsmux alignment=7 name=mux decklinkaudiosrc device-number=0 ! fdkaacenc bitrate=256000 ! queue max-size-time=3000000000 ! mux. mux. ! tee name=split ! queue ! udpsink port=5000 host=239.10.1.1 bind-address=192.168.1.2 split. ! queue ! tcpserversink host=192.168.1.2 port=6001
encoder2:
image: my-org/gstreamer:latest
restart: unless-stopped
network_mode: host
environment:
TZ: Europe/London
volumes:
- /usr/lib/libDeckLinkAPI.so:/usr/lib/libDeckLinkAPI.so:ro
- /usr/lib/libDeckLinkPreviewAPI.so:/usr/lib/libDeckLinkPreviewAPI.so:ro
devices:
- /dev/blackmagic:/dev/blackmagic
command: gst-launch-1.0 decklinkvideosrc device-number=1 mode=1080i50 video-format=8bit-yuv drop-no-signal-frames=true output-afd-bar=true ! videoconvert ! "video/x-raw, width=1920, height=1080, format=I420, colorimetry=bt709, framerate=25/1, interlace-mode=interleaved" ! x264enc bitrate=30000 interlaced=true tune=zerolatency speed-preset=superfast key-int-max=25 ! queue max-size-time=3000000000 ! mpegtsmux alignment=7 name=mux decklinkaudiosrc device-number=1 ! fdkaacenc bitrate=256000 ! queue max-size-time=3000000000 ! mux. mux. ! tee name=split ! queue ! udpsink port=5000 host=239.10.1.2 bind-address=192.168.1.2 split. ! queue ! tcpserversink host=192.168.1.2 port=6002
流媒体到平台
我们选择 Restreamer 作为接收夹层流、对其进行格式化和转码并将其输出到各种平台的工具。Restreamer 建立在 FFmpeg 的基础上,拥有直观的网络界面,操作员可以设置流媒体,并单独添加和删除输出到不同平台的内容,因此非常适合这项工作。
与 Gstreamer 一样,Restreamer 也是在 Docker 容器中与夹层编码实例一起使用官方镜像运行的。我们再次使用 Docker Compose,利用这个 Compose 文件将 Restreamer 与 Gstreamer 实例一起启动:
services:
server:
image: "datarhei/restreamer:latest"
restart: unless-stopped
environment:
TZ: Europe/London
ports:
- "80:8080"
- "1935:1935"
- "1936:1936"
- "6000:6000/udp"
volumes:
- config:/core/config
- data:/core/data
volumes:
config:
data:
Restreamer 在两台服务器上运行,配置几乎相同,唯一的区别是第一台服务器设置为流式传输到主流 URL,第二台服务器设置为流式传输到备份(平台支持)。
24/7 频道流
对于我们的两个频道,即《Ideal World》和《Ideal Extra》,我们在 Restreamer 中分别设置了两个流媒体。
第一个流被设置为 1080p50 8 Mbps H.264 流,用于传输到我们网站和智能电视应用程序使用的流媒体平台。对于该数据流,Restreamer 被配置为将输入的全动态画面去交错为每秒 50 帧,然后重新编码。
第二个流被设置为 1440p60 16 Mbps H.264 流,以便传输到 YouTube。与第一种情况类似,Restreamer 被配置为对流进行去交错和重新编码,但除此之外,它还被设置为将其缩放为 2560×1440,并将其从 50 帧/秒转换为 60 帧/秒。
我选择这样做是为了绕过并利用 YouTube Live 平台的一些特性。目前,YouTube 只支持两种帧频的直播流,即 30 fps 和 60 fps。50 fps 的流媒体会被 YouTube 转换为 30 fps,因此有必要将标准转换为 60 fps,以便让 YouTube 使用更高的帧频并保持完整的动作。在撰写本文时,许多非美国广播公司以 25 帧/秒(由平台转换为 30 帧/秒)向 YouTube 传输流媒体,结果导致流媒体明显生涩,因此与其他公司相比,选择以 60 帧/秒传输流媒体大大提高了我们的流媒体质量。YouTube Live 目前还为分辨率大于 1920×1080 的流选择了更高质量的编码工作流程,因此我也选择将分辨率提升到 1440p,以利用这一优势。
社交媒体流
除了我们频道的连续串流外,Restreamer 还用于向 Facebook、Instagram 和 TikTok 提供 “弹出式 “串流。通过 Restreamer 的网络用户界面,我们的操作员可以轻松输入每个流媒体事件的流媒体键,并在事件发生前打开流媒体,在事件发生后关闭流媒体。
这些流的设置与我们频道的连续流非常相似,尽管只是单一的流。不过,它们还可以根据社交媒体平台的要求,将原生的 16:9(横向)制作格式旋转为 9:16(纵向)格式,Restreamer 再次让这一切变得非常简单。
最终结果
2023 年初,该系统投入使用,我们的所有数据流都切换到了该系统。事实证明,它非常可靠且用途广泛,直到 2023 年 7 月我们的服务关闭之前,它一直为我们提供着良好的服务。它本来可以运行更长的时间,事实上这也是最初的计划,但遗憾的是,其他因素阻碍了它的运行。
这个项目的一些要求也导致了 Restreamer 项目的上游改进。应 Restreamer 维护者的要求,我们添加了对 FFmpeg 的 bwdif 去隔行扫描过滤器的支持,为软件增加了高质量的去隔行扫描支持。我还修改了 FFmpeg 的帧速率过滤器,通过插值新帧而不是复制/删除帧来进行标准转换。这个改动还没有合并到项目中,所以还不能提供给所有人,但它可以作为一个拉取请求,我希望它能很快被合并。
作者:Orry Verducci
原文:https://medium.com/@orryv/broadcast-grade-live-streaming-with-gstreamer-and-restreamer-4b8cc8f05bdb
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。