草庐IT

Jetson Xavier NX 配置(七)—— 数据传输之socket文件传输 & usb摄像头RTSP视频推流

益生珺珺 2023-04-05 原文

目录

1、Python socket 文件传输

(1)发送单个文件(一次性)

(2)发送一个文件夹下的所有文件(一次性)

(3)发送每个文件夹下的最新文件(等时间间隔持续发送)

2、usb摄像头RTSP视频推流

(1)下载与配置

(2)使用


1、Python socket 文件传输

简介:python的socket库提供了基于TCP/IP协议的数据传输功能,相当于服务器端开了一个通道listen着,等待一台客户端connect,成功建立连接后,通过send和recv的发送和应答来实现数据传输
需要:同一内网下两台设备的ip地址(在cmd中,windows通过ipconfig命令查看,ubuntu通过ifconfig查看)

(1)发送单个文件(一次性)

参考博客:https://blog.csdn.net/m0_55415810/article/details/1214 p54582

(2)发送一个文件夹下的所有文件(一次性)

参考博客:python socket通信传输某文件夹下的所有图片_不告诉你/tp的博客-CSDN博客

这段代码我在运行试用的时候有出现报错。

一开始send一长串十六进制字符串,相当于是在对暗号,对上暗号了服务器才确认发送数据。但是我这里收发都报错,原代码 s.send("\xAA\x96\xAC\x00\x01\x00\x01\x69")  报错 TypeError: a bytes-like object is required, not 'str' ,改成了 s.send(b'\xAA\x96\xAC\x00\x01\x00\x01\x69') ;原代码 if(rev_str[6] == b"\x01") 的判断报错,应该是进制的问题,我改成了 if(str(rev_str[6]) == “1”) 用十进制判断就可以了

另外前面的send和recv,收发的是文件长度等信息,需要encode和decode成utf-8格式,否则也报错TypeError: a bytes-like object is required, not 'str'

(3)发送每个文件夹下的最新文件(等时间间隔持续发送)

前情提要:应用场景是有N个摄像头,对应N个文件夹,定时更新摄像头的最新抓拍截图,需要将最新的图像传输给其他客户端。

基于(2)进行了一些修改,尤其要注意沾包的问题,如果存在两次连续的send,而实际想要发送的这两次是两个独立的数据文件,对于socket来说他认为两次连续发送的内容是粘连在一起发送的。因此要避免连续的send,在send中间加一句recv(),进行阻塞,多一次一问一答的确认。

上代码:

(传输的数据存放方式与命名格式如下,可根据自己的需求自行修改)

 

服务器端-发送(先启动):

import sys
import socket  
import time
import os
import re

s_server = socket.socket()
print("开始创建服务器socket")
host = ''
port = 7891  # 随意设置一个空闲的端口号(和客户端保持一致即可)
addr = (host, port)
s_server.bind(addr)  # 绑定端口
s_server.listen(5)  # 监听等待客户端的connect,没有的话就一直停留在这一步等待

# 客户端程序运行以后就成功建立了连接
to_client, addr = s_server.accept()
print ('...connected from :', addr)
rev_str = to_client.recv(1024)
print(rev_str)

# 确认过暗号,是要接受该客户端的信息
if(str(rev_str[6]) == "1"):
    start = time.time()
    while True:
        # 每隔一定时间(20s)发送一次
        if (time.time() - start) > 20:
            # 遍历文件夹下的所有文件夹
            path_folder = r"/home/ysj/parking/code/cameras/"
            dirs_folder = os.listdir(path_folder)
            print("文件夹个数")
            print(len(dirs_folder)) 
            to_client.send(str(len(dirs_folder)).encode('utf-8'))

            # 遍历文件夹
            for folder in dirs_folder:  

                # 函数阻塞,防止沾包(避免连续两个send)
                to_client.recv(8) 

                start1 = time.time()
                print("当前文件夹:%s"%folder)
                # 获取该文件夹下的所有图片文件
                path_file = path_folder + folder + "/"
                files = os.listdir(path_file)
                # 对文件夹内的图片按文件名中的序号排序,取最大的那张(最新)
                # 我的图片命名格式如:192.168.1.104_15.jpg,需要用正则表达式取出其中的序号“15”
                files.sort(key = lambda x:int(x[re.search('(?<=_)(.+?)(?=\.jpg)', x).span()[0] : re.search('(?<=_)(.+?)(?=\.jpg)', x).span()[1]]))
                # 取最后一张图片
                file_size = os.path.getsize(path_file + files[-1])
                print('即将发送的文件长度是:%d '%file_size)
                file_info='%s|%s'%(files[-1], file_size)
                to_client.send(file_info.encode('utf-8'))
                to_client.recv(6)
                # 一张图片可能要分好几批才能发送完,此处是连续send
                fout = open(path_file + files[-1], "rb")
                has_send = 0
                while has_send < file_size:
                    frame_data = fout.read(1024)
                    to_client.send(frame_data)
                    has_send+=len(frame_data)

                end1 = time.time()
                dur1 = end1 - start1
                print('time cost: %.5f sec' %dur1)
            
            start = time.time()

    # 如果要定时持续接收的话就不关闭连接了
    # print("program exit normally:-> close socket")
    # s_server.close()
    # to_client.close()

