Skip to content

Commit bfe82ed

Browse files
authored
Add rest get_jpeg_snapshot functionality (#114)
1 parent 68a45cf commit bfe82ed

File tree

4 files changed

+74
-10
lines changed

4 files changed

+74
-10
lines changed

go2rtc_client/rest.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,18 @@ async def validate_server_version(self) -> AwesomeVersion:
171171
)
172172

173173
return application_info.version
174+
175+
@handle_error
176+
async def get_jpeg_snapshot(
177+
self, name: str, width: int | None = None, height: int | None = None
178+
) -> bytes:
179+
"""Get a JPEG snapshot from the stream."""
180+
params: dict[str, str | int] = {"src": name}
181+
if width:
182+
params["width"] = width
183+
if height:
184+
params["height"] = height
185+
resp = await self._client.request(
186+
"GET", f"{_API_PREFIX}/frame.jpeg", params=params
187+
)
188+
return await resp.read()

tests/__init__.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,19 @@
33
from pathlib import Path
44

55

6-
def load_fixture(filename: str) -> str:
6+
def load_fixture(filename: str) -> Path:
77
"""Load a fixture."""
8-
path = Path(__package__) / "fixtures" / filename
9-
return path.read_text(encoding="utf-8")
8+
return Path(__package__) / "fixtures" / filename
9+
10+
11+
def load_fixture_bytes(filename: str) -> bytes:
12+
"""Load a fixture and return bytes."""
13+
return load_fixture(filename).read_bytes()
14+
15+
16+
def load_fixture_str(filename: str) -> str:
17+
"""Load a fixture and return str."""
18+
return load_fixture(filename).read_text(encoding="utf-8")
1019

1120

1221
URL = "http://localhost:1984"

tests/fixtures/snapshot.jpg

286 KB
Loading

tests/test_rest.py

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@
1313

1414
from go2rtc_client.exceptions import Go2RtcVersionError
1515
from go2rtc_client.models import WebRTCSdpOffer
16-
from go2rtc_client.rest import _ApplicationClient, _StreamClient, _WebRTCClient
17-
from tests import load_fixture
16+
from go2rtc_client.rest import (
17+
_API_PREFIX,
18+
_ApplicationClient,
19+
_StreamClient,
20+
_WebRTCClient,
21+
)
1822

19-
from . import URL
23+
from . import URL, load_fixture_bytes, load_fixture_str
2024

2125
if TYPE_CHECKING:
2226
from aioresponses import aioresponses
@@ -34,7 +38,7 @@ async def test_application_info(
3438
responses.get(
3539
f"{URL}{_ApplicationClient.PATH}",
3640
status=200,
37-
body=load_fixture("application_info_answer.json"),
41+
body=load_fixture_str("application_info_answer.json"),
3842
)
3943
resp = await rest_client.application.get_info()
4044
assert isinstance(resp.version, AwesomeVersion)
@@ -61,7 +65,7 @@ async def test_streams_get(
6165
responses.get(
6266
f"{URL}{_StreamClient.PATH}",
6367
status=200,
64-
body=load_fixture(filename),
68+
body=load_fixture_str(filename),
6569
)
6670
resp = await rest_client.streams.list()
6771
assert resp == snapshot
@@ -151,7 +155,7 @@ async def test_version_supported(
151155
expected_result: AbstractContextManager[Any],
152156
) -> None:
153157
"""Test validate server version."""
154-
payload = json.loads(load_fixture("application_info_answer.json"))
158+
payload = json.loads(load_fixture_str("application_info_answer.json"))
155159
payload["version"] = server_version
156160
responses.get(
157161
f"{URL}{_ApplicationClient.PATH}",
@@ -173,10 +177,46 @@ async def test_webrtc_offer(
173177
responses.post(
174178
f"{URL}{_WebRTCClient.PATH}?src={camera}",
175179
status=200,
176-
body=load_fixture("webrtc_answer.json"),
180+
body=load_fixture_str("webrtc_answer.json"),
177181
)
178182
resp = await rest_client.webrtc.forward_whep_sdp_offer(
179183
camera,
180184
WebRTCSdpOffer("v=0..."),
181185
)
182186
assert resp == snapshot
187+
188+
189+
@pytest.mark.parametrize(
190+
("height", "width", "additional_params"),
191+
[
192+
(None, None, ""),
193+
(100, None, "&height=100"),
194+
(None, 200, "&width=200"),
195+
(100, 200, "&height=100&width=200"),
196+
],
197+
ids=[
198+
"No height and no width",
199+
"Only height",
200+
"Only width",
201+
"Height and width",
202+
],
203+
)
204+
async def test_get_jpeg_snapshot(
205+
responses: aioresponses,
206+
rest_client: Go2RtcRestClient,
207+
height: int | None,
208+
width: int | None,
209+
additional_params: str,
210+
) -> None:
211+
"""Test getting a jpeg snapshot."""
212+
camera = "camera.12mp_fluent"
213+
image_bytes = load_fixture_bytes("snapshot.jpg")
214+
responses.get(
215+
f"{URL}{_API_PREFIX}/frame.jpeg?src={camera}{additional_params}",
216+
status=200,
217+
body=image_bytes,
218+
)
219+
resp = await rest_client.get_jpeg_snapshot(camera, width, height)
220+
assert isinstance(resp, bytes)
221+
222+
assert resp == image_bytes

0 commit comments

Comments
 (0)