#!/usr/bin/env python3 """MJPEG-Stream auslesen. Beispiele: python3 webcam.py # Verbindung testen, Frame-Infos ausgeben python3 webcam.py --snapshot bild.jpg # ein Einzelbild speichern python3 webcam.py --save frames/ -n 50 # 50 Frames als JPEG speichern python3 webcam.py --show # Live-Fenster (benötigt opencv-python + numpy) """ import argparse import os import sys import time import requests URL = "http://192.168.10.82:8080/stream.mjpg" SOI, EOI = b"\xff\xd8", b"\xff\xd9" def frames(url, timeout=10): """Generator: liefert jedes JPEG-Frame des MJPEG-Streams als bytes.""" with requests.get(url, stream=True, timeout=timeout) as r: r.raise_for_status() buf = b"" for chunk in r.iter_content(chunk_size=4096): buf += chunk while True: start = buf.find(SOI) if start < 0: buf = b"" break end = buf.find(EOI, start + 2) if end < 0: buf = buf[start:] break yield buf[start:end + 2] buf = buf[end + 2:] def main(): p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) p.add_argument("--url", default=URL) p.add_argument("--snapshot", metavar="DATEI", help="ein Frame speichern und beenden") p.add_argument("--save", metavar="ORDNER", help="Frames in Ordner speichern") p.add_argument("-n", type=int, default=0, help="nach N Frames beenden (0 = endlos)") p.add_argument("--show", action="store_true", help="Live-Fenster anzeigen (OpenCV)") a = p.parse_args() if a.show: import cv2 import numpy as np if a.save: os.makedirs(a.save, exist_ok=True) count, t0 = 0, time.time() try: for jpg in frames(a.url): count += 1 if a.snapshot: with open(a.snapshot, "wb") as f: f.write(jpg) print(f"Gespeichert: {a.snapshot} ({len(jpg)} Bytes)") return if a.save: with open(os.path.join(a.save, f"frame_{count:06d}.jpg"), "wb") as f: f.write(jpg) if a.show: img = cv2.imdecode(np.frombuffer(jpg, np.uint8), cv2.IMREAD_COLOR) cv2.imshow("Webcam", img) if cv2.waitKey(1) & 0xFF in (ord("q"), 27): break fps = count / (time.time() - t0) print(f"\rFrame {count} {len(jpg)} Bytes {fps:.1f} fps", end="", flush=True) if a.n and count >= a.n: break except KeyboardInterrupt: pass except requests.RequestException as e: sys.exit(f"Verbindungsfehler: {e}") print() if __name__ == "__main__": main()