2025年9月2日 星期二

ONVIF 通訊協定說明

 ONVIF 通訊協定說明

  • 定義:ONVIF (Open Network Video Interface Forum) 是一個開放標準,定義網路攝影機、NVR、VMS 之間的互通協定。

  • 目的:解決不同品牌設備之間的相容問題,讓 IPCAM、NVR、VMS 能透過統一的 SOAP / XML-based Web Services API 溝通。

  • 常見 Profile

    • Profile S:IP 攝影機基本串流(RTSP、影像、音訊、事件)。

    • Profile G:錄影、儲存與回放控制。

    • Profile T:支援 H.265/H.264 影像壓縮,含 metadata。

    • Profile M:AI / Metadata 傳輸(人臉、車牌等辨識)。


應用於串流視訊的流程

  1. 設備發現 (Device Discovery)

    • 使用 WS-Discovery (UDP multicast)。

    • 可透過 onvif 工具或 SDK 掃描區域網路上的 ONVIF 設備。

  2. 能力查詢 (GetCapabilities)

    • 確認設備支援的 Profile(S/T/G/M)。

  3. 媒體設定 (Media Service)

    • 呼叫 GetProfiles() 取得 Profile token。

    • 呼叫 GetStreamUri() 取得 RTSP URL,例如:

      rtsp://192.168.1.50:554/Streaming/Channels/101
  4. 串流播放

    • 使用 VLC、FFmpeg、GStreamer、OpenCV 直接拉 RTSP 串流。


Python 範例(使用 onvif-zeep + OpenCV)

from onvif import ONVIFCamera import cv2 # 連接攝影機 cam = ONVIFCamera('192.168.1.50', 80, 'admin', 'password') # 取得媒體服務 media = cam.create_media_service() # 取得 profiles profiles = media.GetProfiles() token = profiles[0].token # 取得 RTSP 串流 URI stream_uri = media.GetStreamUri({'StreamSetup': {'Stream': 'RTP-Unicast', 'Transport': {'Protocol': 'RTSP'}}, 'ProfileToken': token}) print("RTSP URL:", stream_uri.Uri) # 使用 OpenCV 播放串流 cap = cv2.VideoCapture(stream_uri.Uri) while True: ret, frame = cap.read() if not ret: break cv2.imshow("ONVIF Stream", frame) if cv2.waitKey(1) == 27: # ESC 退出 break cap.release() cv2.destroyAllWindows()

要不要我再給你一個 FFmpeg 或 GStreamer 指令範例,用於命令列直接串流播放/錄影?


Linux (FFmpeg ) Video Play URL

============================

以下指令可直接套用。把 USER:PASS@IP:554/PATH 換成你的攝影機 RTSP 位址。

播放(監看)

ffplay -rtsp_transport tcp -stimeout 5000000 \ "rtsp://USER:PASS@IP:554/PATH"

說明:TCP 穩定;-stimeout=5,000,000µs 逾時。

原碼錄影(不重編,最省 CPU)

# 儲存成 MKV(建議容器) ffmpeg -rtsp_transport tcp -i "rtsp://USER:PASS@IP:554/PATH" \ -c copy -map 0 -f matroska rec.mkv # 或儲存成 TS(方便切片) ffmpeg -rtsp_transport tcp -i "rtsp://USER:PASS@IP:554/PATH" \ -c copy -map 0 -f mpegts rec.ts

說明:-c copy 不轉碼;RTSP→MP4 可能索引不穩,改用 MKV/TS。

轉碼並壓到固定碼率(H.264)

ffmpeg -rtsp_transport tcp -i "rtsp://USER:PASS@IP:554/PATH" \ -c:v libx264 -preset veryfast -tune zerolatency -b:v 4M -maxrate 4M -bufsize 8M \ -c:a aac -b:a 128k -movflags +faststart out.mp4

轉 HLS(HTTP 播放)

ffmpeg -rtsp_transport tcp -i "rtsp://USER:PASS@IP:554/PATH" \ -c:v libx264 -preset veryfast -g 50 -sc_threshold 0 \ -c:a aac -b:a 128k \ -f hls -hls_time 6 -hls_list_size 10 -hls_flags delete_segments \ hls/out.m3u8

說明:-g 50≈50fps 的 1 秒 GOP;依實際 FPS 調整。

轉推 RTMP(例如 YouTube/自架 nginx-rtmp)

ffmpeg -rtsp_transport tcp -i "rtsp://USER:PASS@IP:554/PATH" \ -c:v libx264 -preset veryfast -tune zerolatency -b:v 4M -maxrate 4M -bufsize 8M \ -c:a aac -b:a 128k -f flv "rtmp://RTMP_SERVER/app/stream_key"

低延遲監看參數組

ffplay -fflags nobuffer -flags low_delay -probesize 32k -analyzeduration 0 \ -rtsp_transport tcp "rtsp://USER:PASS@IP:554/PATH"

週期性截圖

# 每 5 秒一張 ffmpeg -rtsp_transport tcp -i "rtsp://USER:PASS@IP:554/PATH" \ -vf fps=1/5 -q:v 2 shots/frame-%06d.jpg

斷線自動重連(錄影)

ffmpeg -reconnect 1 -reconnect_streamed 1 -reconnect_at_eof 1 \ -rtsp_transport tcp -i "rtsp://USER:PASS@IP:554/PATH" \ -c copy -f mpegts rec.ts

備註

  • IF-5301 多為 H.265/H.264。若拉 H.265 串流且播放器不支援,改 -c:v libx264 轉碼

  • 有聲音就保留 -c:a aac;沒麥克風可加 -an 關閉音訊。

  • ONVIF GetStreamUri() 拿到的 URL 直接套上述指令即可



沒有留言:

張貼留言