本帖最后由 lione95678 于 2021-5-14 11:23 编辑
说一下写这个帖子的原因,因为本人小白,对大侠们写的截图、微信推送视频等帖子,只能按图索骥,不知道为什么这么写流程,造成很多困扰。所以针对论坛里neroxps的帖子“[教程系列] 【Node-red】大门情况GIF动图推送微信”,来写一个解读,希望一些和我一样什么都不懂的小白看了以后对node-red的流和节点的用法有一些了解。
大侠们看到后,可哈哈一笑后离开,也可以帮忙看看后提点建议,并就后面提到的一些问题帮忙给个解惑。谢谢了
正文: 流程照片(我把这个分成3块,3块的功能如图): 在这里,我修改了一下,然后按照需求进行分段说明 我的流程图:1、按需截取avi文件并保存,转存为gif文件 首先说明一下,为什么新增了一个“simpletime”节点。原作者neroxps为了获取当前时间,写了很多行代码,搞得我这个小白头大。关键一点,以前我为了给多次延时抓拍的图片设置为抓拍时间为文件名的操作,结果发现所有文件名都是一个时间的,(比如设置每延时10秒抓拍一次,结果发现只得到2个文件,因为有几个文件重名了,覆盖了前面的文件)即前一个设备触发的时间,而不是延时后的时间(大概是我不懂怎么设置吧),后来发现“simpletime”节点可以,所以以后就改用这个节点了。 1、手动触发这个节点就不说了,看一下“simpletime”节点的设置,如图: 这里,我只勾选了这些,因为我需要的文件名:2021年3月3日15点22分31秒.avi,这样取得了勾选的数据后配合后面的函数节点就可以得到这样的文件名。 2、第1个“function”函数节点,即图上的“截图设置”节点。Word下看代码不舒服,你可以把代码复制下来,用Visual Studio Code软件打开查看比较方便。代码如下:
msg.day = msg.myyear+'年'+msg.mymonthn+'月'+msg.mydom+'日' msg.time = msg.myhour+'点'+msg.myminute+'分'+msg.mysecond+'秒' msg.avi_path='/data/www/萤石过道/avi/' msg.gif_path='/data/www/萤石过道/gif/' msg.ffmpeg = {} msg.ffmpeg.rtsp = 'rtsp://**:**@IP:554/h264/ch1/main/av_stream' msg.ffmpeg.extra_arguments = '-max_muxing_queue_size 9999' msg.number = 10; return msg;
解释: 第一行,设置一个msg.day,他的值是前面获取的日期信息加上年月日,这样格式就变成了2011年10月10日这样的; 第二行,设置一个msg.time,他的值是前面获取的时间信息加上点分秒,这样格式就变成了10点15分20秒这样的; 第三行,设置了一个msg.avi_path,它的值就是你要保存avi文件的目录路径; 第四行,设置了一个msg.gif_path,它的值就是你要保存gif文件的目录路径; 第五行,设置了一个msg.ffmpeg,他的值包含了msg.ffmpeg.rtsp和msg.ffmpeg.extra_arguments的值 第六行,设置了一个msg.ffmpeg.rtsp,他的值就是你摄像头rtsp流的地址,如果是萤石的话,就是rtsp://摄像头用户名(默认admin):摄像头密码(摄像头上找)@摄像头IP地址:摄像头端口(默认554)/h264/ch1/main/av_stream 第七行,设置了一个msg.ffmpeg.extra_arguments,作用是在运行ffmpeg时给他一个参数,让他增加一个缓存,这个可以无脑照抄 第八行,设置一个msg.number,作用是在运行ffmpeg时给他一个参数,控制它截取多长时间的视频流,这里设置的是10秒,可以按照需要修改。 3、第2个“function”函数节点,即图上的“执行命令”节点。代码如下:
msg.payload = `/usr/bin/ffmpeg -rtsp_transport tcp -i ${msg.ffmpeg.rtsp} ${msg.ffmpeg.extra_arguments} -t ${msg.number} ${msg.avi_path}${msg.day}${msg.time}.avi > /dev/null && /usr/bin/ffmpeg -i ${msg.avi_path}${msg.day}${msg.time}.avi ${msg.gif_path}${msg.day}${msg.time}.gif > /dev/null` return msg;
这个节点中,return msg;就不说了,实际上就是第一行代码要说明的,这行代码实际上就是设置了一个msg.payload,他的值就是一个linux的命令,实际上这是2条命令合并起来的,当中用了&&来分隔,&&在linux的命令中,就是顺序执行各条命令,只有当前一个执行成功时候,才执行后面的。这两个命令的含义就是第一个命令是让ffmpeg来截取rtsp视频流后储存为avi文件,第二个命令就是把avi文件转为gif文件。原作者neroxps后面还有第三条命令,这个命令的作用就是把avi文件给删除掉。因为他是把avi文件作为临时文件来使用的,如果你也需要,只需要在我的第一条代码后面的最后一个’(英文的冒号)前,加入这些下面引号里面的代码就可以,注意&&前面有一个英文空格。
“ && rm -f ${msg.avi_path}${msg.day}${msg.time}.avi”
在这行代码中,所有的${msg.**}实际上都是上一个节点中传送下来的信息。实际上这行代码很简单,把${msg.**}用(中文代替),=后面就是这样的,`/usr/bin/ffmpeg -rtsp_transport tcp -i (rtsp流视频地址) (ffmpeg的缓存参数) -t (ffmpeg截取的视频时间长) (avi文件目录)(avi文件名,用当前日期代替)(avi文件名,用时间名代替).avi > /dev/null && /usr/bin/ffmpeg -i (avi文件目录)(avi文件名,用当前日期代替)(avi文件名,用时间名代替).avi (gif文件目录)(gif文件名,用当前日期代替)(gif文件名,用时间名代替).gif > /dev/null`
这就是一个ffmpeg截取视频流并保存,以及转换格式的命令。这个命令的用法就不多说了,可以有很多的参数,要自己上网查了。
另外说明一下2点,一是docker方式安装的node-red中ffmpeg的安装,二是目录的问题。
node-red中ffmpeg的安装 首先,你需要一个在node-red中使用的ffmpeg软件,因为本人是使用unraid系统,docke方式安装的node-red,所以说一下这种安装方式,如果你的docker镜像自带ffmpeg,可以取消这一步: 在unraid中,进入控制台,其他linux的操作系统应该也一样,就是用命令行方式。进行以下操作: 1、进入node-red容器内部 1)运行命令 docker ps ,找到docker id,如c6916a10db1e 2)运行命令,进入docker内部: docker exec -it nodered bash 这里,将nodered用docker的id代替,如下: docker exec -it c6916a10db1e bash 3)运行命令,安装ffmpeg: apk add ffmpeg 注意,如果出现以下错误,说明权限有问题 ERROR: Unable to lock database: Permission denied ERROR: Failed to open apk database: Permission denied 办法:输入exit退出容器 然后输入sudo docker exec -ti -u root nodered /bin/bash(nodered修改为容器id) 再输入apk add ffmpeg即可 安装完成后,你可以在容器内部运行命令,查看ffmpeg有了没有,命令为: ls /usr/bin/ 如果里面有ffmpeg这个文件,那么就ok了。
目录的问题 因为我是unraid系统安装的docker的node-red,安装时将unraid的/mnt/user/appdata/nodered目录映射给了node-red的/data目录,所以上面提到的/data/www/萤石过道/avi目录实际上就是unraid的/mnt/user/appdata/nodered/www/萤石过道/avi目录。我不知道除了安装的时候进行映射以外,还有什么方式可以让node-red读取宿主机的目录吗?用过在unraid下软链接的方式,但实际上这种操作是错误的。有懂的朋友指点一下。
另外,这些目录我是需要先新建好的,node-red可以创建文件,但无法创建目录,应该是权限的问题。一开始用原作者neroxps的流程来试用,这个问题差点把我搞死,谁让我是小白呢。 如果你能搞定目录的权限问题,也可以和原作者neroxps一样,把获得的当前日期作为文件夹,把获得的当前时间作为文件名。 后面2步应该是来按照原作者neroxps的流程,讲一下微信推送和定时删除文件的,有点懒了,等以后写好了直接在这个帖子后面加上word附件吧。
按照每个人的使用习惯,这种可以截取视频后保存,可以直接拍照后保存(萤石等使用萤石云api,有节点的)。保存后的文件可以用图片方式、视频方式用企业微信发送(可以用临时素材的方式,也可以像原作者一样发送网址),方法多多,群里的大侠都有帖子和流程附件。
上传2个word附件,一个是本篇的内容,一个是原先写的针对neroxps的“[教程系列] 【Node-red】大门情况GIF动图推送微信”帖子(这个帖子也是只写了截取视频的那一部分,只是写了以后觉得太繁琐,自己都看不明白了,所以就不贴出来了) 但愿后面还有兴趣写下去。
流程备份
[{"id":"404fa878.1eec78","type":"inject","z":"3272a3df.4a49bc","name":"手动触发","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{}","payloadType":"json","x":520,"y":1600,"wires":[["56cf2802.893c28"]]},{"id":"e0a50037.b2544","type":"function","z":"3272a3df.4a49bc","name":"截图设置","func":"msg.day = msg.myyear+'年'+msg.mymonthn+'月'+msg.mydom+'日'\n//设置一个msg.day,他的值是前面获取的日期信息加上年月日,这样格式就变成了2011年10月10日这样的\nmsg.time = msg.myhour+'点'+msg.myminute+'分'+msg.mysecond+'秒'\n//设置一个msg.time,他的值是前面获取的时间信息加上点分秒,这样格式就变成了10点15分20秒这样的;\nmsg.avi_path='/data/www/萤石过道/avi/'\n//设置了一个msg.avi_path,它的值就是你要保存avi文件的目录路径;\nmsg.gif_path='/data/www/萤石过道/gif/'\n//设置了一个msg.gif_path,它的值就是你要保存gif文件的目录路径\nmsg.ffmpeg = {}\n//设置了一个msg.ffmpeg,他的值包含了msg.ffmpeg.rtsp和msg.ffmpeg.extra_arguments的值\nmsg.ffmpeg.rtsp = 'rtsp://**:**@IP:554/h264/ch1/main/av_stream'\n//设置了一个msg.ffmpeg.rtsp,他的值就是你摄像头rtsp流的地址,如果是萤石的话,就是rtsp://摄像头用户名(默认admin):摄像头密码(摄像头上找)@摄像头IP地址:摄像头端口(默认554)/h264/ch1/main/av_stream\nmsg.ffmpeg.extra_arguments = '-max_muxing_queue_size 9999'\n//设置了一个msg.ffmpeg.extra_arguments,作用是在运行ffmpeg时给他一个参数,让他增加一个缓存,这个可以无脑照抄\nmsg.number = 10;\n//设置一个msg.number,作用是在运行ffmpeg时给他一个参数,控制它截取多长时间的视频流,这里设置的是10秒,可以按照需要修改\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":500,"y":1700,"wires":[["4ecaf9dc.f138a8"]]},{"id":"4ecaf9dc.f138a8","type":"function","z":"3272a3df.4a49bc","name":"执行命令","func":"msg.payload = `/usr/bin/ffmpeg -rtsp_transport tcp -i ${msg.ffmpeg.rtsp} ${msg.ffmpeg.extra_arguments} -t ${msg.number} ${msg.avi_path}${msg.day}${msg.time}.avi > /dev/null && /usr/bin/ffmpeg -i ${msg.avi_path}${msg.day}${msg.time}.avi ${msg.gif_path}${msg.day}${msg.time}.gif > /dev/null`\nreturn msg;\n//第一行代码实际上就是设置了一个msg.payload,他的值就是一个linux的命令,实际上这是2条命令合并起来的,当中用了&&来分隔,&&在linux的命令中,就是顺序执行各条命令,只有当前一个执行成功时候,才执行后面的。这两个命令的含义就是第一个命令是让ffmpeg来截取rtsp视频流后储存为avi文件,第二个命令就是把avi文件转为gif文件。\n//在这行代码中,所有的${msg.**}实际上都是上一个节点中传送下来的信息。实际上这行代码很简单,把${msg.**}用(中文代替),=后面就是这样的,`/usr/bin/ffmpeg -rtsp_transport tcp -i (rtsp流视频地址) (ffmpeg的缓存参数) -t (ffmpeg截取的视频时间长) (avi文件目录)(avi文件名,用当前日期代替)(avi文件名,用时间名代替).avi > /dev/null && /usr/bin/ffmpeg -i (avi文件目录)(avi文件名,用当前日期代替)(avi文件名,用时间名代替).avi (gif文件目录)(gif文件名,用当前日期代替)(gif文件名,用时间名代替).gif > /dev/null`\n//这就是一个ffmpeg截取视频流并保存,以及转换格式的命令。这个命令的用法就不多说了,可以有很多的参数,要自己上网查了。\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":740,"y":1620,"wires":[["18f5ff6e.1bad41"]]},{"id":"18f5ff6e.1bad41","type":"exec","z":"3272a3df.4a49bc","command":"","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":750,"y":1680,"wires":[["7a1f1868.d1b0f8"],[],[]]},{"id":"56cf2802.893c28","type":"simpletime","z":"3272a3df.4a49bc","name":"","mydate":false,"myymd":false,"myyear":true,"mymonth":false,"mymonthn":true,"mydom":true,"mydoy":false,"myday":false,"myhourpm":false,"myhour":true,"mytime":false,"mytimes":false,"myminute":true,"myminutes":false,"mysecond":true,"mymillis":false,"myepoch":false,"myrawdate":false,"mypm":false,"x":490,"y":1660,"wires":[["e0a50037.b2544"]]},{"id":"7a1f1868.d1b0f8","type":"debug","z":"3272a3df.4a49bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":730,"y":1740,"wires":[]}]
|