一支可直接用的 Python 腳本:輸入 IP/帳密,列出所有 Profile 的 RTSP 與快照 URL。
依序嘗試取得 Profile S/T。無外部播放器相依,只用 ONVIF API。
安裝:
pip install onvif-zeep
腳本 onvif_get_rtsp.py
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 列出 ONVIF 裝置的 RTSP 與 Snapshot URI
import argparse, sys
from onvif import ONVIFCamera
from zeep.exceptions import Fault
def connect(ip, port, user, pwd):
try:
cam = ONVIFCamera(ip, port, user, pwd)
return cam
except Exception:
# 某些環境需手動指定 WSDL 目錄
try:
import pkg_resources
wsdl_dir = pkg_resources.resource_filename('onvif', 'wsdl')
cam = ONVIFCamera(ip, port, user, pwd, wsdl_dir=wsdl_dir)
return cam
except Exception as e:
print(f"連線失敗:{e}")
sys.exit(2)
def get_device_info(cam):
try:
dev = cam.create_devicemgmt_service()
info = dev.GetDeviceInformation()
return f"{info.Manufacturer} {info.Model} FW:{info.FirmwareVersion} SN:{info.SerialNumber}"
except Exception:
return "(無法讀取裝置資訊)"
def list_streams(cam):
media = cam.create_media_service()
try:
profiles = media.GetProfiles()
except Fault as e:
print(f"讀取 Profiles 失敗:{e}")
sys.exit(3)
results = []
for p in profiles:
token = p.token
name = getattr(p, 'Name', token)
# RTSP
rtsp = ""
try:
req = media.create_type('GetStreamUri')
req.ProfileToken = token
req.StreamSetup = {'Stream': 'RTP-Unicast', 'Transport': {'Protocol': 'RTSP'}}
rtsp = media.GetStreamUri(req).Uri or ""
except Fault:
rtsp = ""
# Snapshot(若支援)
snap = ""
try:
req2 = media.create_type('GetSnapshotUri')
req2.ProfileToken = token
snap = media.GetSnapshotUri(req2).Uri or ""
except Fault:
snap = ""
results.append((name, token, rtsp, snap))
return results
def main():
ap = argparse.ArgumentParser(description="ONVIF RTSP/Snapshot URI 列表")
ap.add_argument("--ip", required=True, help="裝置 IP")
ap.add_argument("--user", required=True, help="使用者名稱")
ap.add_argument("--pwd", required=True, help="密碼")
ap.add_argument("--port", type=int, default=80, help="ONVIF 服務埠,預設 80")
args = ap.parse_args()
cam = connect(args.ip, args.port, args.user, args.pwd)
print("裝置資訊:", get_device_info(cam))
rows = list_streams(cam)
if not rows:
print("未找到任何 Profile")
sys.exit(4)
print("\nProfiles 與串流:")
for i, (name, token, rtsp, snap) in enumerate(rows, 1):
print(f"{i:02d}. Name={name} Token={token}")
print(f" RTSP : {rtsp or '(無)'}")
print(f" Snapshot: {snap or '(無)'}")
if __name__ == "__main__":
main()
用法:
python3 onvif_get_rtsp.py --ip 192.168.1.50 --user admin --pwd 123456 --port 80
後續直接用 ffplay 監看:
ffplay -rtsp_transport tcp "rtsp://USER:PASS@IP:554/由上面取得的PATH"
註記:
-
多數 IPC 的 RTSP 埠為 554。ONVIF 回的 URI 若不含帳密,需在 URI 前段補
user:pass@
。 -
少數品牌把 ONVIF 服務放在 8899、8000 等,改
--port
。 -
若沒有 Snapshot URI,代表裝置未實作或需特定 Profile。
沒有留言:
張貼留言