86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
#!/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()
|