2025年9月2日 星期二

Python 腳本:輸入 IP/帳密,列出所有 Profile 的 RTSP 與快照 URL

 一支可直接用的 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。

沒有留言:

張貼留言