whatshot玩转直播流:使用SRS搭建推流服务器;使用SRS+ffmpeg中转推流;OBS推流到自建服务器;使用ffmpeg把直播流复制到多个网站

@Ta 2021-12-30发布,02-22 22:50修改 4121点击

推荐使用Linux,Windows建议在WSL2中进行尝试。

使用SRS搭建推流服务器

1a. Ubuntu安装docker教程(Windows忽略)

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

1b. Windows安装WSL2+docker教程(Linux忽略)

https://post.smzdm.com/p/a259kqlp/

image.png

装好后请打开一个 WSL2 Ubuntu 命令行窗口,执行第2步。

2. 安装ffmpeg

sudo apt update
sudo apt install ffmpeg

3. 安装SRS推流服务器

任选一个版本:

3a. 使用SRS3(稳定版)

docker run --restart=always --name srs -d -it --network=host registry.cn-hangzhou.aliyuncs.com/ossrs/srs:3

3b. 使用SRS4(beta版)

docker run --restart=always --name srs -d -it --network=host registry.cn-hangzhou.aliyuncs.com/ossrs/srs:4 ./objs/srs -c conf/docker.conf

SRS控制面板:http://localhost:8080/
推流服务器:rtmp://localhost:1935(1935是RTMP的默认端口,所以可以省略)

4. 用ffmpeg中转推流

4a. 尝试用ffmpeg命令行中转推流

-i后面可以接各种资源,包括视频文件、m3u8地址、flv地址等。

如果音频编码不是aac,可以删掉-bsf:a aac_adtstoasc参数。

请给网址打引号,防止生出各种麻烦。

ffmpeg -re -i 'http://cctvalih5ca.v.myalicdn.com/live/cctv13_2/index.m3u8' -f flv -c copy -bsf:a aac_adtstoasc 'rtmp://localhost/live/livestream'

按ctrl+c关闭ffmpeg。

4b. 写一个循环,失败时自动重启ffmpeg

4a参数调好,确认没问题之后再进行。

请务必进行此步骤,否则任何风吹草动都可能会导致推流停止。

while true; do ffmpeg -re -i 'http://cctvalih5ca.v.myalicdn.com/live/cctv13_2/index.m3u8' -f flv -c copy -bsf:a aac_adtstoasc 'rtmp://localhost/live/livestream'; done

因为循环会不断重启ffmpeg,如果要结束推流,需要不断按ctrl+c,或者直接关掉终端(命令行窗口)。

关于ffmpeg的-re参数

推流请务必在开头加-re参数,否则可能会遇到间歇性卡顿,原因是流的发送/接收速度不稳定。对于直播流,如果网络延迟导致发送/接收速度跟不上,就应该直接丢帧,而不是后期加速发送。如果不加-re,播放的时候就会遇到流速不一致的问题,一会儿快一会儿慢,于是这里卡一下那里卡一下。-rerealtime,实时)参数保证了流的速度始终是1x,不会忽快忽慢导致卡顿。

观看地址

查看流状态:
http://localhost:8080/console/ng_index.html#/streams?port=1985

image.png

点预览就能观看,如果预览容易卡,可以尝试把观看地址后缀.flv改成.m3u8,可能会更流畅,例如:

http://ossrs.net/players/srs_player.html?vhost=__defaultVhost__&app=live&stream=livestream.m3u8&server=localhost&port=8080&autostart=false&schema=http

image.png

所有观看地址(按可靠程度排序,flv最不可靠,可能会卡住,不推荐;如果是远程观看,localhost换成机器IP):


推多个流到自建服务器

把推流地址rtmp://localhost/live/livestream里的livestream改成其他内容,就可以形成不同的流。

第一个终端里执行:

while true; do ffmpeg -re -i 'http://cctvalih5ca.v.myalicdn.com/live/cctv13_2/index.m3u8' -f flv -c copy -bsf:a aac_adtstoasc 'rtmp://localhost/live/cctv13'; done

第二个终端里执行:

while true; do ffmpeg -re -i 'http://cctvalih5ca.v.myalicdn.com/live/cctv2_2/index.m3u8' -f flv -c copy -bsf:a aac_adtstoasc 'rtmp://localhost/live/cctv2'; done

这样就有两个流可以看了。

image.png


用 OBS Studio 推流到自建服务器

如果是自制节目,也可以直接通过 OBS Studio 推流到SRS服务器,URL填写rtmp://localhost/live(如果是远程推流,localhost换成机器IP),流名称填写livestream

image.png

image.png

image.png


使用ffmpeg把直播流复制到多个网站

首先介绍一下直播网站的推流码和RTMP推流地址的关系。当你在直播网站看到以下信息时:

image.png

把“服务器地址”和“串流密钥”用/相连(如果服务器地址结尾已经有/,无需再加/),就得到可在ffmpeg命令行中使用的RTMP推流地址了。

所有直播网站都可以获得服务器地址和串流密钥,只是有的网站把它藏在了难以找到的地方。

哔哩哔哩推流码

https://link.bilibili.com/p/center/index?#/my-room/start-live

