Erster Commit: MJPEG-Relay, Stream-Tool und README
This commit is contained in:
commit
2de90feafc
5 files changed
+388
No files matched your search
@@ -0,0 +1,85 @@
|
||||
#!/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()
|
||||
Reference in new issue
Block a user