From 453d9397b203fa08a90a440e63953b73a73d2b5b Mon Sep 17 00:00:00 2001 From: Tyler Romero Date: Mon, 8 Jan 2024 10:31:15 -0800 Subject: [PATCH 1/3] Allow user to manually specify stream type --- README.md | 3 ++- src/grabber.py | 17 ++++++++--------- src/stream.py | 16 +++++++++------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 6fd1437..95aa6f5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ process frames from a video file, device, or stream. ## Download -This application is easy to use on any system with Docker installed. +This application is easy to use on any system with Docker installed. ```shell $ docker pull groundlight/stream @@ -29,6 +29,7 @@ options: -f, --fps=FPS number of frames to capture per second. 0 to use maximum rate possible. [default: 5] -h, --help show this message. -s, --stream=STREAM id, filename or URL of a video stream (e.g. rtsp://host:port/script?params OR video.mp4 OR *.jpg) [default: 0] + -o, --streamtype=TYPE (optional) type of stream. One of [device, directory, rtsp, youtube, file, image_url] [default: auto-infer] -t, --token=TOKEN API token to authenticate with the Groundlight API -v, --verbose enable debug logs -w, --width=WIDTH resize images to w pixels wide (and scale height proportionately if not set explicitly) diff --git a/src/grabber.py b/src/grabber.py index df8fd1f..cf18858 100644 --- a/src/grabber.py +++ b/src/grabber.py @@ -2,7 +2,6 @@ import logging import os import random -import re import time import urllib from abc import ABCMeta, abstractmethod @@ -18,28 +17,28 @@ class FrameGrabber(metaclass=ABCMeta): @staticmethod - def create_grabber(stream=None, **kwargs): + def create_grabber(stream=None, streamtype=None, **kwargs): logger.debug(f"Input {stream=} (type {type(stream)}") - if type(stream) == int: + if (type(stream) == int and not streamtype) or streamtype == "device": logger.debug("Looking for camera {stream=}") return DeviceFrameGrabber(stream=stream) - elif (type(stream) == str) and (stream.find("*") != -1): + elif ((type(stream) == str) and (stream.find("*") != -1) and not streamtype) or streamtype == "directory": logger.debug(f"Found wildcard file {stream=}") return DirectoryFrameGrabber(stream=stream) - elif (type(stream) == str) and (stream[:4] == "rtsp"): + elif ((type(stream) == str) and (stream[:4] == "rtsp") and not streamtype) or streamtype == "rtsp": logger.debug(f"found rtsp stream {stream=}") return RTSPFrameGrabber(stream=stream) - elif (type(stream) == str) and (stream.find("youtube.com") > 0): + elif ((type(stream) == str) and (stream.find("youtube.com") > 0) and not streamtype) or streamtype == "youtube": logger.debug(f"found youtube stream {stream=}") return YouTubeFrameGrabber(stream=stream) - elif (type(stream) == str) and Path(stream).is_file(): + elif ((type(stream) == str) and Path(stream).is_file() and not streamtype) or streamtype == "file": logger.debug(f"found filename stream {stream=}") return FileStreamFrameGrabber(stream=stream, **kwargs) - elif (type(stream) == str) and (stream[:4] == "http"): + elif ((type(stream) == str) and (stream[:4] == "http") and not streamtype) or streamtype == "image_url": logger.debug(f"found image url {stream=}") return ImageURLFrameGrabber(url=stream, **kwargs) else: - raise ValueError(f"cannot create a frame grabber from {stream=}") + raise ValueError(f"cannot create a frame grabber from {stream=} {streamtype=}") @abstractmethod def grab(): diff --git a/src/stream.py b/src/stream.py index 09c4381..b57c62f 100644 --- a/src/stream.py +++ b/src/stream.py @@ -9,6 +9,7 @@ -f, --fps=FPS number of frames to capture per second. 0 to use maximum rate possible. [default: 5] -h, --help show this message. -s, --stream=STREAM id, filename or URL of a video stream (e.g. rtsp://host:port/script?params OR movie.mp4 OR *.jpg) [default: 0] + -o, --streamtype=TYPE (optional) type of stream. One of [device, directory, rtsp, youtube, file, image_url] [default: auto-infer] -t, --token=TOKEN api token to authenticate with the groundlight api -v, --verbose enable debug logs -w, --width=WIDTH resize images to w pixels wide (and scale height proportionately if not set explicitly) @@ -35,9 +36,8 @@ import cv2 import docopt import yaml -from groundlight import Groundlight - from grabber import FrameGrabber +from groundlight import Groundlight from motion import MotionDetector fname = os.path.join(os.path.dirname(__file__), "logging.yaml") @@ -169,10 +169,12 @@ def main(): DETECTOR = args["--detector"] STREAM = args["--stream"] - try: - STREAM = int(STREAM) - except ValueError as e: - logger.debug(f"{STREAM=} is not an int. Treating as a filename or url.") + STREAM_TYPE = args.get("--type") + if STREAM_TYPE is None: + try: + STREAM = int(STREAM) + except ValueError as e: + logger.debug(f"{STREAM=} is not an int. Treating as a filename or url.") FPS = args["--fps"] try: @@ -215,7 +217,7 @@ def main(): logger.debug(f"creating groundlight client with {ENDPOINT=} and {TOKEN=}") gl = Groundlight(endpoint=ENDPOINT, api_token=TOKEN) - grabber = FrameGrabber.create_grabber(stream=STREAM, fps_target=FPS) + grabber = FrameGrabber.create_grabber(stream=STREAM, stream_type=STREAM_TYPE, fps_target=FPS) q = Queue() tc = ThreadControl() if motion_detect: From 64f0aabee9f9660c0deb13d2d019bd0105d5a40f Mon Sep 17 00:00:00 2001 From: Tyler Romero Date: Mon, 8 Jan 2024 11:00:00 -0800 Subject: [PATCH 2/3] cleanup --- README.md | 2 +- src/grabber.py | 18 ++++++++++-------- src/stream.py | 9 +++++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 95aa6f5..fd062f5 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ options: -f, --fps=FPS number of frames to capture per second. 0 to use maximum rate possible. [default: 5] -h, --help show this message. -s, --stream=STREAM id, filename or URL of a video stream (e.g. rtsp://host:port/script?params OR video.mp4 OR *.jpg) [default: 0] - -o, --streamtype=TYPE (optional) type of stream. One of [device, directory, rtsp, youtube, file, image_url] [default: auto-infer] + -x, --streamtype=TYPE (optional) type of stream. One of [device, directory, rtsp, youtube, file, image_url] [default: auto-infer] -t, --token=TOKEN API token to authenticate with the Groundlight API -v, --verbose enable debug logs -w, --width=WIDTH resize images to w pixels wide (and scale height proportionately if not set explicitly) diff --git a/src/grabber.py b/src/grabber.py index cf18858..b106e9e 100644 --- a/src/grabber.py +++ b/src/grabber.py @@ -17,28 +17,30 @@ class FrameGrabber(metaclass=ABCMeta): @staticmethod - def create_grabber(stream=None, streamtype=None, **kwargs): + def create_grabber(stream=None, stream_type=None, **kwargs): logger.debug(f"Input {stream=} (type {type(stream)}") - if (type(stream) == int and not streamtype) or streamtype == "device": + if (type(stream) == int and not streamtype) or stream_type == "device": logger.debug("Looking for camera {stream=}") return DeviceFrameGrabber(stream=stream) - elif ((type(stream) == str) and (stream.find("*") != -1) and not streamtype) or streamtype == "directory": + elif ((type(stream) == str) and (stream.find("*") != -1) and not stream_type) or stream_type == "directory": logger.debug(f"Found wildcard file {stream=}") return DirectoryFrameGrabber(stream=stream) - elif ((type(stream) == str) and (stream[:4] == "rtsp") and not streamtype) or streamtype == "rtsp": + elif ((type(stream) == str) and (stream[:4] == "rtsp") and not stream_type) or stream_type == "rtsp": logger.debug(f"found rtsp stream {stream=}") return RTSPFrameGrabber(stream=stream) - elif ((type(stream) == str) and (stream.find("youtube.com") > 0) and not streamtype) or streamtype == "youtube": + elif ( + (type(stream) == str) and (stream.find("youtube.com") > 0) and not stream_type + ) or stream_type == "youtube": logger.debug(f"found youtube stream {stream=}") return YouTubeFrameGrabber(stream=stream) - elif ((type(stream) == str) and Path(stream).is_file() and not streamtype) or streamtype == "file": + elif ((type(stream) == str) and Path(stream).is_file() and not stream_type) or stream_type == "file": logger.debug(f"found filename stream {stream=}") return FileStreamFrameGrabber(stream=stream, **kwargs) - elif ((type(stream) == str) and (stream[:4] == "http") and not streamtype) or streamtype == "image_url": + elif ((type(stream) == str) and (stream[:4] == "http") and not stream_type) or stream_type == "image_url": logger.debug(f"found image url {stream=}") return ImageURLFrameGrabber(url=stream, **kwargs) else: - raise ValueError(f"cannot create a frame grabber from {stream=} {streamtype=}") + raise ValueError(f"cannot create a frame grabber from {stream=} {stream_type=}") @abstractmethod def grab(): diff --git a/src/stream.py b/src/stream.py index b57c62f..d2fbdea 100644 --- a/src/stream.py +++ b/src/stream.py @@ -9,7 +9,7 @@ -f, --fps=FPS number of frames to capture per second. 0 to use maximum rate possible. [default: 5] -h, --help show this message. -s, --stream=STREAM id, filename or URL of a video stream (e.g. rtsp://host:port/script?params OR movie.mp4 OR *.jpg) [default: 0] - -o, --streamtype=TYPE (optional) type of stream. One of [device, directory, rtsp, youtube, file, image_url] [default: auto-infer] + -x, --streamtype=TYPE (optional) type of stream. One of [device, directory, rtsp, youtube, file, image_url] [default: auto-infer] -t, --token=TOKEN api token to authenticate with the groundlight api -v, --verbose enable debug logs -w, --width=WIDTH resize images to w pixels wide (and scale height proportionately if not set explicitly) @@ -169,12 +169,17 @@ def main(): DETECTOR = args["--detector"] STREAM = args["--stream"] - STREAM_TYPE = args.get("--type") + STREAM_TYPE = args.get("--streamtype") if STREAM_TYPE is None: try: STREAM = int(STREAM) except ValueError as e: logger.debug(f"{STREAM=} is not an int. Treating as a filename or url.") + else: + STREAM_TYPE = STREAM_TYPE.lower() + if STREAM_TYPE not in ["device", "directory", "rtsp", "youtube", "file", "image_url"]: + raise ValueError(f"Invalid stream type {STREAM_TYPE=}") + logger.debug(f"{STREAM_TYPE=}") FPS = args["--fps"] try: From 611e5f27e69656c95416ca3001a7f86bfe5ef9f2 Mon Sep 17 00:00:00 2001 From: Auto-format Bot Date: Mon, 8 Jan 2024 20:09:32 +0000 Subject: [PATCH 3/3] Automatically reformatting code with black and isort --- src/stream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stream.py b/src/stream.py index d2fbdea..f15d6c8 100644 --- a/src/stream.py +++ b/src/stream.py @@ -36,8 +36,9 @@ import cv2 import docopt import yaml -from grabber import FrameGrabber from groundlight import Groundlight + +from grabber import FrameGrabber from motion import MotionDetector fname = os.path.join(os.path.dirname(__file__), "logging.yaml")