树莓派-制作家庭监控-在云端实时查看
作者:Vic ,分类:Raspberry-Pi(树莓派) 发布于 2020-06-11 14:53:32.0

画了个图方便理解 , 解决方案如下


ffmpeg推流命令

命令和编码参数不同 , 会导致延时时长不同 , 我的延时在本地局域网在1-2秒左右 , ffmpeg的更多命令可以看官网 ffmpeg-doc , 关于-preset ultrafast -tune:v zerolatency 编码速度参数看官方 Video Encoding Guide

    1. ffmpeg -framerate 15 -video_size 640x480 -i /dev/video0 -vcodec h264_omx -preset ultrafast -tune:v zerolatency -f flv rtmp://xxx.cn:1935/app

nginx rtmp 配置

on_playon_publish通知类的请求到tomcat , rtmp会把客户端的ip等信息放到Parameter中方便service决策拉流者或推流者的身份 并响应给rtmp对应的http状态码让rtmp知道 , 该连接是允许继续操作还是丢弃该请求 .

    • HTTP 2xx code continues RTMP session : 2xx状态码继续操作保持会话
    • HTTP 3xx将RTMP重定向到另一个流,该流的名称来自 LocationHTTP响应标头。如果新的流名称以开头,rtmp:// 则会创建远程中继。中继要求指定IP地址而不是域名,并且仅适用于大于1.3.10的Nginx版本。另请参阅notify_relay_redirect。
    • 否则,RTMP连接将被丢弃 , 返回4xx或5xx状态码将被rtmp丢弃连接
    • 如果上面配置参数不理解或你有其他需求 , 可以看官方github文档 ,我就是一点一点这么理解的 rtmp-github , 看不懂可以翻译
    1. # live stream conf
    2. rtmp {
    3. server {
    4. listen 1935;
    5. application app {
    6. live on; #开启直播
    7. notify_method get; # 通知请求方法
    8. on_play http://127.0.0.1:8080/video/play; # 请求到tomcat的 拉流连接通知决策地址
    9. on_publish http://127.0.0.1:8080/video/publish; # 请求到tomcat的 推流连接通知决策地址
    10. max_connections 10; # 连接数量
    11. # 实时记录视频到文件
    12. recorder savelive{
    13. record video; # 只记录视频,也可以使用all参数同时记录音频和视频
    14. record_max_size 200M; # 单个文件最大200M
    15. # record_path /home/rpi-video; # 文件路径
    16. record_suffix %Y-%m-%d-%H_%M.flv; # 已年月日时分作为视频名称
    17. }
    18. }
    19. }
    20. }

还可以在http块加入以下配置, 方便查看rtmp提供的实时连接日志 , http://127.0.0.1:8080/stat

    1. location /stat {
    2. rtmp_stat all;
    3. rtmp_stat_stylesheet stat.xsl;
    4. }
    5. location /stat.xsl {
    6. root  /你的路径/nginx-rtmp-module-master;  #the path of nginx-rtmp-module
    7. }

Tomcat处理通知决策

我这里用的是ip白名单模式来防止其他人恶意推流和拉流 , 刚才上面也讲了, 允许的连接返回2xx状态就可以了 , 我这之所以用throw的方式返回2xx和其他状态, 因为我正常随意返回个字符串就应该代表2xx的状态了 , 但测试了多次不行 , 最后就选了这种方式 . flowCache是个缓存 , 你可以把允许连接的IP白名单加入里面 , 就可以了 , 我觉得很方便 , request.getParameter("addr"); 是rtmp透传过来的客户端信息 .在 rtmp-github 里都有.

    1. /**
    2. * nginx rtmp 播放流连接决策
    3. * @return
    4. */
    5. @ResponseBody
    6. @ResponseStatus
    7. @RequestMapping(value = "/play",method = RequestMethod.GET)
    8. public String play(HttpServletRequest request) {
    9. String ip = request.getParameter("addr");
    10. // 该ip是否在 允许拉流的白名单中
    11. if(flowCache.exist(ip)){
    12. throw new PermissionPassedException("permission passed");
    13. }else{
    14. flowCache.put(ip,"拉流被拒绝"+DateTool.now());
    15. throw new PermissionDeniedException("permission denied");
    16. }
    17. }
    18. /**
    19. * nginx rtmp 发布流连接决策
    20. * @return
    21. */
    22. @ResponseBody
    23. @RequestMapping(value = "/publish",method = RequestMethod.GET)
    24. public String publish(HttpServletRequest request) {
    25. String ip = request.getParameter("addr");
    26. // 该ip是否在 允许推流的白名单中
    27. if(flowCache.exist(ip)){
    28. throw new PermissionPassedException("permission passed");
    29. }else{
    30. flowCache.put(ip,"推流被拒绝:"+ DateTool.now());
    31. throw new PermissionDeniedException("permission denied");
    32. }
    33. }

允许连接

    1. /**
    2. * 允许流访问
    3. */
    4. @ResponseStatus(value = HttpStatus.OK)
    5. public class PermissionPassedException extends RuntimeException{
    6. public PermissionPassedException(String message) {
    7. super(message);
    8. }
    9. }

拒绝连接

    1. /**
    2. * 无权限访问
    3. */
    4. @ResponseStatus(value = HttpStatus.NOT_FOUND)
    5. public class PermissionDeniedException extends RuntimeException{
    6. public PermissionDeniedException(String message) {
    7. super(message);
    8. }
    9. }

到这里整个树莓派家庭监控就实现了 本文讲的不多但都是重点 , 需要有nginx,树莓派,ffmgeg等等基础支持 , 我算是现学现卖, 准备工作和相关知识研究了差不多1个多月 , 现在我的家庭监控已经部署在阿里云的服务器上 , 随时随地使用PC和手机实现推流和拉流的操作 , 和直播的原理相同 , 但有一点要注意 : 阿里云的实例安全安全组一定要配置开启rtmp协议的端口号 , 并且系统防火墙也要配置开放端口 !