家庭监控系统实现(二) -- 树莓派定时转存文件功能及HTTP服务器准备

转载请注明出处:https://blog.csdn.net/mymottoissh/article/details/83590248

上一篇对开发需要的环境进行了准备。现在开始准备代码。前面我们说过,会在树莓派一端建立服务器,而Android会作为客户端进行连接。本篇针对的即是服务端的代码。具体来讲,服务端需要实现两个服务器,分别作为视频文件服务器和实时视频推送服务器。本篇实现的功能包括定时转存视频文件以及本地HTTP服务器的准备。

依照之前的设计思路,该服务器实现的功能是每隔3min,将采集到的视频流存储为文件。同时,该路径下启动一HTTP服务器供Android访问。那么可以这样设计,树莓派上电时,开启后台service。这个service有两个作用,一是需要实现定时转存文件功能。二是提供HTTP本地服务。考虑到后续需要实现的实时视频流的推送功能,HTTP服务至少需要提供一个GET处理方式。来确定客户端请求的是历史视频文件还是实时视频流,又或者是直接访问的文件。如果客户端请求的是历史视频文件,那么需要将所有视频文件的文件名返回给客户端供访问。如果请求的是实时视频流,则需要开启流推送。如果是直接访问的视频文件,还需要将文件传送给客户端。

为了实现上述功能,我们的main函数加载时,需要干两件事:

if __name__ == '__main__':
    #开启文件转存线程
    startRecording()
    #开启本地HTTP服务器
    server = MyVideoHttpServer.MyVideoHttpServer()
    server.setPort("127.0.0.1", 8080)
    server.setHandler(MyVideoHttpServer.MyVideoHttpHandler)
    server.start()

其实有了上一节对picamera的介绍,视频转存部分的代码,直接在例子的基础是改吧改吧就可以用了。

def getFileName():
    ts = time.localtime(time.time())
    return 'video_' + str(ts.tm_year) + '_' + str(ts.tm_mon) + '_' + str(ts.tm_mday) + '_' + str(ts.tm_hour) + '_' + str(ts.tm_min) + '_' + str(ts.tm_sec) + ".h264"

def recordFile():
    camera = picamera.PiCamera()
    camera.resolution = (640, 480)
    while True:
        camera.start_recording(getFileName())
        camera.wait_recording(180)
        camera.stop_recording()

def startRecording():
    trd = threading.Thread(target=recordFile, args=())
    trd.start()

对于HTTP的部分,直接上代码

import SocketServer
import BaseHTTPServer
import urlparse
import os
import socket
import shutil

class MyVideoHttpServer:
    handler = None
    ip = "127.0.0.1"
    port = 8080

    def setHandler(self, handler):
        self.handler = handler

    def setPort(self, addr="127.0.0.1", port=8080):
        self.ip = addr
        self.port = port

    def start(self):
        httpd = SocketServer.TCPServer(("", self.port), self.handler)
        httpd.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
        httpd.serve_forever()

class MyVideoHttpHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_GET(self):
        print "get req received"
        print self.path
        path = urlparse.urlparse(self.path).path
        query = urlparse.urlparse(self.path).query
        print query

        if len(query) == 0:
            if len(path.split(".")) > 1 and (path.split(".")[1] == "h264" or path.split(".")[1] == "mp4"):
                try:
                    file = open("." + path, 'rb')
                    self.respFileHeaders(os.path.getsize("." + path))
                    shutil.copyfileobj(file, self.wfile)
                except:
                    print "file process error"
                finally:
                    file.close()
            else:
                self.respErr()
        else:
            params = dict()
            for p in query.split("&"):
                if p.find("=") > 0:
                    params[p.split("=")[0]] = p.split("=")[1]
            showMode = params.get("showMode")
            print showMode
            #1 hist
            if showMode == "1":
                print "history file mode"
                self.sendFileList()
            #2 air
            elif showMode == "0":
                print "air mode"
                self.startRtmpServer()
            else:
                self.respErr()

    def respTextHeaders(self, contentLen):
        self.send_response(200)
        self.send_header("Content-Type", "text/plain")
        self.send_header("Content-Length", contentLen)
        self.send_header("Transfer-Encoding", "utf-8")
        self.end_headers()

    def respFileHeaders(self, contentLen):
        self.send_response(200)
        self.send_header("Content-Type", "application/octet-stream")
        self.send_header("Content-Length", contentLen)
        self.end_headers()

    def respErr(self):
        self.send_response(404)
        self.end_headers()

    def sendFileList(self):
        fileList = ""
        for root, dirs, files in os.walk(os.curdir):
            if len(files) > 0:
                for f in files:
                    if len(f.split(".")) > 0 and f.split(".")[1] == "h264":
                        fileList += f
                        fileList += " "
        self.respTextHeaders(len(fileList))
        self.wfile.write(fileList)

    def startRtmpServer(self):
        self.respTextHeaders(2)
        self.wfile.write("OK")
        os.system("gst-launch-1.0 -v v4l2src device=/dev/video0 ! 'video/x-raw, width=640, height=480, framerate=30/1' ! queue ! videoconvert ! omxh264enc ! h264parse ! flvmux ! rtmpsink location='rtmp://192.168.0.102/live live=1' &")

