GithubHelp home page GithubHelp logo

ethercatduino / cctvagent Goto Github PK

View Code? Open in Web Editor NEW

This project forked from jaofeng/cctvagent

0.0 0.0 0.0 98 KB

接收 RTSP 串流, 並在用戶端以 HTTP 播放的解決方案

License: MIT License

Python 90.29% CSS 1.56% HTML 0.69% JavaScript 7.46%

cctvagent's Introduction

RTSP Over HTTP Solution

前言

因工作上的需要,需要將 IP Cam 即時影像顯示在終端設備上,作為監控螢幕使用。

一般的作法是直接利用 NVR 廠商提供的 SDK/Player 進行顯示播放,但廠商提供的 SDK/Player 是 Windows base 的,而終端設備卻是 Linux 且 GUI 為 Web base,不得不自行從 IP Cam 接取 RTSP 影像串流。

雖然網路上有很多資源可以幾乎不花心力就可以做到所需功能,但還是想研究一下何謂 SSPDONVIFRTSPStreaming 等等相關知識,所以才會有這個專案。

本人非影像專業工程師,如有謬論或錯誤,懇請各位先進不吝告知

第三方模組

  • WebSocket 使用 websocket_server
    pip install git+https://github.com/Pithikos/python-websocket-server
  • WS-Discovery 使用 wsdiscovery
    pip install WSDiscovery
  • ONVIF 相關功能使用 python-onvif
    pip install onvif-py3
  • RTSP 串流擷取使用 OpenCV
    pip install opencv-python

專案目錄結構

. 
├─ cctv
│  ├─ __init__.py
│  ├─ agent.py
│  ├─ onvifAgent.py
│  └─ rtspProxy.py
├─ jfNet
│  ├─ __init__.py
│  ├─ CastReceiver.py
│  ├─ CastSender.py
│  ├─ SSDP.py
│  ├─ TcpClient.py
│  └─ TcpServer.py
├─ www
│  ├─ css
│  │  ├─ base.css
│  │  └─ index.css
│  ├─ js
│  │  ├─ index.js
│  │  ├─ jquery.min.js
│  │  ├─ rtspProxy.js
│  │  ├─ rtspProxy.min.js
│  │  └─ index.css
│  └─ index.html
├─ cctvAgent.py
└─ webSvc.py

檔案說明

  • cctv 目錄是本專案主要模組,其中包含:
    • agent.py
      負責處理 IP Cam 探索,使用 UPnP/SSDPWS-Discovery 兩種技術,如果不需要主動搜尋 IP Cam,可不使用此模組
    • onvifAgent.py
      ONVIF 協定相關資料取得,譬如 IP Cam 的 Profile串流網址解析度編碼模式
    • rtspProxy.py
      使用 OpenCV 讀取 RTSP 串流,再以 WebSocketMotion JPEG(M-Jpeg) over HTTP 串流輸出
  • www 是 HTML 網頁目錄
  • cctvAgent.py
    程式進入點,執行後可使用 help 檢視可使用的指令
  • webSvc.py
    繼承自 BaseHTTPRequestHandler 的 HTTP Web Server 模組
  • jfNet 模組是本人另一專案, 請參閱 SocketTest

原理說明

RTSP over HTTP 的原理其實很簡單:

當終端要求取得影像時,讀取當下的影像(影格)並轉換成圖檔傳送終端

rtspProxy.py 使用 OpenCVRTSP 來源拉流(讀取當下影像),再將讀取的影像經壓縮或調整後,使用 WebSocket 或原來的 HTTP GET Connection 送至終端瀏覽器,再經由 HTML img tag 顯示

以下將以三部分說明:

影像擷取

  1. 使用 OpenCVVideoCapture() 函式開啟 RTSP 串流
  2. 依參數進行解析度調整、圖像品質以 OpenCV 進行壓縮、放大

WebSocket 傳輸方式

  1. 使用 python-websocket-server 作為 WebSocket 伺服器

  2. 終端使用 rtstProxy(.min).js 連線至伺服器,連線後,發送請求資料給伺服器

  3. 伺服器在接取終端連線,並取得請求的資料後,開始使用 OpenCV 自以 VideoCapture() 函式所建立的 camera 物件中讀取影像(影格)

  4. 取得影格後,調整解析度、品質後,再轉換成 JPEG 圖檔內容

  5. 將 JPEG 圖檔內容轉換成 Base64 字串(Bytes to Base64,原始大小如 30KBytes,會擴張成 40KBytes,請參閱維基百科)

  6. 32KBytes 為一單位,切割字串內容

  7. 傳送給 請求同一個 RTSP 的終端 JavaScript

  8. 各終端的 JavaScript 組合這些字串內容後,直接指給 img.src

    開發過程中發現傳輸時,常常因為網路品質不佳等原因,容易產生終端(JavaScript WebSocket)解析封包長度錯誤,而造成畫面無法顯示、卡頓、斷線等狀況。

    目前暫未研究的錯誤發生原因是因為 python-websocket-server 的問題,還是其他問題,所以目前的暫時的解法是: 傳給使用者前,先把 Base64 字串以 32KBytes 為單位進行切割,到 JavaScript 後,再將之組合,最後指給 img.src 顯示

M-JPEG 傳輸方式

  1. 伺服器取得終端的 img.src HTTP GET 請求後,先於 HTTP Header 中回應 Content-Type: multipart/x-mixed-replace;boundary={自訂字串}
  2. 再自 camera 取得影格,並依傳入的 URL 參數,調整解析度、品質後,再轉換成 JPEG 圖檔內容
  3. HTTP Header 加上 Content-Type: image/jpegContent-Lengthboundary 後,直接將 JPEG 圖像內容以 Bytes 方式傳送至終端
  4. 瀏覽器會自動以 boundary 拆解圖像內容後餵給 img

使用說明

  • IP Cam 的 IP 位址與 Profile ID,請於 cctvAgent.pyindex.js 中設定,或請自行修改成讀取參數檔的方式載入
  • 使用 WebSocket 傳輸串流時,需搭配 rtspProxy(.min).js 使用
  • 如需將 WebSocket 串流方式提供給非本機連線,請自行將 index.js 內的 cctv.ProxyHost 修改成本機 IP
  • rtspProxy(.min).js 與 M-Jpeg 的使用方式,請參閱 index.js 內的 useRtspProxy()useHttpMJpegPuller() 兩函式
  • 終端顯示順暢與否、是否會延遲,取決於原始 RTSP 串流解析度、網路品質、終端顯示解析度等等
  • 經在同一封閉網路的不負責實測:satisfied:,對終端設備負載較輕的方式是 M-Jpeg
    • 測試環境設備:
      • Server : MacBook Pro 13" / Mojave 10.14.5
      • Client : tBOX810-838-FL / Debian 10, Kernel 14.2
    • 測試方式:
      • 終端同時開 4 分割畫面,對伺服器請求同一個 IP Cam 影像
    • 測試結果:
      • 以終端顯示的 CPU Usage 而言,WebSocket 高於 M-Jpeg 約 1.2 倍
      • 以記憶體用量而言,兩者差不多
      • 以網路流量而言,WebSocket 高於 M-Jpeg 約 1.4 倍

參考資料

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.