先注册成为主播,然后点击开播后可见

image.png

  • 服务器地址:rtmp://live-push.bilivideo.com/live-bvc/
  • 串流密钥:?streamname=live_123456_7890123456&key=不能告诉你&schedule=rtmp&pflag=1
  • 可在ffmpeg命令行中使用的RTMP推流地址:rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_123456_7890123456&key=不能告诉你&schedule=rtmp&pflag=1

斗鱼推流码

https://mp.douyu.com/live/main

先注册成为主播,然后点击开播后可见

image.png

  • 服务器地址:rtmp://sendtc3.douyu.com/live
  • 串流密钥:12345678abcdEFGH?wsSecret=不能告诉你&wsTime=61cd25c4&wsSeek=off&wm=0&tw=0&roirecognition=0&record=flv&origin=tct
  • 可在ffmpeg命令行中使用的RTMP推流地址:rtmp://sendtc3.douyu.com/live/12345678abcdEFGH?wsSecret=不能告诉你&wsTime=61cd25c4&wsSeek=off&wm=0&tw=0&roirecognition=0&record=flv&origin=tct

虎牙推流码

教程:http://help.huya.com/355
页面:https://i.huya.com/index.php?m=ProfileSetting#ktylts

需要用虎牙官方软件开播一次才可进入主播设置。建议先用虎牙手机app开播一次,可以顺便人脸识别实名认证。

图片.png

  • 从虎牙网站复制的推流地址可直接在ffmpeg中使用:rtmp://tx.direct.huya.com/huyalive/保密-保密-0-保密-保密-A-保密-1?seq=保密&type=simple

多网站推流命令

下面是同时推流到哔哩哔哩和斗鱼的例子:

while true; do
ffmpeg -re -f flv -listen 1 -i rtmp://0.0.0.0:1945/live/livestream \
  -f fifo -fifo_format flv -map 0:v -map 0:a -vtag 7 -atag 10 \
  -flags +global_header -flvflags no_duration_filesize \
  -drop_pkts_on_overflow 1 -attempt_recovery 1 -recover_any_error 1 -c copy \
    'rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_123456_7890123456&key=不能告诉你&schedule=rtmp&pflag=1' \
  -f fifo -fifo_format flv -map 0:v -map 0:a -vtag 7 -atag 10 \
  -flags +global_header -flvflags no_duration_filesize \
  -drop_pkts_on_overflow 1 -attempt_recovery 1 -recover_any_error 1 -c copy \
    'rtmp://sendtc3.douyu.com/live/12345678abcdEFGH?wsSecret=不能告诉你&wsTime=61cd25c4&wsSeek=off&wm=0&tw=0&roirecognition=0&record=flv&origin=tct' \
# end
done

因为循环会不断重启ffmpeg,如果要结束推流,需要不断按ctrl+c,或者直接关掉终端(命令行窗口)。

不断重复以下几行就能推流到更多网站:

  -f fifo -fifo_format flv -map 0:v -map 0:a -vtag 7 -atag 10 \
  -flags +global_header -flvflags no_duration_filesize \
  -drop_pkts_on_overflow 1 -attempt_recovery 1 -recover_any_error 1 -c copy \
    'rtmp://服务器地址/串流密钥' \

如果你想同时推流到SRS服务器,那么串流密钥随便写就可以,比如:

  • rtmp://localhost/live/aaa
  • rtmp://localhost/live/bbb

不同的串流密钥就形成不同的流,可以分别观看。

最后,OBS推流到以下服务器,你就可以同时在多个网站开播了:

  • URL:rtmp://localhost:1945/live
  • 流名称:livestream

image.png


推流的同时录像

以下是保存直播录像到/home/hu60/Videos/我的直播录像-日期-时间.flv,并同时推流到哔哩哔哩和斗鱼的例子:

while true; do
ffmpeg -re -f flv -listen 1 -i rtmp://0.0.0.0:1945/live/livestream \
  -f flv -flvflags no_duration_filesize -c copy "/home/hu60/Videos/我的直播录像-$(date '+%F_%H-%M-%S').flv" \
  -f fifo -fifo_format flv -map 0:v -map 0:a -vtag 7 -atag 10 \
  -flags +global_header -flvflags no_duration_filesize \
  -drop_pkts_on_overflow 1 -attempt_recovery 1 -recover_any_error 1 -c copy \
    'rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_123456_7890123456&key=不能告诉你&schedule=rtmp&pflag=1' \
  -f fifo -fifo_format flv -map 0:v -map 0:a -vtag 7 -atag 10 \
  -flags +global_header -flvflags no_duration_filesize \
  -drop_pkts_on_overflow 1 -attempt_recovery 1 -recover_any_error 1 -c copy \
    'rtmp://sendtc3.douyu.com/live/12345678abcdEFGH?wsSecret=不能告诉你&wsTime=61cd25c4&wsSeek=off&wm=0&tw=0&roirecognition=0&record=flv&origin=tct' \
# end
done

自由组合ffmpeg的输入和输出

