文章目录
一、SRS国标GB28181搭建
下面两篇文章写的很详细,这里就不作赘述了。
国产开源流媒体SRS4.0对视频监控GB28181的支持
支持对接GB28181吗?监控,智能摄像头,国标推流,RTSP
摄像头配置以及web demo
二、FRP内网穿透
1.SRS配置文件
# push gb28181 stream to SRS.
listen 7009;
max_connections 1000;
daemon off;
srs_log_tank console;
http_api {
enabled on;
listen 11985;
}
http_server {
enabled on;
listen 18080;
}
stats {
network 0;
}
stream_caster {
enabled on;
caster gb28181;
# 转发流到rtmp服务器地址与端口
# TODO: https://github.com/ossrs/srs/pull/1679/files#r400875104
# [stream] is VideoChannelCodecID(视频通道编码ID) for sip
# 自动创建的道通[stream] 是‘chid[ssrc]’ [ssrc]是rtp的ssrc
# [ssrc] rtp中的ssrc
output rtmp://182.xx.xx.xx:7009/live/[stream];
# 接收设备端rtp流的多路复用端口
listen 7010;
# 多路复用端口类型,on为tcp,off为udp
# 默认:on
tcp_enable on;
# rtp接收监听端口范围,最小值
rtp_port_min 58200;
# rtp接收监听端口范围,最大值
rtp_port_max 58300;
# 是否等待关键帧之后,再转发,
# off:不需等待,直接转发
# on:等第一个关键帧后,再转发
wait_keyframe on;
# rtp包空闲等待时间,如果指定时间没有收到任何包
# rtp监听连接自动停止,发送BYE命令
rtp_idle_timeout 30;
# 是否转发音频流
# 目前只支持aac格式,所以需要设备支持aac格式
# on:转发音频
# off:不转发音频,只有视频
# *注意*!!!:flv 只支持11025 22050 44100 三种
# 如果设备端没有三种中任何一个,转发时为自动选择一种格式
# 同时也会将adts的头封装在flv aac raw数据中
# 这样的话播放器为自动通过adts头自动选择采样频率
# 像ffplay, vlc都可以,但是flash是没有声音,
# 因为flash,只支持11025 22050 44100
audio_enable off;
# 是否开启rtp缓冲
# 开启之后能有效解决rtp乱序等问题
# tcp模式建议关闭
jitterbuffer_enable off;
# 服务器主机号,可以域名或ip地址
# 也就是设备端将媒体发送的地址,如果是服务器是内外网
# 需要写外网地址,
# 调用api创建stream session时返回ip地址也是host
# $CANDIDATE 是系统环境变量,从环境变量获取地址,如果没有配置,用*
# *代表指定stats network 的网卡号地址,如果没有配置network,默认则是第0号网卡地址
# TODO: https://github.com/ossrs/srs/pull/1679/files#r400917594
host 182.xx.xx.xx;
#根据收到ps rtp包自带创建rtmp媒体通道,不需要api接口创建
#rtmp地址参数[stream] 就是通道id 格式chid[ssrc]
auto_create_channel off;
sip {
# 是否启用srs内部sip信令
# 为on信令走srs, off 只转发ps流
enabled on;
# sip监听udp端口
listen 7035;
# SIP server ID(SIP服务器ID).
# 设备端配置编号需要与该值一致,否则无法注册
serial 34020000002000000001;
# SIP server domain(SIP服务器域)
realm 3402000000;
# 服务端发送ack后,接收回应的超时时间,单位为秒
# 如果指定时间没有回应,认为失败
ack_timeout 30;
# 设备心跳维持时间,如果指定时间内(秒)没有接收一个心跳
# 认为设备离线
keepalive_timeout 120;
# 注册之后是否自动给设备端发送invite
# on: 是 off 不是,需要通过api控制
auto_play on;
# 设备将流发送的端口,是否固定
# on 发送流到多路复用端口 如9000
# off 自动从rtp_mix_port - rtp_max_port 之间的值中
# 选一个可以用的端口
invite_port_fixed on;
# 向设备或下级域查询设备列表的间隔,单位(秒)
# 默认60秒
query_catalog_interval 60;
}
}
rtc_server {
enabled on;
# Listen at udp://8000
listen 7037;
#
# The $CANDIDATE means fetch from env, if not configed, use * as default.
#
# The * means retrieving server IP automatically, from all network interfaces,
# @see https://github.com/ossrs/srs/issues/307#issuecomment-599028124
candidate 182.92.xx.xx;
}
vhost __defaultVhost__ {
rtc {
enabled on;
bframe discard;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
}
2.FRP配置文件
# srs_gb28181
#tcp
[srs_gb28181_rtmp]
type = tcp
local_ip = 127.0.0.1
local_port = 7009
remote_port = 7009
[srs_gb28181_7010]
type = tcp
local_ip = 127.0.0.1
local_port = 7010
remote_port = 7010
[srs_gb28181_7011]
type = tcp
local_ip = 127.0.0.1
local_port = 7011
remote_port = 7011
#http
[srs_gb28181_18080]
type = http
local_port = 18080
subdomain = gb-18080
[srs_gb28181_11985]
type = http
local_port = 11985
subdomain = gb-11985
#udp
[srs_gb28181_7035]
type = udp
local_ip = 127.0.0.1
local_port = 7035
remote_port = 7035
[srs_gb28181_7037]
type = udp
local_ip = 127.0.0.1
local_port = 7037
remote_port = 7037
3.连接摄像头
3.1 摄像头配置
3.2 效果展示
三、海康/大华,RTSP推流小工具(不可取)
PS:主动推流不可取,受网络影响容易断线
配置好config.json中的摄像头rtsp地址、编号那些就可以点击start.bat推流了。
jre使用的是从jdk1.8.0_181中复制过来的,这个jre只适用于windows 64
四、BUG摄像头断流问题 2021-10-14
通过长时间的运行测试,会发现受网络原因等,每过一段时间摄像头会出现在srs注册成功了,却没有视频流的问题。集成spring定时任务,定时检查摄像头状态,如果异常直接从srs内部删除,等待摄像头的下一次注册。github官方文档
/**
* 处理摄像头掉线问题的定时任务
*/
@Scheduled(cron = "${scheduleTask.check-state}")
public void unregisterWebCam() {
//所有的流的地址
List<Map<String, Object>> allStreams = srsUtil.getAllStreams();
//srs中存在的sessions 为了解决摄像头流不存在,sip存在的情况
srsUtil.getSessions().stream()
.filter(session ->
allStreams.stream()
.allMatch(o -> checkActive(o) || !o.get("name").toString().contains(session.get("id").toString()))
).forEach(map -> srsUtil.sendUnregister(Optional.ofNullable(map.get("id")).orElse("-999").toString()));
}
private boolean checkActive(Map<String, Object> o) {
Map<String, Object> publish = (Map<String, Object>) o.get("publish");
return !Boolean.parseBoolean(publish.get("active").toString());
}
五、SRS回调验证token是否合法 2021-12-17
配置后台回调接口
vhost __defaultVhost__ {
rtc {
enabled on;
bframe discard;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
http_hooks {
enabled on;
on_play http://192.168.0.100:8282/waterHead/webcam/onPlay;
}
}
controller
/**
* srs回调接口
*/
@SysVisitLog(isActive = false)
@RequestMapping(value = "onPlay", method = RequestMethod.POST)
public Integer onPlay(@RequestBody CallBackDataOnPlay data) {
try {
return service.onPlay(data);
} catch (Exception e) {
e.printStackTrace();
return 1;
}
}
service
@Override
public Integer onPlay(CallBackDataOnPlay data) throws ExecutionException {
String param = data.getParam();
if (StringUtils.isNotBlank(param)) {
String token = StringUtils.countMatches(param, "&") > 0 ?
StringUtils.substringBetween(param, "token=", "&") :
StringUtils.substringAfter(param, "token=");
if (StringUtils.isNotBlank(token) &&
(token.equals(srsUtil.getAiToken()) || StringUtils.isNotBlank(WaterHeadCache.TOKEN_CACHE.get(token)))) {
//这里可以加相应的业务逻辑
return 0;
}
}
return 1;
}
CallBackDataOnPlay 实体
import lombok.Data;
/**
* SRS回调数据
* @author LNX
*/
@Data
public class CallBackDataOnPlay {
private String server_id;
private String action ;
private String client_id ;
private String ip ;
private String vhost ;
private String app ;
private String pageUrl ;
private String stream ;
private String param ;
}
访问视频流应该加token
http://xxxx/live/34020000001320000101@34020000001320000101.flv?token=a130424a475410f7fc7b57a1f0b825f44ec7021e0b479e2f5360b97fddcb8ab9eff3c714fa7fed17f10fc8a21ec297d8f57718abc32e6fee52563dca92e2a64d2154b70a66dcea8966246a93cfec1048d28becdbbdd0a1b2efcaf516f7eebdb38adf06aa26198d8c7fdc83cb57a00b95e46c2b6a1f0c18516cead0e34e09845da3721b1a3334efb0
总结
在搭建过程中遇到了很多问题,但都是小问题。最重要的问题就是,要确保内网穿透出来的端口进出都没问题。我因为一个端口阿里云防火墙没开,搞了一下午。。