重点说一下handler的实现。提供了doGet方法来处理get请求。

如果url中含有showMode的查询字段,那么如果showMode等于1表示历史文件列表请求,那么会给客户端返回当前目录下所有以.mp4和.h264结尾的文件名供前端访问。

如果showMode等于0,表示请求实时数据,此时会开启GStreamer进行视频采集并发送给rtmp服务器。关于rtmp的部署会在下一节记录。

如果请求路径中含有文件名,服务端会尝试打开该文件并返回给客户端。

如果以上情况均不是,则直接返回404。

其实关于上述实现,还有一个重要的缺陷。就是经过测试picamera和GStreamer同时访问一个摄像头资源会造成错误。这个问题需要在结合具体需求来进行权衡。本次实现只针对功能,所以暂且不去考虑这个问题。默认同一时间内仅有一个功能可以使用。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
家庭视频监控系统使用说明 操作注意事项 (1)本系统默认操作员用户名为:mr,密码为:mrsoft。 (2)本系统使用的硬件是天敏VC4000监控卡,其中使用了Mix.dll和Sa7134Capture.dll两个组件,在运行程序前,需要将这些文件添加到当前工程中。程序中没有提供这些文件。 操作流程 系统主界面如图1.1所示,本视频监控系统主要实现了云台控制、快照和录像、录像回放、定时自动监控监控管理及日志。 图1.1 家庭视频监控系统主界面 云台控制 视频监控模块中,可以通过手动控制云台实现视频的聚焦、对焦、光圈和雨刷等效果,而且能够控制云台的上、下、左、右动,从而监控各个不同的方向。云台控制运行结果如图1.2所示。 图1.2 云台控制 色彩控制   视频监控模块中,当选中某个视频监控窗口时,用户可以通过“色彩控制”区域的滑动条对视频窗口进行亮度、对比度、饱和度和色度的调整。色彩控制运行结果如图1.3所示。 图1.3 色彩控制 图像抓拍及生成监控录像   视频监控模块中,用户可以通过在“快照与录像”区域单击“快照”、“录像”按钮进行图像抓拍及录像功能,其中快照主要有bmp和jpg两种格式,录像则保为avi格式。快照与录像运行结果如图1.4所示。 图1.4 图像抓拍及生成监控录像 定时录像设置   视频监控模块中,当用户在主窗体的“快照与录像”区域单击“定时录像”按钮时,弹出“定时录像设置”窗体,该窗体中,用户可以设置定时录像的频率及时刻。定时录像设置窗体运行结果如图1.5所示。 图1.5 定时录像设置 录像回放   录像回放主要用来选择播放已经录制的视频文件,录像回放窗体中,单击“回放”按钮,打开“选择视频文件”对话框,用户选择完要播放的视频文件后,单击“确定”按钮,即可观看选择的视频文件。录像回放运行结果如图1.6所示。 图1.6 录像回放 注册程序   注册程序主要实现软件的注册功能,该窗体运行时,自动获得本机机器码,然后用户手动输入注册码,单击“注册”按钮,如果注册码正确,则成功注册该软件,否则,提示注册码错误。软件注册窗体运行结果如图1.7所示。 图1.7 注册程序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值