你们应该看出来了,ffmpeg的命令是可以自由组合的。它分成输入和输出两部分,输入只能有一个,输出可以有多个。只要把一个输入和至少一个输出放在一起,就可以构成完整的命令。

Linux Shell 命令语法小知识:

  1. 任意两个参数之间都要用空格隔开,当我们说“加在后面”或者“放在一起”时,别忘了打空格。
  2. 如果一行太长,可以在结尾加\然后另起一行。“公网上的推流服务器”就是由多行组成的,如果你想再另起一行写后续命令,别忘了在结尾加\。如果你想在一行的末尾添加参数,也要加在\的前面。

输入

采集现有直播流

支持m3u8、rtmp等多种格式

-re -i 'http://cctvalih5ca.v.myalicdn.com/live/cctv13_2/index.m3u8'

本地视频文件

支持几乎所有视频文件格式

-re -i './我的视频.flv'

接收其他软件的推流

比如可以使用OBS推流给ffmpeg

  • 其中0.0.0.0是监听IP,1945是监听端口。
  • live是推流路径,livestream是推流码,其实两者都可以省略不写,推流时只会产生一条警告说路径不匹配,并不会影响实际推流。
-re -f flv -listen 1 -i rtmp://0.0.0.0:1945/live/livestream

输出

本地文件

也可以输出成mp4、mkv等,但是建议使用flv,不容易损坏,而且和推流的兼容性高(RTMP推流推送的就是类似flv的数据结构)。

-f flv -flvflags no_duration_filesize -c copy "文件名.flv"

局域网内的推流服务器

live是推流路径,livestream是推流名称。把livestream改成其他名称就可以生成多个不同的流。

如果推流服务器不在局域网内,延迟和网速都不能保证,就不能用这个命令,因为这个命令一旦推流卡顿就会自动退出,导致直播中断。

公网推流应该使用后面的公网专用命令,当然局域网推流也可以用那个命令,可能会更稳定。

-f flv -c copy 'rtmp://localhost/live/livestream'

如果推流时报错说要加-bsf:a aac_adtstoasc,就把它加在-c copy的后面:

-f flv -c copy -bsf:a aac_adtstoasc 'rtmp://localhost/live/livestream'

公网上的推流服务器

  • drop_pkts_on_overflow是卡顿时自动丢帧,该选项非常重要,否则一旦出现卡顿就无法自动缓解了,推流可能会一直卡顿下去。
  • attempt_recovery是掉线时自动重连。
  • recover_any_error是无论发生什么错误都自动重连。
  -f fifo -fifo_format flv -map 0:v -map 0:a -vtag 7 -atag 10 \
  -flags +global_header -flvflags no_duration_filesize \
  -drop_pkts_on_overflow 1 -attempt_recovery 1 -recover_any_error 1 -c copy \
    'rtmp://视频网站给出的推流服务器地址/视频网站给出的串流密钥'

如果推流时报错说要加-bsf:a aac_adtstoasc,就把它加在-c copy的后面:

  -f fifo -fifo_format flv -map 0:v -map 0:a -vtag 7 -atag 10 \
  -flags +global_header -flvflags no_duration_filesize \
  -drop_pkts_on_overflow 1 -attempt_recovery 1 -recover_any_error 1 -c copy -bsf:a aac_adtstoasc \
    'rtmp://视频网站给出的推流服务器地址/视频网站给出的串流密钥'

关于 -vtag 7 -atag 10

它们用于指定视频和音频编码,-vtag 7表示AVC(H.264)视频,-atag 10表示AAC音频。

如果你的音频格式是MP3,可改成-vtag 7 -atag 2

  • -vtag
2 = Sorenson H.263
3 = Screen video
4 = On2 VP6
5 = On2 VP6 with alpha channel
6 = Screen video version 2
7 = AVC(H.264)
  • -atag
0 = Linear PCM, platform endian
1 = ADPCM
2 = MP3
3 = Linear PCM, little endian
4 = Nellymoser 16 kHz mono
5 = Nellymoser 8 kHz mono
6 = Nellymoser
7 = G.711 A-law logarithmic PCM , reserved
8 = G.711 mu-law logarithmic PCM , reserved
9 = reserved
10 = AAC (supported in Flash Player 9,0,115,0 and higher)
11 = Speex (supported in Flash Player 10 and higher)
14 = MP3 8 kHz , reserved
15 = Device-specific sound , reserved

编码转换

如果你要推视频文件,建议推流前进行编码转换,转为FLV格式,视频编码H.264/AVC,音频编码AAC

ffmpeg也许支持在推流时进行编码转换,但不建议使用,我没成功过。


Linux Shell 命令语法小知识:

  1. 任意两个参数之间都要用空格隔开,当我们说“加在后面”或者“放在一起”时,别忘了打空格。
  2. 如果一行太长,可以在结尾加\然后另起一行。“公网上的推流服务器”就是由多行组成的,如果你想再另起一行写后续命令,别忘了在结尾加\。如果你想在一行的末尾添加参数,也要加在\的前面。
回复列表(10)
添加新回复
回复需要登录