forked from platypush/platypush
Added stream_on_start
argument to camera
plugins.
It replaces the functionalities of the deprecated `camera` backends.
This commit is contained in:
parent
9cf95125a6
commit
9ad9bd20e4
1 changed files with 84 additions and 30 deletions
|
@ -86,6 +86,7 @@ class CameraPlugin(RunnablePlugin, ABC):
|
|||
stream_format: str = 'mjpeg',
|
||||
listen_port: Optional[int] = 5000,
|
||||
bind_address: str = '0.0.0.0',
|
||||
stream_on_start: bool = False,
|
||||
ffmpeg_bin: str = 'ffmpeg',
|
||||
input_codec: Optional[str] = None,
|
||||
output_codec: Optional[str] = None,
|
||||
|
@ -94,35 +95,51 @@ class CameraPlugin(RunnablePlugin, ABC):
|
|||
"""
|
||||
:param device: Identifier of the default capturing device.
|
||||
:param resolution: Default resolution, as a tuple of two integers.
|
||||
:param frames_dir: Directory where the camera frames will be stored (default:
|
||||
``~/.local/share/platypush/<plugin.name>/frames``)
|
||||
:param frames_dir: Directory where the camera frames will be stored
|
||||
(default: ``~/.local/share/platypush/<plugin.name>/frames``)
|
||||
:param warmup_frames: Cameras usually take a while to adapt their
|
||||
luminosity and focus to the environment when taking a picture.
|
||||
This parameter allows you to specify the number of "warmup" frames
|
||||
to capture upon picture command before actually capturing a frame
|
||||
(default: 5 but you may want to calibrate this parameter for your
|
||||
camera)
|
||||
:param warmup_seconds: Number of seconds to wait before a picture is taken or the first frame of a
|
||||
video/sequence is captured (default: 0).
|
||||
:param capture_timeout: Maximum number of seconds to wait between the programmed termination of a capture
|
||||
session and the moment the device is released.
|
||||
:param scale_x: If set, the images will be scaled along the x-axis by the specified factor
|
||||
:param scale_y: If set, the images will be scaled along the y-axis by the specified factor
|
||||
:param warmup_seconds: Number of seconds to wait before a picture is
|
||||
taken or the first frame of a video/sequence is captured (default:
|
||||
0).
|
||||
:param capture_timeout: Maximum number of seconds to wait between the
|
||||
programmed termination of a capture session and the moment the
|
||||
device is released.
|
||||
:param scale_x: If set, the images will be scaled along the x-axis by
|
||||
the specified factor
|
||||
:param scale_y: If set, the images will be scaled along the y-axis by
|
||||
the specified factor
|
||||
:param color_transform: Color transformation to apply to the images.
|
||||
:param grayscale: Whether the output should be converted to grayscale.
|
||||
:param rotate: If set, the images will be rotated by the specified number of degrees
|
||||
:param rotate: If set, the images will be rotated by the specified
|
||||
number of degrees
|
||||
:param fps: Frames per second (default: 25).
|
||||
:param horizontal_flip: If set, the images will be flipped on the horizontal axis.
|
||||
:param vertical_flip: If set, the images will be flipped on the vertical axis.
|
||||
:param listen_port: Default port to be used for streaming over TCP (default: 5000).
|
||||
:param bind_address: Default bind address for TCP streaming (default: 0.0.0.0, accept any connections).
|
||||
:param input_codec: Specify the ffmpeg video codec (``-vcodec``) used for the input.
|
||||
:param output_codec: Specify the ffmpeg video codec (``-vcodec``) to be used for encoding the output. For some
|
||||
ffmpeg output formats (e.g. ``h264`` and ``rtp``) this may default to ``libxvid``.
|
||||
:param horizontal_flip: If set, the images will be flipped on the
|
||||
horizontal axis.
|
||||
:param vertical_flip: If set, the images will be flipped on the vertical
|
||||
axis.
|
||||
:param listen_port: Default port to be used for streaming over TCP
|
||||
(default: 5000).
|
||||
:param bind_address: Default bind address for TCP streaming (default:
|
||||
0.0.0.0, accept connections on any network interface).
|
||||
:param stream_on_start: If set, the camera will start streaming on the
|
||||
specified ``bind_address`` and ``listen_port`` as soon as the plugin
|
||||
is started. Otherwise, the stream will be started only when the
|
||||
:meth:`.start_streaming` method is called. Default: False.
|
||||
:param input_codec: Specify the ffmpeg video codec (``-vcodec``) used
|
||||
for the input.
|
||||
:param output_codec: Specify the ffmpeg video codec (``-vcodec``) to be
|
||||
used for encoding the output. For some ffmpeg output formats (e.g.
|
||||
``h264`` and ``rtp``) this may default to ``libxvid``.
|
||||
:param input_format: Plugin-specific format/type for the input stream.
|
||||
:param output_format: Plugin-specific format/type for the output videos.
|
||||
:param ffmpeg_bin: Path to the ffmpeg binary (default: ``ffmpeg``).
|
||||
:param stream_format: Default format for the output when streamed to a network device. Available:
|
||||
:param stream_format: Default format for the output when streamed to a
|
||||
network device. Available:
|
||||
|
||||
- ``MJPEG`` (default)
|
||||
- ``H264`` (over ``ffmpeg``)
|
||||
|
@ -137,6 +154,7 @@ class CameraPlugin(RunnablePlugin, ABC):
|
|||
plugin_name = get_plugin_name_by_class(self)
|
||||
assert isinstance(workdir, str) and plugin_name
|
||||
self.workdir = os.path.join(workdir, plugin_name)
|
||||
self._stream_on_start = stream_on_start
|
||||
pathlib.Path(self.workdir).mkdir(mode=0o755, exist_ok=True, parents=True)
|
||||
|
||||
self.camera_info = self._camera_info_class(
|
||||
|
@ -322,7 +340,9 @@ class CameraPlugin(RunnablePlugin, ABC):
|
|||
raise NotImplementedError()
|
||||
|
||||
@staticmethod
|
||||
def store_frame(frame, filepath: str, format: Optional[str] = None):
|
||||
def store_frame( # pylint: disable=redefined-builtin
|
||||
frame, filepath: str, format: Optional[str] = None
|
||||
):
|
||||
"""
|
||||
Capture a frame to the filesystem using the ``PIL`` library - it can be overridden by derived classes.
|
||||
|
||||
|
@ -346,9 +366,9 @@ class CameraPlugin(RunnablePlugin, ABC):
|
|||
def _store_frame(
|
||||
self,
|
||||
frame,
|
||||
*args,
|
||||
frames_dir: Optional[str] = None,
|
||||
image_file: Optional[str] = None,
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> str:
|
||||
"""
|
||||
|
@ -792,21 +812,39 @@ class CameraPlugin(RunnablePlugin, ABC):
|
|||
self,
|
||||
device: Optional[Union[int, str]] = None,
|
||||
duration: Optional[float] = None,
|
||||
stream_format: str = 'mkv',
|
||||
stream_format: Optional[str] = None,
|
||||
**camera,
|
||||
) -> dict:
|
||||
"""
|
||||
Expose the video stream of a camera over a TCP connection.
|
||||
|
||||
:param device: Name/path/ID of the device to capture from (default: None, use the default device).
|
||||
:param duration: Streaming thread duration (default: until :meth:`.stop_streaming` is called).
|
||||
:param stream_format: Format of the output stream - e.g. ``h264``, ``mjpeg``, ``mkv`` etc. (default: ``mkv``).
|
||||
When the streaming is started, the plugin will listen on the specified
|
||||
``bind_address`` and ``listen_port`` and stream camera frames to
|
||||
connected clients. If ``stream_format`` is a video format (H264, H265,
|
||||
MKV, MP4 etc.) then the camera stream can be viewed using a video
|
||||
player - for example, using ``vlc``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
vlc tcp://<host>:<port>
|
||||
|
||||
:param device: Name/path/ID of the device to capture from (default:
|
||||
None, use the default device).
|
||||
:param duration: Streaming thread duration (default: until
|
||||
:meth:`.stop_streaming` is called).
|
||||
:param stream_format: Format of the output stream - e.g. ``h264``,
|
||||
``mjpeg``, ``mkv`` etc. If not specified, the ``stream_format``
|
||||
configured on the plugin will be used.
|
||||
:param camera: Camera object properties - see constructor parameters.
|
||||
:return: The status of the device.
|
||||
"""
|
||||
camera = self.open_device(
|
||||
device=device, stream=True, stream_format=stream_format, **camera
|
||||
device=device,
|
||||
stream=True,
|
||||
stream_format=stream_format or self.camera_info.stream_format,
|
||||
**camera,
|
||||
)
|
||||
|
||||
return self._start_streaming(camera, duration, stream_format) # type: ignore
|
||||
|
||||
def _start_streaming(
|
||||
|
@ -981,7 +1019,23 @@ class CameraPlugin(RunnablePlugin, ABC):
|
|||
return 0
|
||||
|
||||
def main(self):
|
||||
if not self._stream_on_start:
|
||||
self.wait_stop()
|
||||
return
|
||||
|
||||
while not self.should_stop():
|
||||
if self._stream_on_start:
|
||||
self.start_streaming()
|
||||
|
||||
cameras = list(self._streams.values())
|
||||
if not cameras:
|
||||
self.logger.warning('No camera devices could be streamed')
|
||||
self.wait_stop()
|
||||
break
|
||||
|
||||
camera = cameras[0]
|
||||
wait_for_either(self._should_stop, camera.stop_stream_event)
|
||||
self.stop_streaming()
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
|
Loading…
Reference in a new issue