在janus Steaming插件中,官方提供了三种不同的流传输方法,即:
- 由文件(歌曲)产生的按需流:访问此流的不同用户都会从头开始播放该音频文件。
- 仍由文件(广播)产生的伪实时流:访问此流的不同用户都将收到相同的音频。
- 由gstreamer发起的实时流:对于伪实时流,不同的用户将获得相同的视频画面。
前两个在我们安装完janus后是可以直接播放出来的,第三种则需要我们额外部署rtp推流的程序。
官方使用的是使用GStreamer,但使用了FFmpeg,LibAV或其它也可以。
考虑到FFmpeg在流媒体圈子里名气最大,所以就选它了。
一、rtp参数确定
在janus.plugin.streaming.jcfg配置文件里,我们可以找到Steaming插件对rtp流的定义。
rtp-sample: {
type = "rtp"
id = 1
description = "Opus/VP8 live stream coming from external source"
metadata = "You can use this metadata section to put any info you want!"
audio = true
video = true
audioport = 5002
audiopt = 111
audiortpmap = "opus/48000/2"
videoport = 5004
videopt = 100
videortpmap = "VP8/90000"
secret = "adminpwd"
}
从中可以看出:
rtp音频流的端口号是5002,负载类型是111,音频编码为opus格式,音频采样率为48000,音频声道数为2;
rtp视频流的端口号是5004,负载类型是100,视频编码为VP8格式。
二、ffmpeg推流
ffmpeg -re -stream_loop -1 -i /home/test.mp4 -an -vcodec libvpx -payload_type 100 -f rtp rtp://127.0.0.1:5004?pkt_size=1200 -vn -acodec libopus -payload_type 111 -ar 48000 -ac 2 -f rtp rtp://127.0.0.1:5002?pkt_size=1200
-re:按照帧率发送,否则会按照最高速率发送
-i:指定输入文件名
-stream_loop:指定循环读取视频源的次数,-1为无限循环
-vcodec( -c:v ):设置视频编解码器,未设置时则使用与输入文件相同之编解码器
-acodec ( -c:a ):设置音频编解码器,未设置时则使用与输入文件相同之编解码器
-f:设置输出格式
-pkt_size:rtp发送的最大长度
-payload_type:rtp的负载类型
-an:不处理音频
-vn:不处理视频
-ar:设置音频采样率
-ac:设置音频声道数量
这样生成的rtp流的SDP如下,完全符合janus对rtp流的规定
SDP:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
t=0 0
a=tool:libavformat 58.29.100
m=video 5004 RTP/AVP 100
c=IN IP4 127.0.0.1
b=AS:200
a=rtpmap:100 VP8/90000
m=audio 5002 RTP/AVP 111
c=IN IP4 127.0.0.1
b=AS:96
a=rtpmap:111 opus/48000/2
a=fmtp:111 sprop-stereo=1
效果如下:
ffmpeg推流唯一的缺陷就是CPU占用率太高,一直是99%,对音视频实时编解码太消耗cpu资源了。
三、改进
CPU占用率过高的问题解法如下,
首先本地将MP4封装文件转码为WebM封装:
ffmpeg -i test.mp4 -c:v libvpx -crf 10 -b:v 1M output.webm
MP4封装:H264视频编码 + AAC音频编码
WebM封装:VP8视频编码 + Vorbis音频编码
OGG封装:Theora视频编码 + Vorbis音频编码
然后推流时就可以不用再转码了
ffmpeg -re -stream_loop -1 -i /home/output.webm -an -vcodec copy -payload_type 100 -f rtp rtp://127.0.0.1:5004?pkt_size=1200 -vn -acodec copy -payload_type 111 -f rtp rtp://127.0.0.1:5002?pkt_size=1200