intel边缘计算盒子主要程序:
1.mqtt 用于程序心跳上报,盒子系统信息上报以及云端配置下发
2.本地web使用nginx+fcgi
4.frp 用于反向连接
5.推流程序ffmpeg以及截图进程
6.扫描局域网摄像机程序
7.定时任务进程用于bug fix
8.crontab的定时任务,清理日志等
9.supervisor管理所有应用层程序
一、新零售本地页面直播与录播
1. https://github.com/winshining/nginx-http-flv-module 使用了这个nginx的module,作为推流服务器
2. ffmpeg rtsp转rtmp
3. 直播是flv
4.录播是m3u8(ts文件)
因为不是做那种直播平台的,做的是监控上传ts文件。直播的延迟在7秒左右,长时间直播,延迟估计会越来越大,网上说有自动追帧的方法解决。
flv ---ngx---ffmpeg----rtsp
nginx的配置,nginx-http-flv-module 的官网或者rtmp server的官网都有介绍。
ffpmeg的硬编码:https://trac.ffmpeg.org/wiki/Hardware/QuickSync
可采用flv.js播放3.1返回的直播链接,javascript代码示例如下:
if(flvjs.isSupported()) {varvideoElement=document.getElementById('videoElement');varflvPlayer=flvjs.createPlayer({type:'flv',url:'http://xxxxxx/live?app=cams&stream=C100172' });flvPlayer.attachMediaElement(videoElement);flvPlayer.load();flvPlayer.play(); }
可采用hls.js播放3.2返回的录播链接,javascript代码示例如下:
varvideo=document.getElementById('video');if(Hls.isSupported()) {varhls=newHls();hls.loadSource('http://xxxxxx/mplay.m3u8?cameraid=C100172&ts=1578450015000&reqid=8at425qhx37f23bz');
hls.attachMedia(video);hls.on(Hls.Events.MANIFEST_PARSED,function() {video.play(); }); }elseif(video.canPlayType('application/vnd.apple.mpegurl')) {video.src='http://xxxx:6109/mplay.m3u8?cameraid=C100172&ts=1578450015000&reqid=8at425qhx37f23bz';
video.addEventListener('loadedmetadata',function() {
video.play();
});
}
supervisord起的一个进程来实时管理ffmpeg推流
exec ffmpeg -stimeout 10000000 -rtsp_transport tcp -loglevel quiet -i $rtsp -c copy -f flv -an "rtmp://127.0.0.1/cams/$mac" >/dev/null 2>&1
截图:
ffmpeg -stimeout 10000000 -rtsp_transport tcp -loglevel quiet -y -i $rtsp -vframes 1 /opt/$mac\_snapshot.jpg
二、红外疫情防控一体机的录屏的直播与录播
camid=$1
res=$2
if [ -f /home/gg/conf/ird_hires ]; then
scale=1
rate=10
else
scale=0.5
rate=5
fi
gop=$((rate * 2))
#sx=$((x/2))
#sy=$((y/2))
#exec nice -n 10 /usr/bin/ffmpeg -f x11grab -s "$x"x"$y" -r 5 -loglevel quiet -i :0.0 -vcodec libx264 -preset ultrafast -vf scale="$sx":"$sy" -f flv -an "rtmp://127.0.0.1/cams/$camid" >/dev/null 2>&1
exec nice -n 10 /usr/bin/ffmpeg -f x11grab -s "$res" -r $rate -loglevel quiet -i :0.0 -g $gop -vcodec libx264 -preset ultrafast -vf scale="iw*$scale":"ih*$scale" -f flv -an "rtmp://127.0.0.1/cams/$camid" >/dev/null 2>&1
移动侦测: 比较2帧前后的变化,变化大了,就开始录屏
camid=$1
res=$2 //桌面的分辨率
seg_size=4
seg_list=22500
hls_dir=/opt/hls/${camid}MD
if ! sudo test -d $hls_dir ; then mkdir -m 777 $hls_dir; fi
if [ -f /home/gg/conf/ird_hires ]; then
scale=1
rate=10
else
scale=0.5
rate=5
fi
exec nice -n 10 /usr/bin/ffmpeg -y -f x11grab -s "$res" -r $rate -loglevel quiet -i :0.0 -vcodec libx264 -preset ultrafast -vf "scale=iw*$scale:ih*$scale,select=gt(scene\,0.003),setpts=N/($rate*TB)" -g $gop -f hls -start_number 0 -hls_flags append_list -hls_time $seg_size -hls_list_size $seg_list -an -use_localtime 1 -hls_segment_filename "$hls_dir/%s000.ts" $hls_dir/index.m3u8 >/dev/null 2>&1
录屏远程看直播有个奇怪的问题,就是当前有人在操作桌面,看直播就是无限的增加,只有桌面进去,停止录屏的进程,离开在启动。这样的 解决方案。
三、本地页面web后端
盒子本地后端采用nginx+fastcgi方式,提供cgi接口给前端调用:
需要安装的软件有:nginx、fcgiwrap、spawn-fcgi和haserl
1. nginx作为web 服务器,主要是修改其配置⽂件,以⽀持⽤户认证与cgi脚本的执
⾏。如以下配置:
前端页面获取信息需要访问后端cgi脚本,cgi的脚本访问需要认证
location /web/cgi-bin {
auth_request /auth;
}
auth.cgi来进⾏认证检查,如果认证通过则可以继续访问,否则
跳转到login
location /auth {
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME $document_root/auth/auth.cgi;
include fastcgi_params;
# error_page 403 =200 /login;
}
login通过执⾏auth_fail.cgi返回信息到前端,前端弹出登陆⻚。
error_page 403 =200 /login;
location /login {
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME $document_root/auth/auth_fail.cgi;
include fastcgi_params;
# proxy_pass http://127.0.0.1:80/trylogin.html;
# proxy_set_header X-Target $request_uri;
}
登陆⻚检查登陆信息是否正确,并记录状态。
location /login.cgi {
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
认证成功的话则可以访问cgi脚本, cgi脚本的执⾏,通过传递脚本名称以及参数到fcgiwrap,由fcgiwrap来执⾏真正的脚本。脚本的执⾏由haserl解释并返回html⽂档。
location /web/cgi-bin/ {
auth_request /auth;
#fastcgi_pass 127.0.0.1:12345;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
# fastcgi_index /web/cgi-bin;
# fastcgi_split_path_info (/web/cgibin)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# fastcgi_param SCRIPT_FILENAME /ap_www/web/cgi-bin/sys-info.cgi;
include fastcgi_params;
}
}
2.fcgiwrap、 spawn-fcgi
/etc/init.d/fcgiwrap 脚本负责该服务的启动。该脚本中指定的unix socket或端⼝号要与nginx中匹配
3, haserl
cgi
脚本如以下形式。
#!/usr/bin/haserl --shell=/bin/bash
content-type: application/json //正常的返回json
content-type: application/vnd.apple.mpegurl // 这个头是返回视频ts文件
<%
Shell scripts
%>
注意点: fcgi里的shell script不能阻塞,它以所有命令全部执行完后,才会echo输出。
cgi接口就是通过输入输出方式传递消息
或者就是使用nohup xxxxx & 放在后台执行去。
由于当时没有很多接口,后来由于cgi使用的单线程问题,接口都是代理文件的方式给出去。
所以说使用cgi刚开始就要配置多进程的方式。我因为是所有数据都是存文件的方式,没有使用数据库,如果再使用多进程,数据就会乱掉。。。。。
3.扫描局域网摄像机
因为相机上的onvif协议默认是关闭的。所以使用onvif协议去扫描相机是不能够实现的。之前做法是IPC的厂商的相机,默认是打开的,使用gsoap的框架扫描的,但是海康等都是关闭的,并且gsoap的框架太重。
所以决定使用相机的私有协议去发现它。
基本方法就是 :使用厂商的工具去发现,通过wireshark抓包分析。
海康的网上搜了下别人发现的海康的私有协议:https://blog.csdn.net/haoyitech/article/details/79552854
扫描程序是C语言编写:
sudo apt install -y -q libnet1 libnet的安装
gcc -lnet 编译加-lnet
使用了libnet库,libnet是一个raw socket的包,是二层的,可以构造任何的pkt来发送,不通过内核协议栈,加上dhcp+nat后经常出现奇怪的问题,发现摄像机需要的多播和广播包无法发送出去,所以只有用libnet来直接发送构造包发送。
还有就是所在的路由器和交换机会不会转发数据包。。。。
4. supervisord
supervisord进程管理方式使用注意点:
a. 管理的进程里的所需要的环境变量如HOME. 需要再其配置文件里添加下,supervisor没有继承系统的环境变量。实列如下:
environment=DISPLAY=":0",HOME=/home/xxx。 多个环境变量用逗号隔开。
四、获取局域网中的摄像头的配置以及配置摄像头的配置
之前2款相机,一个是海康和IPC的,IPC的根据http接口,海康则是调用海康的sdk,动态库,但是由于也是太重,就用python 爬页面方式获取和配置的。
四、常用命令
ffmpeg 从MP4、ts的文件中取出一帧
ffmpeg -y -loglevel quiet -i video.ts -vframes 1 -f image2 1.png
ffmpeg -y -loglevel quiet -i 1636020194752.ts -vframes 1 -s 640x480 -ss 2 -f image2 gao1.png
-ss 2 从第2秒取出一帧
-s 640x480 取出的图片是要640x48p
因为摄像机一般码流只能拉2路,盒子这拉一路,如果客户的店里的NVR再拉一路,截图就失败了,所以截图从最近的ts文件里获取。
五、ubunut系统常用配置信息获取
1.获取显示器的分辨率:sudo su - pi -c 'DISPLAY=:0.0 xdpyinfo' | awk '/dimensions/{print $2}'
2. 设置1080p的分辨率
3.获取显示器的厂商 :sudo grep 'vendor' /home/user/.local/share/xorg/Xorg.0.log |tail -n1 | awk -F \\\" '{print $2}'
4.调节ubuntu18.04.3的系统音量:
5.ubunutu18.04.3的系统声音打开和静音,需要循环,可能有多块声卡,比如外挂的蓝牙音箱等
6. 设置时区:sudo timedatectl set-timezone "$continent/$city"
六、红外测温--热成像仪(获取温度和红外图片)
我们使用的热成像仪是艾睿的产品,有网络热像仪和usb接口的热成像仪2种
我们提供2套接口:
1.http的接口,获取热力图图片 http jpg url: http://127.0.0.1:8008/video/infrared.jpg
2.tcp端口,用于获取温度: 127.0.0.1:8009
tcp socket 的数据包协议:
固定头(5字节)| 温度长度(4字节)|温度数据|时间戳
+TEMP DataLen Data Time
输出温度的是(288行,384列)的数组,数组的值是该像素对应的温度值(两个字节,单位开尔文),转换公式为,摄氏度=(开尔文+25000)/100 - 273.2。( 因为红外图像就是288x384的大小)
A: 网络热像仪(LT系列)
1. 首先就是根据私有协议,找到红外的设备(多播**)
2. 初始化2个scoket, 一个用于提供图片的,一个是用于提供温度的
3.处理网络IO数据
B. USB的热成像仪(at系列)
usb的,网络推送部分差不多,区别就是获取图片和温度数据,因为是usb的,所以需要用到v4l2的视频获取框架
https://www.linuxtv.org/downloads/v4l-dvb-apis-old/capture-example.html 参照官方的example https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/capture.c.html https://linuxtv.org/docs.php https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/vidioc-enum-fmt.html#c.v4l2_fmtdesc
https://www.kernel.org/doc/html/v4.9/media/intro.html
https://github.com/gjasny/v4l-utils/blob/master/utils/v4l2-ctl/v4l2-ctl.cpp v4l2的源码。
https://github.com/jacksonliam/mjpg-streamer 涉及到v4l2的框架使用,源码值得学习研究
atd的改动,是看v4l2-ctl的源码,看它是怎么获取Media Driver Info.。(因为母机的镜像从ubuntu18.04更新到20,底层驱动变化了)
v4l2的基本流程:
打开设备-> 检查和设置设备属性-> 设置采集数据格式-> 设置一种输入输出方法(缓冲 区管理)(申请内核缓冲区队列)-->把内核的缓冲区队列映射到用户空间-> 循环采集数据-> 关闭设备。
创建一个线程在loop, 执行函数指针
整个流程基本是参考官方的demo来操作的(https://www.linuxtv.org/downloads/v4l-dvb-apis-old/capture-example.html )
intel盒子上用到的系统命令:
sudo apt-cache search libopencv-highgui 查找库的当前版本
echo "$USER ALL=(ALL:ALL)NOPASSWD:ALL" |sudo tee /etc/sudoers.d/$USER 当前用户获取sudo 权限,不需要输入密码
sudo timedatectl set-timezone Asia/Shanghai 设置时区
echo superadmin:qN6RVzwqqwv | sudo chpasswd 修改superadmin用户的密码
sudo adduser --system --shell /bin/bash --group superadmin 修改用户权限组 sudo usermod -aG sudo superadmin sudo usermod -aG adm superadmin
! dpkg -s openssh-server | grep Status: | grep -i installed && sudo apt install -y -q openssh-server 判断软件是否安装
if ! sudo iptables -t filter -C INPUT -p tcp --dport 22 -j ACCEPT ; then
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo service netfilter-persistent save 保存规则
fi 打开22端口
sudo mii-tool eth0 查看网口eth0是否插了网线
echo "@reboot cue /home/name/on_boot.sh" |sudo tee /etc/cron.d/sh1 添加定时crontab定时任务执行
echo "*/10 * * * * cue /home/name/on_boot.sh" |sudo tee /etc/cron.d/sh1
sudo systemctl restart cron.service
sudo dpkg -i xxx.deb
sudo dpkg -P xxx 删除 & 配置
sudo sysctl -q -w net.core.wmem_max=851968 修改tcp的发送缓冲区大小为8511968
sudo sed -i -e 's/User=www-data/User=cue/' -e 's/Group=www-data/Group=cue/' -e 's/\[Service\]/[Service]\nRestart=always/' $FCGI_CFG 修改fcgi使用cue用户启动
sudo systemctl daemon-reload
sudo /etc/init.d/fcgiwrap restart
遇到问题:
红外测温一体机,盒子系统从ubuntu18.04--->20.04。配合飞利浦电视使用,一起断电和上电,ubuntu系统没有声音,声卡状态正常
解决措施:
1. sudo apt install 5.10.0-1057-oem 降低内核版本 到5.10
2. 需要停止录屏进程。强制驱动重新检测声卡
停录屏进程
sleep 5 这时间需要长点,进程停了,但是声卡可能还没有完全释放
sudo -H -u pi bash -c "export DISPLAY=0:0 && xset dmps force off"
sync && sleep 2
sudo -H -u pi bash -c "export DISPLAY=0:0 && xset dmps force on"
起录屏进程
echo off |sudo tee /sys/class/drm/card*/status
sync
sleep 2
echo on |sudo tee /sys/class/drm/card*/status 但是这种方式,黑屏的时间要12s左右
恢复脚本:是放在系统桌面起来后,自动执行
继续更新。。。。。。