video-stream-data 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Andreas Bresser
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: video_stream_data
3
+ Version: 0.1.3
4
+ Summary: Unified data format for video streams (devices, server, ...)
5
+ Home-page: https://github.com/brean/video_stream_data
6
+ Author: Andreas Bresser
7
+ Author-email: Andreas.Bresser@dfki.de
8
+ License: BSD-3
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Dynamic: license-file
12
+
13
+ # Video Stream Data
14
+ Dependency-free data structures for video streaming.
15
+
16
+ ## Installation
17
+ Use **pip** to install. Its recommended to install in a virtual environment
18
+
19
+ ```bash
20
+ python3 -m venv video-streaming-pipeline
21
+ # install using system-site-packages (like opencv and pyudev)
22
+ source video-streaming-pipeline/bin/activate --system-site-packages
23
+ pip3 install video_stream_data
24
+ ```
25
+
26
+ Although not recommended a user installation with `--break-system-packages` would also be okay as it does not have any dependencies.
27
+
28
+ ## Usage
29
+ Simply import the data classes you want to have, you can use the parser to load the video stream settings from a file (see `test/`-folder).
30
+
31
+ You can use the data structure to manually create any kind of video stream.
32
+
33
+
34
+ ```mermaid
35
+ classDiagram
36
+ direction LR
37
+
38
+ class StreamControlType {
39
+ <<enumeration>>
40
+ +INT: str = 'int'
41
+ +BOOL: str = 'bool'
42
+ +MENU: str = 'menu'
43
+ }
44
+
45
+ class Encoding {
46
+ <<enumeration>>
47
+ +PASSTHROUGH: str = 'passthrough'
48
+ +BGR: str = 'bgr'
49
+ +GREY: str = 'grey'
50
+ +GREY16: str = 'grey16'
51
+ +GRB: str = 'rbg'
52
+ +BGRA: str = 'bgra'
53
+ +RGBA: str = 'rgba'
54
+
55
+ }
56
+
57
+ class Codec {
58
+ <<enumeration>>
59
+ +MJPEG: str = 'MJPEG' # Motion-JPEG
60
+ +YUYV: str = 'YUYV' # e.g. YUYV 4:2:2
61
+ +XVID: str = 'XVID' # e.g. mp4 files
62
+ +UNKNOWN: str = 'unknown'
63
+ }
64
+
65
+ class StreamControl {
66
+ +type: StreamControlType
67
+ +name: str
68
+ +writable: bool = False
69
+ +min: float = 0
70
+ +max: float = 0
71
+ +step: int = 1
72
+ +value: float | bool | None = None
73
+ +options: list = []
74
+ }
75
+
76
+ class StreamValue {
77
+ # desired video resolution
78
+ +resolution: list[int]
79
+ +fps: float # desired FPS by user
80
+ # desired configuration
81
+ +controls: dict[str, int | float | bool | None]
82
+ +encoding: Encoding = Encoding.PASSTHROUGH
83
+ +codec: Codec = Codec.UNKNOWN
84
+ }
85
+
86
+ class StreamInfo {
87
+ +name: str
88
+ +stream_path: str
89
+ +driver: str
90
+ +codec: list[str]
91
+ +controls: list[StreamControl]
92
+ +resolutions: list[int, int]
93
+ +max_fps: float
94
+ +values: StreamValue
95
+ +backend: str = 'v4l2'
96
+ }
97
+
98
+ StreamControlType <|-- StreamControl
99
+ Encoding <|-- StreamValue
100
+ Codec <|-- StreamValue
101
+ StreamControl --> StreamInfo : controls
102
+ StreamValue --> StreamInfo : values
103
+
104
+ ```
105
+ *Fig. 1: Data Model for the StreamInfo generated from any device*
@@ -0,0 +1,93 @@
1
+ # Video Stream Data
2
+ Dependency-free data structures for video streaming.
3
+
4
+ ## Installation
5
+ Use **pip** to install. Its recommended to install in a virtual environment
6
+
7
+ ```bash
8
+ python3 -m venv video-streaming-pipeline
9
+ # install using system-site-packages (like opencv and pyudev)
10
+ source video-streaming-pipeline/bin/activate --system-site-packages
11
+ pip3 install video_stream_data
12
+ ```
13
+
14
+ Although not recommended a user installation with `--break-system-packages` would also be okay as it does not have any dependencies.
15
+
16
+ ## Usage
17
+ Simply import the data classes you want to have, you can use the parser to load the video stream settings from a file (see `test/`-folder).
18
+
19
+ You can use the data structure to manually create any kind of video stream.
20
+
21
+
22
+ ```mermaid
23
+ classDiagram
24
+ direction LR
25
+
26
+ class StreamControlType {
27
+ <<enumeration>>
28
+ +INT: str = 'int'
29
+ +BOOL: str = 'bool'
30
+ +MENU: str = 'menu'
31
+ }
32
+
33
+ class Encoding {
34
+ <<enumeration>>
35
+ +PASSTHROUGH: str = 'passthrough'
36
+ +BGR: str = 'bgr'
37
+ +GREY: str = 'grey'
38
+ +GREY16: str = 'grey16'
39
+ +GRB: str = 'rbg'
40
+ +BGRA: str = 'bgra'
41
+ +RGBA: str = 'rgba'
42
+
43
+ }
44
+
45
+ class Codec {
46
+ <<enumeration>>
47
+ +MJPEG: str = 'MJPEG' # Motion-JPEG
48
+ +YUYV: str = 'YUYV' # e.g. YUYV 4:2:2
49
+ +XVID: str = 'XVID' # e.g. mp4 files
50
+ +UNKNOWN: str = 'unknown'
51
+ }
52
+
53
+ class StreamControl {
54
+ +type: StreamControlType
55
+ +name: str
56
+ +writable: bool = False
57
+ +min: float = 0
58
+ +max: float = 0
59
+ +step: int = 1
60
+ +value: float | bool | None = None
61
+ +options: list = []
62
+ }
63
+
64
+ class StreamValue {
65
+ # desired video resolution
66
+ +resolution: list[int]
67
+ +fps: float # desired FPS by user
68
+ # desired configuration
69
+ +controls: dict[str, int | float | bool | None]
70
+ +encoding: Encoding = Encoding.PASSTHROUGH
71
+ +codec: Codec = Codec.UNKNOWN
72
+ }
73
+
74
+ class StreamInfo {
75
+ +name: str
76
+ +stream_path: str
77
+ +driver: str
78
+ +codec: list[str]
79
+ +controls: list[StreamControl]
80
+ +resolutions: list[int, int]
81
+ +max_fps: float
82
+ +values: StreamValue
83
+ +backend: str = 'v4l2'
84
+ }
85
+
86
+ StreamControlType <|-- StreamControl
87
+ Encoding <|-- StreamValue
88
+ Codec <|-- StreamValue
89
+ StreamControl --> StreamInfo : controls
90
+ StreamValue --> StreamInfo : values
91
+
92
+ ```
93
+ *Fig. 1: Data Model for the StreamInfo generated from any device*
@@ -0,0 +1,41 @@
1
+ [metadata]
2
+ name = video_stream_data
3
+ version = 0.1.3
4
+ author = Andreas Bresser
5
+ author_email = Andreas.Bresser@dfki.de
6
+ license = BSD-3
7
+ description = Unified data format for video streams (devices, server, ...)
8
+ url = https://github.com/brean/video_stream_data
9
+ long_description = file: README.md
10
+ long_description_content_type = text/markdown
11
+
12
+ [options]
13
+ packages = find:
14
+ install_requires =
15
+
16
+ [bumpversion]
17
+ current_version = 0.1.3
18
+ commit = True
19
+ tag = True
20
+
21
+ [bumpversion:file:setup.py]
22
+ search = version='{current_version}'
23
+ replace = version='{new_version}'
24
+
25
+ [bumpversion:file:video_stream_data/__init__.py]
26
+ search = __version__ = '{current_version}'
27
+ replace = __version__ = '{new_version}'
28
+
29
+ [bdist_wheel]
30
+ universal = 1
31
+
32
+ [flake8]
33
+ exclude = docs
34
+
35
+ [aliases]
36
+ test = pytest
37
+
38
+ [egg_info]
39
+ tag_build =
40
+ tag_date = 0
41
+
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env python3
2
+ """Use setuptools to install video_stream_data."""
3
+ from setuptools import setup
4
+
5
+ # read from setup.cfg
6
+ setup()
@@ -0,0 +1,46 @@
1
+ """Test loading/saving data."""
2
+ from pathlib import Path
3
+ import tempfile
4
+
5
+ from video_stream_data import Codec, Encoding, StreamInfo, StreamValue
6
+ from video_stream_data.utils import load, save
7
+
8
+ BASE_PATH = Path(__file__).absolute().parent
9
+ LOCAL_VIDEO_DEVICE = BASE_PATH / 'data' / 'local_video_device.yml'
10
+
11
+
12
+ def test_load_stream_info():
13
+ """Test loading data from yaml."""
14
+ stream_info = load(LOCAL_VIDEO_DEVICE)
15
+ assert len(stream_info) == 1
16
+ stream = stream_info[0]
17
+ assert isinstance(stream, StreamInfo)
18
+ assert stream.name == 'Dummy Camera'
19
+ assert isinstance(stream.values, StreamValue)
20
+ assert stream.values.codec == Codec.MJPEG
21
+ assert stream.values.encoding == Encoding.PASSTHROUGH
22
+ assert stream.values.controls['Power Line Frequency'] == 2
23
+ assert stream.controls
24
+ power_line_freq = False
25
+ for ctrl in stream.controls:
26
+ if ctrl.name == 'Power Line Frequency':
27
+ power_line_freq = True
28
+ break
29
+ assert power_line_freq
30
+
31
+
32
+ def test_save_stream_info():
33
+ """Test saving data to temp file."""
34
+ stream_info = load(LOCAL_VIDEO_DEVICE)
35
+ tmp = tempfile.NamedTemporaryFile()
36
+ save(stream_info, tmp.name)
37
+
38
+ # check file by string compare
39
+ saved_data = ''
40
+ with open(tmp.name, 'r') as data:
41
+ saved_data = data.read()
42
+ assert 'Dummy Camera' in saved_data
43
+
44
+ # check full structure by reloading
45
+ reloaded_stream_info = load(tmp.name)
46
+ assert reloaded_stream_info == stream_info
@@ -0,0 +1,166 @@
1
+ """Provide unified meta data definition for video streaming."""
2
+ from dataclasses import asdict, dataclass, field
3
+ from enum import Enum
4
+
5
+
6
+ class StreamControlType(str, Enum):
7
+ """Different configuration types for the stream.
8
+
9
+ Taken from opencv2 device controls.
10
+ """
11
+
12
+ INT = 'int'
13
+ BOOL = 'bool'
14
+ MENU = 'menu'
15
+
16
+
17
+ class Encoding(str, Enum):
18
+ """Defines how the video stream gets encodied.
19
+
20
+ Should default to 'passthrough'.
21
+ Normally BGR in ROS, RGB in h264.
22
+ """
23
+
24
+ PASSTHROUGH = 'passthrough'
25
+ BGR = 'bgr'
26
+ GREY = 'grey'
27
+ GREY16 = 'grey16'
28
+ RGB = 'rgb'
29
+ BGRA = 'bgra'
30
+ RGBA = 'rgba'
31
+
32
+ def to_ros_bridge(self) -> str:
33
+ """Create string to use with the ROS2 CvBridge."""
34
+ if self.value == Encoding.BGR:
35
+ return 'bgr8'
36
+ elif self.value == Encoding.RGB:
37
+ return 'rgb8'
38
+ elif self.value == Encoding.BGR:
39
+ return 'bgra8'
40
+ elif self.value == Encoding.RGB:
41
+ return 'rgba8'
42
+ elif self.value == Encoding.GREY:
43
+ return 'mono8'
44
+ elif self.value == Encoding.GREY16:
45
+ return 'mono16'
46
+ else:
47
+ return str(self.value)
48
+
49
+
50
+ class Codec(str, Enum):
51
+ """Codec type/Pixel format as fourcc."""
52
+
53
+ # see linuxpy/video/raw.py
54
+
55
+ MJPEG = 'MJPEG' # Motion-JPEG
56
+ YUYV = 'YUYV'
57
+ XVID = 'XVID' # MP4 files
58
+ UNKNOWN = 'unknown'
59
+
60
+ def to_text(self) -> str:
61
+ """Create human readable text."""
62
+ if self.value == Encoding.MJPEG:
63
+ return 'Motion-JPEG'
64
+ elif self.value == Encoding.YUYV:
65
+ return 'YUYV'
66
+ elif self.value == Encoding.XVID:
67
+ return 'XVID/MP4'
68
+
69
+ def to_fourcc(self) -> str:
70
+ """Create FourCC-Text for configuration of OpenCV2 VideoWriter."""
71
+ if self.value == Encoding.MJPEG:
72
+ return 'MJPG'
73
+ return str(self)
74
+
75
+
76
+ @dataclass
77
+ class StreamControl:
78
+ """Provide a value the user can configure."""
79
+
80
+ type: StreamControlType # noqa: A003
81
+ name: str
82
+ writable: bool = False
83
+ min: float = 0 # noqa: A003
84
+ max: float = 0 # noqa: A003
85
+ step: int = 1
86
+ value: int | float | bool | None = None
87
+ options: list[(str, str)] = field(default_factory=list)
88
+
89
+ def __post_init__(self):
90
+ if self.type:
91
+ self.type = StreamControlType(self.type)
92
+
93
+ @dataclass
94
+ class StreamValue:
95
+ """Values requested by the user."""
96
+
97
+ # selected resolution
98
+ resolution: list[int]
99
+ # current fps
100
+ fps: float
101
+ # selected control configurations
102
+ controls: dict[str, int | float | bool | None]
103
+ # selected encoding, e.g. bgr
104
+ encoding: Encoding = Encoding.PASSTHROUGH
105
+ # selected codec e.g. MJPEG for "Motion-JPEG" or YUYV for "YUYV 4:2:2"
106
+ codec: Codec = Codec.UNKNOWN
107
+
108
+ def __post_init__(self):
109
+ if self.encoding:
110
+ self.encoding = Encoding(self.encoding)
111
+
112
+
113
+ @dataclass
114
+ class StreamInfo:
115
+ """Stream information provided by the device/host."""
116
+
117
+ name: str
118
+ # unique stream path
119
+ stream_path: str
120
+ # driver for example "uvcvideo" for a local OpenCV webcam or
121
+ # "webrtc" for a WebRTC Video Stream
122
+ driver: str
123
+ # available codec
124
+ codec: list[Codec]
125
+ # all available controls from linuxpy
126
+ controls: list[StreamControl]
127
+ # all available resolutions, starting with the default resolution
128
+ resolutions: list[int, int]
129
+ # max. possible fps (at default resolution)
130
+ max_fps: float
131
+ # current configuration as own data structure so it can easily be handed
132
+ # over as dict from any service
133
+ values: StreamValue
134
+ backend: str = 'v4l2' # (optional) OpenCV2 Backend (only if cv2 is used)
135
+
136
+ def __post_init__(self):
137
+ if self.codec:
138
+ self.codec = [Codec(c) for c in self.codec]
139
+ if self.values and isinstance(self.values, dict):
140
+ self.values = StreamValue(**self.values)
141
+ if self.controls:
142
+ self.controls = [
143
+ StreamControl(**c) if isinstance(c, dict) else c
144
+ for c in self.controls
145
+ ]
146
+
147
+
148
+ def _dict_factory(data):
149
+ def convert_value(obj):
150
+ if isinstance(obj, Enum):
151
+ return obj.value
152
+ elif isinstance(obj, list):
153
+ return [convert_value(x) for x in obj]
154
+ elif isinstance(obj, set):
155
+ return {convert_value(x) for x in obj}
156
+ elif isinstance(obj, tuple):
157
+ return tuple(convert_value(x) for x in obj)
158
+ return obj
159
+ return {k: convert_value(v) for k, v in data}
160
+
161
+
162
+ def stream_as_dict(stream_obj):
163
+ """Serialize stream information as dict."""
164
+ return asdict(
165
+ stream_obj,
166
+ dict_factory=_dict_factory)
@@ -0,0 +1,21 @@
1
+ """Utility functions like saving and loading YAML files."""
2
+ from pathlib import Path
3
+
4
+ import yaml
5
+
6
+ from . import stream_as_dict, StreamInfo
7
+
8
+
9
+ def load(filename: Path | str) -> None | list[StreamInfo]:
10
+ """Load the yaml file and return it as list of StreamInfo."""
11
+ with open(filename, 'r') as data:
12
+ yaml_data = yaml.safe_load(data)
13
+ return [StreamInfo(**stream) for stream in yaml_data]
14
+ return None
15
+
16
+
17
+ def save(data: list[StreamInfo], filename: Path | str) -> None:
18
+ """Save list of StreamInfo to yaml file."""
19
+ yaml_data = [stream_as_dict(s) for s in data]
20
+ with open(filename, 'w') as data:
21
+ data.write(yaml.safe_dump(yaml_data))
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: video_stream_data
3
+ Version: 0.1.3
4
+ Summary: Unified data format for video streams (devices, server, ...)
5
+ Home-page: https://github.com/brean/video_stream_data
6
+ Author: Andreas Bresser
7
+ Author-email: Andreas.Bresser@dfki.de
8
+ License: BSD-3
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Dynamic: license-file
12
+
13
+ # Video Stream Data
14
+ Dependency-free data structures for video streaming.
15
+
16
+ ## Installation
17
+ Use **pip** to install. Its recommended to install in a virtual environment
18
+
19
+ ```bash
20
+ python3 -m venv video-streaming-pipeline
21
+ # install using system-site-packages (like opencv and pyudev)
22
+ source video-streaming-pipeline/bin/activate --system-site-packages
23
+ pip3 install video_stream_data
24
+ ```
25
+
26
+ Although not recommended a user installation with `--break-system-packages` would also be okay as it does not have any dependencies.
27
+
28
+ ## Usage
29
+ Simply import the data classes you want to have, you can use the parser to load the video stream settings from a file (see `test/`-folder).
30
+
31
+ You can use the data structure to manually create any kind of video stream.
32
+
33
+
34
+ ```mermaid
35
+ classDiagram
36
+ direction LR
37
+
38
+ class StreamControlType {
39
+ <<enumeration>>
40
+ +INT: str = 'int'
41
+ +BOOL: str = 'bool'
42
+ +MENU: str = 'menu'
43
+ }
44
+
45
+ class Encoding {
46
+ <<enumeration>>
47
+ +PASSTHROUGH: str = 'passthrough'
48
+ +BGR: str = 'bgr'
49
+ +GREY: str = 'grey'
50
+ +GREY16: str = 'grey16'
51
+ +GRB: str = 'rbg'
52
+ +BGRA: str = 'bgra'
53
+ +RGBA: str = 'rgba'
54
+
55
+ }
56
+
57
+ class Codec {
58
+ <<enumeration>>
59
+ +MJPEG: str = 'MJPEG' # Motion-JPEG
60
+ +YUYV: str = 'YUYV' # e.g. YUYV 4:2:2
61
+ +XVID: str = 'XVID' # e.g. mp4 files
62
+ +UNKNOWN: str = 'unknown'
63
+ }
64
+
65
+ class StreamControl {
66
+ +type: StreamControlType
67
+ +name: str
68
+ +writable: bool = False
69
+ +min: float = 0
70
+ +max: float = 0
71
+ +step: int = 1
72
+ +value: float | bool | None = None
73
+ +options: list = []
74
+ }
75
+
76
+ class StreamValue {
77
+ # desired video resolution
78
+ +resolution: list[int]
79
+ +fps: float # desired FPS by user
80
+ # desired configuration
81
+ +controls: dict[str, int | float | bool | None]
82
+ +encoding: Encoding = Encoding.PASSTHROUGH
83
+ +codec: Codec = Codec.UNKNOWN
84
+ }
85
+
86
+ class StreamInfo {
87
+ +name: str
88
+ +stream_path: str
89
+ +driver: str
90
+ +codec: list[str]
91
+ +controls: list[StreamControl]
92
+ +resolutions: list[int, int]
93
+ +max_fps: float
94
+ +values: StreamValue
95
+ +backend: str = 'v4l2'
96
+ }
97
+
98
+ StreamControlType <|-- StreamControl
99
+ Encoding <|-- StreamValue
100
+ Codec <|-- StreamValue
101
+ StreamControl --> StreamInfo : controls
102
+ StreamValue --> StreamInfo : values
103
+
104
+ ```
105
+ *Fig. 1: Data Model for the StreamInfo generated from any device*
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ README.md
3
+ setup.cfg
4
+ setup.py
5
+ test/test_utils.py
6
+ video_stream_data/__init__.py
7
+ video_stream_data/utils.py
8
+ video_stream_data.egg-info/PKG-INFO
9
+ video_stream_data.egg-info/SOURCES.txt
10
+ video_stream_data.egg-info/dependency_links.txt
11
+ video_stream_data.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ video_stream_data