概述
使用srs来进行直播流转码时,如果直接配置了转码,则无论有无客户端在拉取转码流,转码都会进行。
需要注意到,转码是一件非常消耗CPU资源的事情,所以实现按需转码(只有在转码流被拉取时,才进行转码)是一件非常值得的事情。
srs的FFmpeg转码时的推拉流逻辑
在srs的vhost中,可以配置transcode来使用FFmpeg对流进行转码。
例如下面配置:
1 2 3 4 5 6 7 8 9 10 11 12 13
| listen 1935; vhost www.transcode.com { transcode { enabled on; ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine ff { enabled on; vcodec copy; acodec copy; output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; } } }
|
假设一路流推送到rtmp://www.transcode.com/testapp/teststream
,上面所配置的ffmpeg立即就会对这路流进行转码(即使没有人拉流),
因为它转码的逻辑是拉流到FFmpeg->转码->推流到output所定义的地方
。
那么上面配置中的写法就表示:
- 从
rtmp://127.0.0.1:1935/testapp?vhost=www.transcode.com/teststream
拉流。
- 转码。
- 推流到
rtmp://127.0.0.1:1935/testapp?vhost=www.transcode.com/teststream_ff
也就是转码后反推了一路流到 www.transcode.com
这个vhost下面(由于output可以自定义,所以实际上想推到哪里都可以)。
所以转码一旦开始,就会不断拉流,转码,推流,与有没有人在拉流没有关系,它会持续占用CPU资源。
如何实现srs可控的FFmpeg转码
首先,如果在一个vhost下同时配置 remote 和 transcode,则会出来不先拉原始流就无法拉取转码流的问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| vhost lrm.test.com { mode remote; origin 192.168.90.229:2019; transcode { enabled on; ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine ff { enabled on; vfilter { } vcodec libx264; vbitrate 3500; vfps 60; vwidth 1920; vheight 1080; vthreads 2; vprofile baseline; vpreset superfast; vparams { } acodec libfdk_aac; abitrate 45; asample_rate 44100; achannels 2; aparams { } output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; } } }
|
如上面的配置,如果不先拉取rtmp://lrm.test.com/app/streamname
的未转码流,则无法拉取rtmp://lrm.test.com/app/streamname_ff
的转码流,
并且只要转码一旦开始,就不会停止。
所以,如果想要实现可控转码,则只能通过需要转码时,再下发转码配置来实现,只通过srs本身来控制貌似不行。
按需转码实现思路:
- 如何知道有用户拉流:
用户拉流触发srs的HTTPCallBack
-> 开启转码
。
- 如何开启转码:在用于转码的srs节点上
下发ingest配置从origin拉取原始流
-> 进行转码后将转码流推回origin
。
所以这里的关键在于两点:使用HTTPCallBack来获知拉流信息;使用ingest来拉取原流进行转码,转码操作不会影响srs集群的任何配置。
ingest配置一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| vhost lrm.test.com { ingest livestream { enabled on; input { type stream; url rtmp://192.168.90.229:2019/persist?vhost=lrm.test.com/long; } ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine 720_60 { enabled on; vfilter { } vcodec libx264; vbitrate 3500; vfps 60; vwidth 0; vheight 0; vthreads 12; vprofile main; vpreset fast; vparams { maxrate:v 3500k; minrate:v 3500k; bufsize:v 3500k; } acodec libfdk_aac; abitrate 50; asample_rate 44100; achannels 2; aparams { } output rtmp://192.168.90.229:2019/persist?vhost=lrm.test.com/long_720_60; } } }
|
ingest配置二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| vhost lrm.test.com { ingest livestream { enabled on; input { type stream; url rtmp://192.168.90.229:2019/persist?vhost=lrm.test.com/long; } ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine 1 { enabled off; output rtmp://127.0.0.1:2019/persist?vhost=www.transcode.com/long; } engine 2 { enabled off; output rtmp://127.0.0.1:2019/persist?vhost=www.transcode2.com/long;
} } }
vhost www.transcode.com { transcode { enabled off; ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine 720_60 { enabled on; vfilter { } vcodec libx264; vbitrate 3500; vfps 60; vwidth 0; vheight 0; vthreads 12; vprofile main; vpreset fast; vparams { maxrate:v 3500k; minrate:v 3500k; bufsize:v 3500k; } acodec libfdk_aac; abitrate 50; asample_rate 44100; achannels 2; aparams { } output rtmp://192.168.90.229:2019/persist?vhost=lrm.test.com/long_720_60; } } }
vhost www.transcode2.com { transcode { enabled on; ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine 720_60_1 { enabled on; vfilter { filter_complex 'scale=1280:-1'; } vcodec libx264; vbitrate 3500; vfps 60; vwidth 0; vheight 0; vthreads 12; vprofile main; vpreset fast; vparams { maxrate:v 3500k; minrate:v 3500k; bufsize:v 3500k; } acodec libfdk_aac; abitrate 50; asample_rate 44100; achannels 2; aparams { } output rtmp://192.168.90.229:2019/persist?vhost=lrm.test.com/long_720_60_1; } } }
|
虽然两种方式其实可以达到一样的效果(方式一中也可以添加多个engine),哪种方便用哪一种。