Skip to content

Commit 13be4ee

Browse files
authored
Python SDK: Add Stream Feature Abstraction (#752)
1 parent b53a2b2 commit 13be4ee

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1235
-522
lines changed

demos/python/sdk_wireless_camera_control/docs/api.rst

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,17 @@ These should not be imported directly and instead should be accessed using the r
7676
Abstracted Features
7777
-------------------
7878

79-
.. automodule:: open_gopro.features.cohn_feature
79+
.. autoclass:: open_gopro.features.CohnFeature
8080

81-
.. automodule:: open_gopro.features.access_point_feature
81+
.. autoclass:: open_gopro.features.AccessPointFeature
82+
83+
.. autoclass:: open_gopro.features.StreamFeature
8284

8385
Base Types
8486
----------
8587

86-
.. automodule:: open_gopro.domain.types
88+
.. automodule:: open_gopro.models.types
89+
:undoc-members:
8790

8891
GoPro Enum
8992
^^^^^^^^^^
@@ -183,36 +186,14 @@ These are the various models that are returned in responses, used in commands, e
183186
184187
from open_gopro import models
185188
186-
.. autopydantic_model:: open_gopro.models.media_list.MediaPath
187-
188-
.. autopydantic_model:: open_gopro.models.media_list.MediaMetadata
189-
190-
.. autopydantic_model:: open_gopro.models.media_list.PhotoMetadata
191-
:show-inheritance:
192-
193-
.. autopydantic_model:: open_gopro.models.media_list.VideoMetadata
194-
:show-inheritance:
195-
196-
.. autopydantic_model:: open_gopro.models.media_list.MediaItem
197-
198-
.. autopydantic_model:: open_gopro.models.media_list.GroupedMediaItem
199-
:show-inheritance:
200-
201-
.. autopydantic_model:: open_gopro.models.media_list.MediaFileSystem
202-
203-
.. autopydantic_model:: open_gopro.models.media_list.MediaList
204-
205-
.. autopydantic_model:: open_gopro.models.general.TzDstDateTime
206-
207-
.. autopydantic_model:: open_gopro.models.general.CameraInfo
208-
209-
.. autopydantic_model:: open_gopro.models.general.WebcamResponse
210-
211-
.. autopydantic_model:: open_gopro.models.general.SupportedOption
189+
.. automodule:: open_gopro.models.media_list
190+
:undoc-members:
212191

213-
.. autopydantic_model:: open_gopro.models.general.CohnInfo
192+
.. automodule:: open_gopro.models.streaming
193+
:undoc-members:
214194

215-
.. autoclass:: open_gopro.models.general.ScheduledCapture
195+
.. automodule:: open_gopro.models.general
196+
:undoc-members:
216197

217198
Constants
218199
=========

demos/python/sdk_wireless_camera_control/docs/conf.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,14 @@ def is_on(self) -> bool:
8585
nitpicky = True
8686

8787
TYPE_ALIASES = {
88-
"CameraState": "open_gopro.domain.types.CameraState",
89-
"UpdateCb": "open_gopro.domain.types.UpdateCb",
90-
"UpdateType": "open_gopro.domain.types.UpdateType",
88+
"CameraState": "open_gopro.models.types.CameraState",
89+
"UpdateCb": "open_gopro.models.types.UpdateCb",
90+
"UpdateType": "open_gopro.models.types.UpdateType",
9191
"JsonDict": "open_gopro.JsonDict",
92-
"ResponseType": "open_gopro.domain.types.ResponseType",
93-
"Protobuf": "open_gopro.domain.types.Protobuf",
94-
"IdType": "open_gopro.domain.types.IdType",
92+
"ResponseType": "open_gopro.models.types.ResponseType",
93+
"Protobuf": "open_gopro.models.types.Protobuf",
94+
"IdType": "open_gopro.models.types.IdType",
95+
"StreamOptions": "open_gopro.models.types.StreamOptions",
9596
"SyncAction": "open_gopro.observable.SyncAction",
9697
"AsyncAction": "open_gopro.observable.AsyncAction",
9798
"SyncFilter": "open_gopro.observable.SyncFilter",

demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
)
4141
from open_gopro.domain.gopro_observable import GoProObservable
4242
from open_gopro.domain.parser_interface import GlobalParsers, Parser
43-
from open_gopro.domain.types import CameraState
4443
from open_gopro.models import CameraInfo, GoProResp, TzDstDateTime, constants, proto
4544
from open_gopro.models.constants import (
4645
ActionId,
@@ -50,6 +49,7 @@
5049
SettingId,
5150
StatusId,
5251
)
52+
from open_gopro.models.types import CameraState
5353
from open_gopro.parsers.bytes import (
5454
ConstructByteParserBuilder,
5555
DateTimeByteParserBuilder,

demos/python/sdk_wireless_camera_control/open_gopro/api/builders.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
GlobalParsers,
3535
Parser,
3636
)
37-
from open_gopro.domain.types import CameraState, JsonDict, Protobuf
3837
from open_gopro.models import GoProResp
3938
from open_gopro.models.constants import (
4039
ActionId,
@@ -45,6 +44,7 @@
4544
SettingId,
4645
StatusId,
4746
)
47+
from open_gopro.models.types import CameraState, JsonDict, Protobuf
4848
from open_gopro.network.ble import BleUUID
4949
from open_gopro.parsers.bytes import (
5050
ConstructByteParserBuilder,

demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@
2222
MessageRules,
2323
)
2424
from open_gopro.domain.parser_interface import Parser
25-
from open_gopro.domain.types import CameraState, JsonDict
2625
from open_gopro.models import (
2726
CameraInfo,
2827
GoProResp,
2928
MediaList,
3029
MediaMetadata,
3130
MediaPath,
32-
WebcamResponse,
3331
constants,
3432
proto,
33+
streaming,
3534
)
35+
from open_gopro.models.streaming import WebcamResponse
36+
from open_gopro.models.types import CameraState, JsonDict
3637
from open_gopro.parsers.json import (
3738
CameraStateJsonParser,
3839
LambdaJsonParser,
@@ -424,18 +425,18 @@ async def webcam_preview(self) -> GoProResp[WebcamResponse]:
424425
async def webcam_start(
425426
self,
426427
*,
427-
resolution: constants.WebcamResolution | None = None,
428-
fov: constants.WebcamFOV | None = None,
428+
resolution: streaming.WebcamResolution | None = None,
429+
fov: streaming.WebcamFOV | None = None,
429430
port: int | None = None,
430-
protocol: constants.WebcamProtocol | None = None,
431+
protocol: streaming.WebcamProtocol | None = None,
431432
) -> GoProResp[WebcamResponse]:
432433
"""Start the webcam.
433434
434435
Args:
435-
resolution (constants.WebcamResolution | None): resolution to use. If not set, camera default will be used.
436-
fov (constants.WebcamFOV | None): field of view to use. If not set, camera default will be used.
436+
resolution (streaming.WebcamResolution | None): resolution to use. If not set, camera default will be used.
437+
fov (streaming.WebcamFOV | None): field of view to use. If not set, camera default will be used.
437438
port (int | None): port to use for streaming. If not set, camera default of 8554 will be used.
438-
protocol (constants.WebcamProtocol | None): streaming protocol to use. If not set, camera default of TS will
439+
protocol (streaming.WebcamProtocol | None): streaming protocol to use. If not set, camera default of TS will
439440
be used.
440441
441442
Returns:

demos/python/sdk_wireless_camera_control/open_gopro/demos/gui/livestream.py

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55

66
import argparse
77
import asyncio
8-
from typing import Any
98

109
from rich.console import Console
1110

1211
from open_gopro import WirelessGoPro
13-
from open_gopro.models import constants, proto
12+
from open_gopro.models import proto, streaming
1413
from open_gopro.util import add_cli_args_and_parse, ainput
1514
from open_gopro.util.logger import setup_logging
1615

@@ -20,48 +19,36 @@
2019
async def main(args: argparse.Namespace) -> None:
2120
setup_logging(__name__, args.log)
2221

23-
async with WirelessGoPro(args.identifier, enable_wifi=False) as gopro:
24-
await gopro.ble_command.set_shutter(shutter=constants.Toggle.DISABLE)
25-
await gopro.ble_command.register_livestream_status(
26-
register=[proto.EnumRegisterLiveStreamStatus.REGISTER_LIVE_STREAM_STATUS_STATUS]
27-
)
28-
22+
async with WirelessGoPro(
23+
args.identifier,
24+
enable_wifi=False,
25+
interfaces={WirelessGoPro.Interface.BLE},
26+
) as gopro:
2927
console.print(f"[yellow]Connecting to {args.ssid}...")
3028
await gopro.access_point.connect(args.ssid, args.password)
3129

32-
# Start livestream
33-
livestream_is_ready = asyncio.Event()
34-
35-
async def wait_for_livestream_start(_: Any, update: proto.NotifyLiveStreamStatus) -> None:
36-
if update.live_stream_status == proto.EnumLiveStreamStatus.LIVE_STREAM_STATE_READY:
37-
livestream_is_ready.set()
38-
39-
console.print("[yellow]Configuring livestream...")
40-
gopro.register_update(wait_for_livestream_start, constants.ActionId.LIVESTREAM_STATUS_NOTIF)
41-
await gopro.ble_command.set_livestream_mode(
42-
url=args.url,
43-
window_size=args.resolution,
44-
minimum_bitrate=args.min_bit,
45-
maximum_bitrate=args.max_bit,
46-
starting_bitrate=args.start_bit,
47-
encode=args.encode,
48-
lens=args.fov,
30+
console.print(f"[yellow]Starting livestream to {args.url}...")
31+
await gopro.streaming.start_stream(
32+
streaming.StreamType.LIVE,
33+
streaming.LivestreamOptions(
34+
url=args.url,
35+
minimum_bitrate=args.min_bit,
36+
maximum_bitrate=args.max_bit,
37+
starting_bitrate=args.start_bit,
38+
resolution=args.resolution if args.resolution else None,
39+
fov=args.fov if args.fov else None,
40+
encode=args.encode,
41+
),
42+
)
43+
assert gopro.streaming.url
44+
console.print(
45+
f"[yellow]Livestream to {gopro.streaming.url} is now streaming and should be available for viewing at."
4946
)
50-
51-
# Wait to receive livestream started status
52-
console.print("[yellow]Waiting for livestream to be ready...\n")
53-
await livestream_is_ready.wait()
54-
55-
# TODO Is this still needed?
56-
await asyncio.sleep(2)
57-
58-
console.print("[yellow]Starting livestream")
59-
assert (await gopro.ble_command.set_shutter(shutter=constants.Toggle.ENABLE)).ok
60-
61-
console.print("[yellow]Livestream is now streaming and should be available for viewing.")
6247
await ainput("Press enter to stop livestreaming...\n")
6348

64-
await gopro.ble_command.set_shutter(shutter=constants.Toggle.DISABLE)
49+
await gopro.streaming.stop_active_stream()
50+
51+
# TODO merge this into access point feature
6552
await gopro.ble_command.release_network()
6653

6754

demos/python/sdk_wireless_camera_control/open_gopro/demos/gui/preview_stream.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
from rich.console import Console
1010

1111
from open_gopro import WirelessGoPro
12-
from open_gopro.demos.gui.util import display_video_blocking
13-
from open_gopro.models import constants
12+
from open_gopro.demos.gui.video_display import BufferlessVideoCapture
13+
from open_gopro.models import streaming
1414
from open_gopro.util import add_cli_args_and_parse
1515
from open_gopro.util.logger import setup_logging
1616

@@ -21,14 +21,22 @@ async def main(args: argparse.Namespace) -> None:
2121
setup_logging(__name__, args.log)
2222

2323
async with WirelessGoPro(args.identifier) as gopro:
24-
await gopro.http_command.set_preview_stream(mode=constants.Toggle.DISABLE)
25-
await gopro.ble_command.set_shutter(shutter=constants.Toggle.DISABLE)
26-
assert (await gopro.http_command.set_preview_stream(mode=constants.Toggle.ENABLE, port=args.port)).ok
24+
console.print("Starting preview stream...")
25+
await gopro.streaming.start_stream(
26+
streaming.StreamType.PREVIEW,
27+
streaming.PreviewStreamOptions(port=args.port),
28+
)
2729

2830
console.print("Displaying the preview stream...")
29-
display_video_blocking(f"udp://127.0.0.1:{args.port}", printer=console.print)
30-
31-
await gopro.http_command.set_preview_stream(mode=constants.Toggle.DISABLE)
31+
assert gopro.streaming.url
32+
BufferlessVideoCapture(
33+
source=gopro.streaming.url,
34+
protocol=BufferlessVideoCapture.Protocol.TS,
35+
printer=console.print,
36+
).display_blocking()
37+
38+
console.print("Stopping preview stream...")
39+
await gopro.streaming.stop_active_stream()
3240

3341

3442
def parse_arguments() -> argparse.Namespace:

demos/python/sdk_wireless_camera_control/open_gopro/demos/gui/util.py

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)