当前位置:首页-未分类-正文

OBS多平台直播方法及原理

OBS 目前要推流到多个平台,大部分用的方法是这么几种:
1、使用OBS的录制功能,录制到“某个rtmp://的网址”上;
2、多开OBS,电脑可能会卡,而且一个游戏、一个摄像头只能被一个OBS抓到画面;
3、不用OBS而用XSplit,这软件想要推多个平台是要钱的;
4、用Restream.io提供的服务,要钱的;
5、本地架一个nginx-rtmp服务;
6、用rtmprelayer软件做转发;
这些方法都比较麻烦,有的门槛还有点高(比如钱的门槛啊自己架服务器的门槛啊高配电脑的门槛啊……)。
其实,免费开源的OBS,里面的模块设计是可以多开推流的。只是作者没有在界面上给你做这个功能。那么简单说就是只要做个界面,就能把OBS的这个多推流功能给开放出来。
因为做这个的一个目标就是要简单易用门槛低,希望界面是一眼看过去就知道是怎么用的:

多推流插件界面截图
安装方法也很简单,整个文件夹解压到OBS的安装目录下,然后再启动OBS,多路推流的界面就会显示出来了。
必须要 OBS 25.0 或者更高版本才能用,不然软件会出现无法运行的情况,原因后面会解释。
使用的时候还请多注意平台规范。

OBS多路推流原理

上面的方法2暂且跳过,确实没什么好解释的。关于只是用OBS本身不使用附加软件的方案,就只说方法1了。OBS软件里提供了两套能够用来“输出”的模块,一个在 obs-outputs.dll 里,包含 rtmp_stream 和 flv_output;一个在 obs-ffmpeg.dll 里,叫做 ffmpeg_output。这些DLL文件只要翻一翻 OBS 的安装目录,就可以看到。
根据OBS设置项的不同,画面和声音信号转成 H.264 和 AAC 数据包的流程也会不同。只开推流的时候,它是像下面这个样子的:

捕捉、合成等处理之后的音视频信号,从 libobs.dll 里出来,进入编码器(obs-x264.dll,obs-ffmpeg.dll 里的 ffmpeg_nvenc 英伟达硬编 ,enc-amf.dll 里的 AMD 硬编,obs-qsv.dll 里的核显硬编,win-mf.dll 里的Windows自带编码器),然后编码器输出的一个个数据包送到 obs-outputs.dll 里面去,封装成 FLV 格式通过 RTMP 推流到服务器。
但是如果用户开了录制,并且录像格式选择的是“标准”,编码器是“使用推流编码器”,那么OBS内部的数据流会变成这样:


此时还是只有一套编码器,保存录像和推流用的是一样的。好处是开录像或者不开录像,对电脑性能的消耗没有什么区别。因为这里面最耗资源的是中间那个编码器。
OBS在录像的时候是可以允许用户使用独立的编码器的

此时OBS会开两套编码器来应对推流和录像。这也就是说,这个时候用户可以调成录像和推流的画质是不一样的:网络比较烂的时候,推流用低码率,然后录像用高码率,这样直播完了之后想要剪辑,不会变成粪画质。
到这里为止,录像一直用的是“标准”模式,能给选保存位置的地方也就一个“录像路径”。目前还和多推流没有关系。接下来要说“自定义输出(ffmpeg)”。

FFMPEG是一套开源的多媒体处理软件,最基本的用法是通过输入命令的方式对视频文件进行处理和压制。里面的各种 DLL 也可以单独拿出来用。OBS这里就是DLL单独拿出来用的。前面图片里出现的 ffmpeg_muxer,就是把它里面的 avformat.dll 拿来用,使得一个个的 H.264 和 AAC 数据包可以存成 FLV、MP4 等文件。在OBS的自定义输出(ffmpeg)模式下,它不仅用了 avformat.dll,还用了 avcodec.dll。它的数据流会变成这样

和上面几张图最大的区别是,这里的 ffmpeg_output 再往后是没有流程的。因为从音视频信号往后,所有的操作都由 ffmpeg 完成;OBS不是把编码后的 H.264、AAC 数据包拿出来然后去推流或者去保存文件,而是ffmpeg自己爱存哪里存哪里的状态。这种模式下,用户可以把“ffmpeg输出类型”改为“输出到URL”。这里的URL理解为“网址”就好了,可以填一个RTMP的推流地址和推流码。此时录像就变成了第二个“推流”,也就实现了两路推流。
这里有一个要补充的是,因为 ffmpeg 的推流功能实际上用的是 avformat.dll ,也就是说上面那个 ffmpeg_muxer 我觉得也可以拿来推流。可能是 OBS 在界面上没做这样的功能或者 ffmpeg_muxer 里面没有做相关兼容。这个我没调查研究过,所以就不乱说了。
录制功能拿来推流也是有一些缺点,比如它没有OBS那样的丢包控制,比如看不到现在录制的那一路推流是不是流畅、帧率多少、网络阻塞不阻塞。
到这里为止,OBS的几种推流同时录像的模式已经解释完了。但是在这几种模式里,是没用共用编码器的同时开两路推流的。编码器可以说是直播过程中最最消耗系统资源的模块,这个如果能共用,那么能节省非常大量的系统资源。
实际上研究过OBS的代码,就会发现其实是可以组装出这样的数据流图的

不要什么 ffmpeg_muxer,反正接口一样,换成 rtmp_stream,每个都是推流,这样就是多推流。但是这里的 obs_encoder 是 OBS 主界面创建的。OBS在启动之后,并不会创建这个东西,只有在你第一次开始推流(或者“使用推流编码器”模式下的录像)的时候,把这些东西创建出来。不过创建出来以后你停止推流或者录像,它并不会删除这些编码器。修改了OBS的设置项的话,它会删除,然后下一次开始推流的时候又会创建。所以如果启动OBS以后没有开过直播或者录像,我的插件开始直播会提示要你开一下直播,否则我代码里获取不到这个它的编码器,也就没法和它共用、也就没法省资源。
如果想要设置不同的码率或者分辨率,那么也只要

就搞定了。和上面的“标准”模式的录像是一样一样一样的。OBS 在它的核心里面提供了这样的能力,但是在界面上没做这样的功能。我做的插件,就是给它加一个这样的界面、能用这样的功能。
到这里为止,插件里面是怎么做的、做了什么,就解释完了。其实本来也就代码都放上来了,看看代码就什么都知道了……里面并没有秘密。
顺便说一下,在OBS 25.0以前的版本里,它在 rtmp_stream 模块用了一些全局变量。这也就导致 rtmp_stream 的多开会产生一些问题,比如崩溃。但是这种全局变量和多线程问题,并不是100%出现的。
用 rtmprelayer 和 nginx-rtmp 按我理解是一样的,都是自己机器上开个 RTMP 服务器,让 OBS 把直播流推到这个 RTMP 服务器上,这个服务器软件收到数据以后,再转发给各个平台。然后 Restream.io 呢,就是把这个“开在自己机器上的RTMP服务器”开到了它的服务器上,由它来给你转发。这样呢好处就是自己网络状态并不是那么牛逼的情况下也可以同时推四五六七八个平台,反正 Restream.io 用服务器去给你转。不过看起来价格并不便宜。