客户端-接收:

import socket               # 导入 socket 模块
import time
 
s = socket.socket()         # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 7891       # 设置端口号
 
s.connect(("192.168.1.106", port)) # 服务器的ip地址


while True:
    # 允许一轮接收发的时候才进行
    # 都要encode和decode成utf-8,否则报错无法传输str而是需要字节
    s.send(b'\xAA\x96\xAC\x00\x01\x00\x01\x69')
    # 对上暗号后,接收即将传输的文件夹下的文件个数
    file_num = s.recv(1024).decode('utf-8')
    print(file_num)
    file_num = int(file_num)

    for file_end in range(0, file_num):

        # 对应服务器端的那一句防止沾包的recv,传的内容无所谓
        s.send(str(file_num).encode('utf-8'))

        file_info = s.recv(80).decode('utf-8')
        print(file_info)
        filename,filesize=str(file_info).split('|')
        s.send(filesize.encode('utf-8'))
        filesize=int(filesize)
        # 接收文件的位置
        f_txt = open("./receive0905/"+filename, "ab")
        has_receive = 0
        while has_receive < filesize:
            picture_date = s.recv(1024)
            f_txt.write(picture_date)
            has_receive+=len(picture_date)
        # time.sleep(2)
        f_txt.close()
        print("接收了一个")
 
# s.close()

2、usb摄像头RTSP视频推流

参考博客:2.gstreamer USB摄像头RTSP推流_生如~夏花的博客-CSDN博客_gstreamer usb摄像头

(1)下载与配置

先下gst-rtsp-server,不能要最新版本的,没有autogen.sh,用旧版本

git clone  -b 1.8 https://github.com/GStreamer/gst-rtsp-server.git 

再下载common.git,粘贴到server下common文件夹下:

GitHub - GStreamer/common: 'common' shared submodule. This module is unused and deprecated.

然后就运行autogen.sh,make就好:

cd gst-rtsp-server 
./autogen.sh
sudo make

(2)使用

使用的时候进入examples文件夹
注:device=/dev/video0,此处的序号0是接入的摄像头序号,如果有多个摄像头需要修改

查看摄像头设备
sudo v4l2-ctl --list-devices
./test-launch --gst-debug-level=3 "( v4l2src device=/dev/video0 ! videoconvert ! video/x-raw, format=(string)NV12, width=640, height=480, framerate=30/1 ! queue ! x264enc bitrate=10240 !  rtph264pay name=pay0 pt=96 )"

(不记得最后成功执行的是哪一段代码了)

./test-launch  --gst-debug=3 "( v4l2src ! video/x-raw,width=640,height=480, framerate=30/1 ! omxh264enc ! h264parse ! rtph264pay name=pay0 pt=96 )"

执行后显示:stream ready at rtsp://127.0.0.1:8554/test

在同一局域网下的另一台主机上,就可以在VLC plyaer里打开网络串流,地址改成服务器的ip地址即可

或者通过opencv也可以获取

问题:当前的视频推流延迟太高了,有10s左右,还未深究

主要参考:

python socket通信传输某文件夹下的所有图片_不告诉你/tp的博客-CSDN博客
2.gstreamer USB摄像头RTSP推流_生如~夏花的博客-CSDN博客_usb摄像头rtsp推流

有关Jetson Xavier NX 配置(七)—— 数据传输之socket文件传输 & usb摄像头RTSP视频推流的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  4. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  5. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  6. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  9. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  10. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

随机推荐