利用手机摄像头串流实现远程监控

国庆假期在家和猫猫玩的不亦乐乎,由于中途有两天不在家,还是蛮担心它们会不会被饿到的,临走的时候才想起可以利用旧手机的摄像头以及现有的公网的服务器搭一个简易的监控,实现远程访问,闲暇时间也可以看看它们。这两天就基于这个想法做了一些实现。

经网上调研,决定采用rtmp流式传输方案(因为有现成的轮子,易实现,咱要站在巨人的肩膀上),项目可分为三个角色,手机发送端、服务器处理端、用户接收端。旧手机将实时画面传输至服务器,用户通过手机的浏览器或播放器获取服务器上的画面。

具体实现:

  • 发送端采用IRL Pro软件
  • 服务端采用SRS(Simple Realtime Server)开源项目方案
  • 接收端可采用SRS方案提供的浏览器终端,或者VLC播放器软件

服务端的SRS项目部署总体而言还是比较简单的,首先安装
Docker,而后运行代码,使SRS在后台运行。

docker run --name srs -p 1935:1935 -p 1985:1985 -p 8080:8080 \
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5

再运行代码验证是否部署成功,以下命令使用ffmpeg工具将一段演示视频推流至SRS服务器,此时任意设备登录SRS console(服务器IP地址:8080),即可预览该演示视频。

docker run --name srspush registry.cn-hangzhou.aliyuncs.com/ossrs/srs:encoder \
ffmpeg -stream_loop -1 -re -i doc/source.flv -c copy \
-f flv rtmp://host.docker.internal/live/livestream

值得注意的是,这里的推流地址host.docker.internal是host主机地址(不能直接写127.0.0.1,因为这是srspush容器的ip地址),不过在Linux可能不支持该写法,可以先查询docker0网桥的ip地址,然后填入即可。

视频演示:Bilibili

一些心得

这是我第一次成功部署Docker应用,之前试过HomeAssistant的Docker部署,但碍于项目复杂又对Docker并不熟悉,并没有成功。这次成功部署对Docker也有了一些理解,就在这里梳理一下。

Docker是一个开源的应用容器引擎,开发者打包他们的应用以及运行环境到容器中,用户可以通过Docker快速灵活的部署它们。Docker在概念上类似Vmware等虚拟机,但是Docker更轻量,它不会去模拟底层的硬件和操作系统 ,只会为每一个应用提供完全隔离的运行环境。你可以在容器中配置不同的应用环境,并且不同的环境之间互相不影响,这个“环境”在Docker中也被称作为Container(容器)。容器内的应用进程直接运行于宿主的内核。相比我使用过的Pipenv等Python打包虚拟环境,它的层级又更高,前者只关注Python相关的环境。

Docker运行需要有一个基础的镜像(Image),比如可以根据需要,拉取python、java等不同环境的镜像。这个项目拉取的是SRS5.0的镜像,将它实例化后便成为一个容器,容器可以被创建、启动、停止、删除、暂停等,容器的实质是进程。

容器之间的通信:docker0 是 Docker 默认创建的虚拟网桥,主要用于连接容器与宿主机网络。它通过Bridge桥接模式实现容器间的通信以及容器与外部网络的交互。通过docker0的IP地址(即host.docker.internal,可通过ip addr查询),可以访问host上的服务。处于同一网络的容器之间可以相互访问。每个容器都有127.0.0.1地址,代表该容器的地址,要访问其他容器,可以通过容器名或者容器的IP地址。上文代码中的-p选项实现了端口映射,使host能够访问容器内的服务。

例:上面的推流地址rtmp://host.docker.internal/live可以写成
rtmp://srs/live(同一网络,容器名)
rtmp://172.18.0.2/live(同一网络下的SRS容器IP地址)
rtmp://172.18.0.1/live (主机虚拟网卡IP地址,通过host服务访问,SRS开启端口映射)

Docker还支持Host网络模式,此时其与host具有相同IP地址,可能会造成端口冲突,优点是网络模型简单,性能高。

下面列举一些常用命令,供参考:

docker run --name name --network mynet 新建并运行
docker start/stop  运行/停止已有容器
docker rm 删除
docker ps -a 列出所有容器
docker network ls 列出所有网络
docker inspect srs | grep IPAddress 查询容器IP地址
docker network create 创建一个新的网络
docker network connect <network> <container> 连接容器到网络
docker inspect 获取容器信息
docker exec -it <container> /bin/bash 进入容器终端

这篇文章写完发现网站崩了,外部访问服务器端口死活连接不上,排查了几个小时原因,最后无奈重启,竟然恢复了…也许是腾讯云防火墙设置的问题,也许是安装docker的原因,唉,经验+1。