reactor-sdk 0.1.0__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,26 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Set up Python
16
+ uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.12"
19
+
20
+ - name: Install dependencies
21
+ run: |
22
+ python -m pip install --upgrade pip
23
+ pip install build
24
+
25
+ - name: Build package
26
+ run: python -m build
@@ -0,0 +1,31 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ id-token: write
9
+ contents: read
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-latest
14
+ environment: pypi
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.12"
23
+
24
+ - name: Build package
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install build
28
+ python -m build
29
+
30
+ - name: Publish to PyPI
31
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,131 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # PyInstaller
28
+ *.manifest
29
+ *.spec
30
+
31
+ # Installer logs
32
+ pip-log.txt
33
+ pip-delete-this-directory.txt
34
+
35
+ # Unit test / coverage reports
36
+ htmlcov/
37
+ .tox/
38
+ .nox/
39
+ .coverage
40
+ .coverage.*
41
+ .cache
42
+ nosetests.xml
43
+ coverage.xml
44
+ *.cover
45
+ *.py,cover
46
+ .hypothesis/
47
+ .pytest_cache/
48
+ pytest_cache/
49
+
50
+ # Translations
51
+ *.mo
52
+ *.pot
53
+
54
+ # Django stuff:
55
+ *.log
56
+ local_settings.py
57
+
58
+ # Flask stuff:
59
+ instance/
60
+ .webassets-cache
61
+
62
+ # Scrapy stuff:
63
+ .scrapy
64
+
65
+ # Sphinx documentation
66
+ docs/_build/
67
+
68
+ # PyBuilder
69
+ target/
70
+
71
+ # Jupyter Notebook
72
+ .ipynb_checkpoints
73
+
74
+ # IPython
75
+ profile_default/
76
+ ipython_config.py
77
+
78
+ # pyenv
79
+ .python-version
80
+
81
+ # celery beat schedule file
82
+ celerybeat-schedule
83
+
84
+ # SageMath parsed files
85
+ *.sage.py
86
+
87
+ # Environments
88
+ .env
89
+ .venv
90
+ env/
91
+ venv/
92
+ ENV/
93
+ env.bak/
94
+ venv.bak/
95
+
96
+ # Spyder project settings
97
+ .spyderproject
98
+ .spyproject
99
+
100
+ # Rope project settings
101
+ .ropeproject
102
+
103
+ # mkdocs documentation
104
+ /site
105
+
106
+ # mypy
107
+ .mypy_cache/
108
+ .dmypy.json
109
+ dmypy.json
110
+
111
+ # Pyre type checker
112
+ .pyre/
113
+
114
+ # pytype static type analyzer
115
+ .pytype/
116
+
117
+ # Cython debug symbols
118
+ cython_debug/
119
+
120
+ # IDE
121
+ .idea/
122
+ .vscode/
123
+ *.swp
124
+ *.swo
125
+
126
+ # OS
127
+ .DS_Store
128
+ Thumbs.db
129
+
130
+ # Project specific
131
+ *.log
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Reactor Technologies, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.4
2
+ Name: reactor-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Reactor - Real-time AI video streaming
5
+ Project-URL: Homepage, https://reactor.inc
6
+ Project-URL: Documentation, https://docs.reactor.inc
7
+ Project-URL: Repository, https://github.com/reactor-team/py-sdk
8
+ Author-email: Reactor Technologies <support@reactor.inc>
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Multimedia :: Video
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: aiohttp>=3.9.0
21
+ Requires-Dist: aiortc>=1.9.0
22
+ Requires-Dist: av>=12.0.0
23
+ Requires-Dist: numpy>=1.24.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
26
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
27
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
28
+ Requires-Dist: ruff>=0.3.0; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Reactor Python SDK
32
+
33
+ [![PyPI version](https://img.shields.io/pypi/v/reactor-sdk)](https://pypi.org/project/reactor-sdk/)
34
+ [![PyPI downloads](https://img.shields.io/pypi/dm/reactor-sdk)](https://pypi.org/project/reactor-sdk/)
35
+ [![build](https://img.shields.io/github/actions/workflow/status/reactor-team/py-sdk/ci.yml?branch=main)](https://github.com/reactor-team/py-sdk/actions)
36
+ [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
37
+
38
+ Python SDK for Reactor - Real-time AI video streaming platform.
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ pip install reactor-sdk
44
+ ```
45
+
46
+ ## Quick Start
47
+
48
+ ```python
49
+ import asyncio
50
+ from reactor_sdk import Reactor, ReactorStatus
51
+
52
+ async def main():
53
+ # Create a Reactor instance with your API key
54
+ reactor = Reactor(
55
+ model_name="my-model",
56
+ api_key="REACTOR_API_KEY", # SDK automatically fetches JWT token
57
+ )
58
+
59
+ # Use decorators for clean event handling
60
+ @reactor.on_frame
61
+ def handle_frame(frame):
62
+ print(f"Received frame: {frame.shape}")
63
+
64
+ @reactor.on_message
65
+ def handle_message(msg):
66
+ print(f"Message: {msg}")
67
+
68
+ @reactor.on_status(ReactorStatus.READY)
69
+ def handle_ready(status):
70
+ print("Connected and ready!")
71
+
72
+ @reactor.on_error
73
+ def handle_error(error):
74
+ print(f"Error: {error}")
75
+
76
+ # Connect to the model (JWT token is fetched automatically)
77
+ await reactor.connect()
78
+
79
+ # Send commands
80
+ await reactor.send_command("setParameter", {"value": 0.5})
81
+
82
+ # Keep running
83
+ try:
84
+ while reactor.get_status() == ReactorStatus.READY:
85
+ await asyncio.sleep(0.1)
86
+ finally:
87
+ await reactor.disconnect()
88
+
89
+ if __name__ == "__main__":
90
+ asyncio.run(main())
91
+ ```
92
+
93
+ ## Features
94
+
95
+ - **WebRTC video streaming** via aiortc
96
+ - **Event-driven API** matching the JavaScript SDK
97
+ - **Frame callbacks** for single-frame access
98
+ - **Video input** support for sending video to models
99
+ - **Local development** mode for testing
100
+ - **Full type hints** for IDE support
101
+
102
+ ## API Reference
103
+
104
+ ### Reactor
105
+
106
+ The main class for connecting to Reactor models.
107
+
108
+ ```python
109
+ from reactor_sdk import Reactor
110
+
111
+ # Production usage with API key
112
+ reactor = Reactor(
113
+ model_name="my-model",
114
+ api_key="REACTOR_API_KEY", # SDK fetches JWT automatically
115
+ )
116
+
117
+ # Local development (no API key needed)
118
+ reactor = Reactor(
119
+ model_name="my-model",
120
+ local=True,
121
+ )
122
+ ```
123
+
124
+ The `Reactor` type can also be used for type annotations:
125
+
126
+ ```python
127
+ from reactor_sdk import Reactor
128
+
129
+ def process_reactor(reactor: Reactor) -> None:
130
+ # reactor has full type hints for all methods
131
+ pass
132
+ ```
133
+
134
+ #### Methods
135
+
136
+ - `await reactor.connect()` - Connect to the model (fetches JWT automatically if API key provided)
137
+ - `await reactor.disconnect(recoverable: bool = False)` - Disconnect
138
+ - `await reactor.reconnect()` - Reconnect to existing session
139
+ - `await reactor.send_command(command: str, data: dict)` - Send a command
140
+ - `await reactor.publish_track(track: MediaStreamTrack)` - Send video to model
141
+ - `await reactor.unpublish_track()` - Stop sending video
142
+ - `reactor.get_status()` - Get current status
143
+ - `reactor.get_session_id()` - Get session ID
144
+ - `reactor.set_frame_callback(callback)` - Set frame callback
145
+
146
+ #### Decorators
147
+
148
+ Use decorators for clean event handling:
149
+
150
+ ```python
151
+ @reactor.on_frame
152
+ def handle_frame(frame):
153
+ """Called for each video frame (numpy array H,W,3)."""
154
+ pass
155
+
156
+ @reactor.on_message
157
+ def handle_message(message):
158
+ """Called for each message from the model."""
159
+ pass
160
+
161
+ @reactor.on_status
162
+ def handle_any_status(status):
163
+ """Called for all status changes."""
164
+ pass
165
+
166
+ @reactor.on_status(ReactorStatus.READY)
167
+ def handle_ready(status):
168
+ """Called only when status becomes READY."""
169
+ pass
170
+
171
+ @reactor.on_status([ReactorStatus.READY, ReactorStatus.CONNECTING])
172
+ def handle_active(status):
173
+ """Called when status is READY or CONNECTING."""
174
+ pass
175
+
176
+ @reactor.on_error
177
+ def handle_error(error):
178
+ """Called when an error occurs."""
179
+ pass
180
+
181
+ @reactor.on_stream
182
+ def handle_stream(track):
183
+ """Called when video stream/track changes."""
184
+ pass
185
+ ```
186
+
187
+ #### Events (alternative to decorators)
188
+
189
+ - `status_changed` - Status changed (disconnected, connecting, ready)
190
+ - `session_id_changed` - Session ID changed
191
+ - `new_message` - Message received from model
192
+ - `stream_changed` - Video stream changed
193
+ - `error` - Error occurred
194
+
195
+ ## Examples
196
+
197
+ See the `examples/` directory for complete examples:
198
+
199
+ - `pygame_app/` - Pygame application with dynamic UI controls
200
+ - `rtmp_app/` - Stream Reactor video to RTMP servers (Twitch, YouTube, etc.)
201
+
202
+ ## License
203
+
204
+ MIT License - Copyright (c) 2025 Reactor Technologies, Inc.
@@ -0,0 +1,174 @@
1
+ # Reactor Python SDK
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/reactor-sdk)](https://pypi.org/project/reactor-sdk/)
4
+ [![PyPI downloads](https://img.shields.io/pypi/dm/reactor-sdk)](https://pypi.org/project/reactor-sdk/)
5
+ [![build](https://img.shields.io/github/actions/workflow/status/reactor-team/py-sdk/ci.yml?branch=main)](https://github.com/reactor-team/py-sdk/actions)
6
+ [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
7
+
8
+ Python SDK for Reactor - Real-time AI video streaming platform.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ pip install reactor-sdk
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```python
19
+ import asyncio
20
+ from reactor_sdk import Reactor, ReactorStatus
21
+
22
+ async def main():
23
+ # Create a Reactor instance with your API key
24
+ reactor = Reactor(
25
+ model_name="my-model",
26
+ api_key="REACTOR_API_KEY", # SDK automatically fetches JWT token
27
+ )
28
+
29
+ # Use decorators for clean event handling
30
+ @reactor.on_frame
31
+ def handle_frame(frame):
32
+ print(f"Received frame: {frame.shape}")
33
+
34
+ @reactor.on_message
35
+ def handle_message(msg):
36
+ print(f"Message: {msg}")
37
+
38
+ @reactor.on_status(ReactorStatus.READY)
39
+ def handle_ready(status):
40
+ print("Connected and ready!")
41
+
42
+ @reactor.on_error
43
+ def handle_error(error):
44
+ print(f"Error: {error}")
45
+
46
+ # Connect to the model (JWT token is fetched automatically)
47
+ await reactor.connect()
48
+
49
+ # Send commands
50
+ await reactor.send_command("setParameter", {"value": 0.5})
51
+
52
+ # Keep running
53
+ try:
54
+ while reactor.get_status() == ReactorStatus.READY:
55
+ await asyncio.sleep(0.1)
56
+ finally:
57
+ await reactor.disconnect()
58
+
59
+ if __name__ == "__main__":
60
+ asyncio.run(main())
61
+ ```
62
+
63
+ ## Features
64
+
65
+ - **WebRTC video streaming** via aiortc
66
+ - **Event-driven API** matching the JavaScript SDK
67
+ - **Frame callbacks** for single-frame access
68
+ - **Video input** support for sending video to models
69
+ - **Local development** mode for testing
70
+ - **Full type hints** for IDE support
71
+
72
+ ## API Reference
73
+
74
+ ### Reactor
75
+
76
+ The main class for connecting to Reactor models.
77
+
78
+ ```python
79
+ from reactor_sdk import Reactor
80
+
81
+ # Production usage with API key
82
+ reactor = Reactor(
83
+ model_name="my-model",
84
+ api_key="REACTOR_API_KEY", # SDK fetches JWT automatically
85
+ )
86
+
87
+ # Local development (no API key needed)
88
+ reactor = Reactor(
89
+ model_name="my-model",
90
+ local=True,
91
+ )
92
+ ```
93
+
94
+ The `Reactor` type can also be used for type annotations:
95
+
96
+ ```python
97
+ from reactor_sdk import Reactor
98
+
99
+ def process_reactor(reactor: Reactor) -> None:
100
+ # reactor has full type hints for all methods
101
+ pass
102
+ ```
103
+
104
+ #### Methods
105
+
106
+ - `await reactor.connect()` - Connect to the model (fetches JWT automatically if API key provided)
107
+ - `await reactor.disconnect(recoverable: bool = False)` - Disconnect
108
+ - `await reactor.reconnect()` - Reconnect to existing session
109
+ - `await reactor.send_command(command: str, data: dict)` - Send a command
110
+ - `await reactor.publish_track(track: MediaStreamTrack)` - Send video to model
111
+ - `await reactor.unpublish_track()` - Stop sending video
112
+ - `reactor.get_status()` - Get current status
113
+ - `reactor.get_session_id()` - Get session ID
114
+ - `reactor.set_frame_callback(callback)` - Set frame callback
115
+
116
+ #### Decorators
117
+
118
+ Use decorators for clean event handling:
119
+
120
+ ```python
121
+ @reactor.on_frame
122
+ def handle_frame(frame):
123
+ """Called for each video frame (numpy array H,W,3)."""
124
+ pass
125
+
126
+ @reactor.on_message
127
+ def handle_message(message):
128
+ """Called for each message from the model."""
129
+ pass
130
+
131
+ @reactor.on_status
132
+ def handle_any_status(status):
133
+ """Called for all status changes."""
134
+ pass
135
+
136
+ @reactor.on_status(ReactorStatus.READY)
137
+ def handle_ready(status):
138
+ """Called only when status becomes READY."""
139
+ pass
140
+
141
+ @reactor.on_status([ReactorStatus.READY, ReactorStatus.CONNECTING])
142
+ def handle_active(status):
143
+ """Called when status is READY or CONNECTING."""
144
+ pass
145
+
146
+ @reactor.on_error
147
+ def handle_error(error):
148
+ """Called when an error occurs."""
149
+ pass
150
+
151
+ @reactor.on_stream
152
+ def handle_stream(track):
153
+ """Called when video stream/track changes."""
154
+ pass
155
+ ```
156
+
157
+ #### Events (alternative to decorators)
158
+
159
+ - `status_changed` - Status changed (disconnected, connecting, ready)
160
+ - `session_id_changed` - Session ID changed
161
+ - `new_message` - Message received from model
162
+ - `stream_changed` - Video stream changed
163
+ - `error` - Error occurred
164
+
165
+ ## Examples
166
+
167
+ See the `examples/` directory for complete examples:
168
+
169
+ - `pygame_app/` - Pygame application with dynamic UI controls
170
+ - `rtmp_app/` - Stream Reactor video to RTMP servers (Twitch, YouTube, etc.)
171
+
172
+ ## License
173
+
174
+ MIT License - Copyright (c) 2025 Reactor Technologies, Inc.
@@ -0,0 +1,126 @@
1
+ # Pygame Example Application
2
+
3
+ A pygame-based application demonstrating the Reactor Python SDK with real-time video streaming and dynamic UI controls.
4
+
5
+ ## Features
6
+
7
+ - Real-time video stream display from Reactor models
8
+ - Dynamic controller UI that builds controls based on model capabilities
9
+ - Support for sliders, checkboxes, dropdowns, and text inputs
10
+ - Automatic command execution when adjusting slider values
11
+
12
+ ## Prerequisites
13
+
14
+ - Python 3.10 or higher
15
+ - A Reactor API key (get one at https://reactor.inc)
16
+
17
+ ## Installation
18
+
19
+ 1. Install the Reactor SDK (from the parent directory):
20
+
21
+ ```bash
22
+ cd /path/to/py-sdk
23
+ pip install -e .
24
+ ```
25
+
26
+ 2. Install pygame:
27
+
28
+ ```bash
29
+ pip install pygame
30
+ ```
31
+
32
+ Or install all dependencies:
33
+
34
+ ```bash
35
+ cd examples/pygame_app
36
+ pip install -r requirements.txt
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ### Local Development
42
+
43
+ Connect to a local Reactor model running at `localhost:8080`:
44
+
45
+ ```bash
46
+ python main.py --local
47
+ ```
48
+
49
+ ### Remote Connection
50
+
51
+ Connect to a remote Reactor model using your API key:
52
+
53
+ ```bash
54
+ python main.py --api-key REACTOR_API_KEY --model your-model-name
55
+ ```
56
+
57
+ ### Command Line Options
58
+
59
+ | Option | Short | Description |
60
+ |--------|-------|-------------|
61
+ | `--api-key` | `-k` | Reactor API key for authentication |
62
+ | `--model` | `-m` | Model name to connect to (default: `example-model`) |
63
+ | `--local` | `-l` | Connect to local coordinator at `localhost:8080` |
64
+ | `--coordinator-url` | `-c` | Custom coordinator URL |
65
+ | `--verbose` | `-v` | Enable verbose logging |
66
+
67
+ ### Examples
68
+
69
+ ```bash
70
+ # Local development
71
+ python main.py --local --model my-local-model
72
+
73
+ # Production with API key
74
+ python main.py -k sk_live_xxxxx -m production-model
75
+
76
+ # With verbose logging
77
+ python main.py --local -v
78
+
79
+ # Custom coordinator
80
+ python main.py -k REACTOR_API_KEY -m my-model -c https://custom-coordinator.example.com
81
+ ```
82
+
83
+ ## Controls
84
+
85
+ - **ESC**: Quit the application
86
+ - **Mouse Click**: Interact with controller UI elements
87
+ - **Mouse Scroll**: Scroll the controller panel
88
+
89
+ ## UI Layout
90
+
91
+ ```
92
+ ┌─────────────────────────────────┬──────────────────┐
93
+ │ │ │
94
+ │ │ Reactor │
95
+ │ Video Stream │ Commands │
96
+ │ (960 x 720) │ │
97
+ │ │ [Dynamic UI │
98
+ │ │ controls │
99
+ │ │ based on │
100
+ │ │ model caps] │
101
+ │ │ │
102
+ └─────────────────────────────────┴──────────────────┘
103
+ ```
104
+
105
+ ## How It Works
106
+
107
+ 1. **Connection**: The app connects to the Reactor coordinator, which assigns a GPU machine
108
+ 2. **Capabilities**: Once connected, it requests the model's capabilities schema
109
+ 3. **Dynamic UI**: The controller parses the schema and builds appropriate UI controls
110
+ 4. **Commands**: User interactions trigger commands sent to the model via WebRTC data channel
111
+ 5. **Video**: The model's video output is streamed back and displayed in real-time
112
+
113
+ ## Troubleshooting
114
+
115
+ ### "No API key provided" error
116
+ Make sure to provide either `--api-key` or `--local` flag.
117
+
118
+ ### Video not displaying
119
+ - Check that the model is running and producing output
120
+ - Verify the connection status indicator (green = connected)
121
+ - Enable verbose logging with `-v` to see detailed connection info
122
+
123
+ ### Controller not showing commands
124
+ - Wait a few seconds after connection for capabilities to be received
125
+ - The app automatically retries requesting capabilities every 5 seconds
126
+ - Check verbose logs for any errors in the capabilities response