sora-sdk 2025.5.0.dev4__cp314-cp314-manylinux_2_31_aarch64.whl

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.

Potentially problematic release.


This version of sora-sdk might be problematic. Click here for more details.

@@ -0,0 +1,61 @@
1
+ from .sora_sdk_ext import * # noqa: F401,F403
2
+
3
+ # インストールされたパッケージの場合は importlib.metadata から取得
4
+ # 開発環境の場合は VERSION ファイルから取得
5
+ try:
6
+ from importlib.metadata import version, PackageNotFoundError
7
+
8
+ try:
9
+ __version__ = version("sora_sdk")
10
+ except PackageNotFoundError:
11
+ # パッケージがインストールされていない場合(開発環境)
12
+ import os
13
+
14
+ _version_file = os.path.join(
15
+ os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "VERSION"
16
+ )
17
+ if os.path.exists(_version_file):
18
+ with open(_version_file, "r") as f:
19
+ __version__ = f.read().strip()
20
+ else:
21
+ __version__ = "unknown"
22
+ except ImportError:
23
+ # Python 3.8 以前の互換性のため
24
+ __version__ = "unknown"
25
+
26
+ """
27
+ sink はそれぞれ track が必要で参照を保持する必要がある
28
+ しかしながら、 sink の C++ 側で shared_ptr として track を持つと、
29
+ リファレンスカウンタが正しく処理されず終了時にリークしてしまう。
30
+ そのため Python で Wrapper を作り、その中で保持することとした。
31
+ """
32
+
33
+
34
+ class SoraAudioSink(SoraAudioSinkImpl):
35
+ def __init__(self, track, output_frequency, output_channels):
36
+ super().__init__(track, output_frequency, output_channels)
37
+ self.__track = track
38
+
39
+ def __del__(self):
40
+ super().__del__()
41
+ del self.__track
42
+
43
+
44
+ class SoraAudioStreamSink(SoraAudioStreamSinkImpl):
45
+ def __init__(self, track, output_frequency, output_channels):
46
+ super().__init__(track, output_frequency, output_channels)
47
+ self.__track = track
48
+
49
+ def __del__(self):
50
+ super().__del__()
51
+ del self.__track
52
+
53
+
54
+ class SoraVideoSink(SoraVideoSinkImpl):
55
+ def __init__(self, track):
56
+ super().__init__(track)
57
+ self.__track = track
58
+
59
+ def __del__(self):
60
+ super().__del__()
61
+ del self.__track
File without changes
@@ -0,0 +1,503 @@
1
+ from collections.abc import Callable, Sequence
2
+ import enum
3
+ from typing import Annotated, overload
4
+
5
+ import numpy
6
+ from numpy.typing import NDArray
7
+
8
+
9
+ class SoraSignalingErrorCode(enum.IntEnum):
10
+ CLOSE_SUCCEEDED = 0
11
+
12
+ CLOSE_FAILED = 1
13
+
14
+ INTERNAL_ERROR = 2
15
+
16
+ INVALID_PARAMETER = 3
17
+
18
+ WEBSOCKET_HANDSHAKE_FAILED = 4
19
+
20
+ WEBSOCKET_ONCLOSE = 5
21
+
22
+ WEBSOCKET_ONERROR = 6
23
+
24
+ PEER_CONNECTION_STATE_FAILED = 7
25
+
26
+ ICE_FAILED = 8
27
+
28
+ class SoraSignalingType(enum.IntEnum):
29
+ WEBSOCKET = 0
30
+
31
+ DATACHANNEL = 1
32
+
33
+ class SoraDegradationPreference(enum.IntEnum):
34
+ DISABLED = 0
35
+
36
+ BALANCED = 3
37
+
38
+ MAINTAIN_FRAMERATE = 1
39
+
40
+ MAINTAIN_RESOLUTION = 2
41
+
42
+ class SoraSignalingDirection(enum.IntEnum):
43
+ SENT = 0
44
+
45
+ RECEIVED = 1
46
+
47
+ class SoraTrackState(enum.IntEnum):
48
+ LIVE = 0
49
+
50
+ ENDED = 1
51
+
52
+ class SoraLoggingSeverity(enum.IntEnum):
53
+ VERBOSE = 0
54
+
55
+ INFO = 1
56
+
57
+ WARNING = 2
58
+
59
+ ERROR = 3
60
+
61
+ NONE = 4
62
+
63
+ def enable_libwebrtc_log(arg: SoraLoggingSeverity, /) -> None: ...
64
+
65
+ def rtc_log(arg0: SoraLoggingSeverity, arg1: str, /) -> None: ...
66
+
67
+ class SoraTrackInterface:
68
+ @property
69
+ def kind(self) -> str: ...
70
+
71
+ @property
72
+ def id(self) -> str: ...
73
+
74
+ @property
75
+ def enabled(self) -> bool: ...
76
+
77
+ @property
78
+ def state(self) -> SoraTrackState: ...
79
+
80
+ def set_enabled(self, enable: bool) -> bool: ...
81
+
82
+ class SoraMediaTrack(SoraTrackInterface):
83
+ @property
84
+ def stream_id(self) -> str: ...
85
+
86
+ def set_frame_transformer(self, arg: SoraFrameTransformer, /) -> None: ...
87
+
88
+ class SoraAudioSource(SoraTrackInterface):
89
+ @overload
90
+ def on_data(self, data: int, samples_per_channel: int, timestamp: float) -> None: ...
91
+
92
+ @overload
93
+ def on_data(self, data: int, samples_per_channel: int) -> None: ...
94
+
95
+ @overload
96
+ def on_data(self, ndarray: Annotated[NDArray[numpy.int16], dict(shape=(None, None), order='C', device='cpu')], timestamp: float) -> None: ...
97
+
98
+ @overload
99
+ def on_data(self, ndarray: Annotated[NDArray[numpy.int16], dict(shape=(None, None), order='C', device='cpu')]) -> None: ...
100
+
101
+ class SoraVideoSource(SoraTrackInterface):
102
+ @overload
103
+ def on_captured(self, ndarray: Annotated[NDArray[numpy.uint8], dict(shape=(None, None, 3), order='C', device='cpu')]) -> None: ...
104
+
105
+ @overload
106
+ def on_captured(self, ndarray: Annotated[NDArray[numpy.uint8], dict(shape=(None, None, 3), order='C', device='cpu')], timestamp: float) -> None: ...
107
+
108
+ @overload
109
+ def on_captured(self, ndarray: Annotated[NDArray[numpy.uint8], dict(shape=(None, None, 3), order='C', device='cpu')], timestamp_us: int) -> None: ...
110
+
111
+ class SoraAudioSinkImpl:
112
+ def __init__(self, track: SoraTrackInterface, output_frequency: int = -1, output_channels: int = 0) -> None: ...
113
+
114
+ def __del__(self) -> None: ...
115
+
116
+ def read(self, frames: int = 0, timeout: float = 1) -> tuple: ...
117
+
118
+ @property
119
+ def on_data(self) -> Callable[[Annotated[NDArray[numpy.int16], dict(shape=(None, None))]], None]: ...
120
+
121
+ @on_data.setter
122
+ def on_data(self, arg: Callable[[Annotated[NDArray[numpy.int16], dict(shape=(None, None))]], None], /) -> None: ...
123
+
124
+ @property
125
+ def on_format(self) -> Callable[[int, int], None]: ...
126
+
127
+ @on_format.setter
128
+ def on_format(self, arg: Callable[[int, int], None], /) -> None: ...
129
+
130
+ class SoraAudioFrame:
131
+ def __getstate__(self) -> tuple[list[int], int, int, int, int | None]: ...
132
+
133
+ def __setstate__(self, arg: tuple[Sequence[int], int, int, int, int | None], /) -> None: ...
134
+
135
+ @property
136
+ def samples_per_channel(self) -> int: ...
137
+
138
+ @property
139
+ def num_channels(self) -> int: ...
140
+
141
+ @property
142
+ def sample_rate_hz(self) -> int: ...
143
+
144
+ @property
145
+ def absolute_capture_timestamp_ms(self) -> int | None: ...
146
+
147
+ def data(self) -> Annotated[NDArray[numpy.int16], dict(shape=(None, None))]: ...
148
+
149
+ class SoraAudioStreamSinkImpl:
150
+ def __init__(self, track: SoraTrackInterface, output_frequency: int = -1, output_channels: int = 0) -> None: ...
151
+
152
+ def __del__(self) -> None: ...
153
+
154
+ @property
155
+ def on_frame(self) -> Callable[[SoraAudioFrame], None]: ...
156
+
157
+ @on_frame.setter
158
+ def on_frame(self, arg: Callable[[SoraAudioFrame], None], /) -> None: ...
159
+
160
+ class SoraVAD:
161
+ def __init__(self) -> None: ...
162
+
163
+ def analyze(self, frame: SoraAudioFrame) -> float: ...
164
+
165
+ class SoraVideoFrame:
166
+ def data(self) -> Annotated[NDArray[numpy.uint8], dict(shape=(None, None, 3))]: ...
167
+
168
+ class SoraVideoSinkImpl:
169
+ def __init__(self, arg: SoraTrackInterface, /) -> None: ...
170
+
171
+ def __del__(self) -> None: ...
172
+
173
+ @property
174
+ def on_frame(self) -> Callable[[SoraVideoFrame], None]: ...
175
+
176
+ @on_frame.setter
177
+ def on_frame(self, arg: Callable[[SoraVideoFrame], None], /) -> None: ...
178
+
179
+ class SoraConnection:
180
+ def connect(self) -> None: ...
181
+
182
+ def disconnect(self) -> None: ...
183
+
184
+ def send_data_channel(self, label: str, data: bytes) -> bool: ...
185
+
186
+ def get_stats(self) -> str: ...
187
+
188
+ @property
189
+ def on_set_offer(self) -> Callable[[str], None]: ...
190
+
191
+ @on_set_offer.setter
192
+ def on_set_offer(self, arg: Callable[[str], None], /) -> None: ...
193
+
194
+ @property
195
+ def on_ws_close(self) -> Callable[[int, str], None]: ...
196
+
197
+ @on_ws_close.setter
198
+ def on_ws_close(self, arg: Callable[[int, str], None], /) -> None: ...
199
+
200
+ @property
201
+ def on_disconnect(self) -> Callable[[SoraSignalingErrorCode, str], None]: ...
202
+
203
+ @on_disconnect.setter
204
+ def on_disconnect(self, arg: Callable[[SoraSignalingErrorCode, str], None], /) -> None: ...
205
+
206
+ @property
207
+ def on_signaling_message(self) -> Callable[[SoraSignalingType, SoraSignalingDirection, str], None]: ...
208
+
209
+ @on_signaling_message.setter
210
+ def on_signaling_message(self, arg: Callable[[SoraSignalingType, SoraSignalingDirection, str], None], /) -> None: ...
211
+
212
+ @property
213
+ def on_notify(self) -> Callable[[str], None]: ...
214
+
215
+ @on_notify.setter
216
+ def on_notify(self, arg: Callable[[str], None], /) -> None: ...
217
+
218
+ @property
219
+ def on_push(self) -> Callable[[str], None]: ...
220
+
221
+ @on_push.setter
222
+ def on_push(self, arg: Callable[[str], None], /) -> None: ...
223
+
224
+ @property
225
+ def on_message(self) -> Callable[[str, bytes], None]: ...
226
+
227
+ @on_message.setter
228
+ def on_message(self, arg: Callable[[str, bytes], None], /) -> None: ...
229
+
230
+ @property
231
+ def on_rpc(self) -> Callable[[bytes], None]: ...
232
+
233
+ @on_rpc.setter
234
+ def on_rpc(self, arg: Callable[[bytes], None], /) -> None: ...
235
+
236
+ @property
237
+ def on_switched(self) -> Callable[[str], None]: ...
238
+
239
+ @on_switched.setter
240
+ def on_switched(self, arg: Callable[[str], None], /) -> None: ...
241
+
242
+ @property
243
+ def on_track(self) -> Callable[[SoraMediaTrack], None]: ...
244
+
245
+ @on_track.setter
246
+ def on_track(self, arg: Callable[[SoraMediaTrack], None], /) -> None: ...
247
+
248
+ @property
249
+ def on_data_channel(self) -> Callable[[str], None]: ...
250
+
251
+ @on_data_channel.setter
252
+ def on_data_channel(self, arg: Callable[[str], None], /) -> None: ...
253
+
254
+ class SoraTransformableFrameDirection(enum.IntEnum):
255
+ UNKNOWN = 0
256
+
257
+ RECEIVER = 1
258
+
259
+ SENDER = 2
260
+
261
+ class SoraTransformableFrame:
262
+ def get_data(self) -> Annotated[NDArray[numpy.uint8], dict(shape=(None,), writable=False)]: ...
263
+
264
+ def set_data(self, arg: Annotated[NDArray[numpy.uint8], dict(shape=(None,), order='C', device='cpu', writable=False)], /) -> None: ...
265
+
266
+ @property
267
+ def payload_type(self) -> int: ...
268
+
269
+ @property
270
+ def ssrc(self) -> int: ...
271
+
272
+ @property
273
+ def rtp_timestamp(self) -> int: ...
274
+
275
+ @rtp_timestamp.setter
276
+ def rtp_timestamp(self, arg: int, /) -> None: ...
277
+
278
+ @property
279
+ def direction(self) -> SoraTransformableFrameDirection: ...
280
+
281
+ @property
282
+ def mine_type(self) -> str: ...
283
+
284
+ class SoraTransformableAudioFrameType(enum.IntEnum):
285
+ EMPTY = 0
286
+
287
+ SPEECH = 1
288
+
289
+ CN = 2
290
+
291
+ class SoraTransformableAudioFrame(SoraTransformableFrame):
292
+ @property
293
+ def contributing_sources(self) -> Annotated[NDArray[numpy.uint32], dict(shape=(None,), writable=False)]: ...
294
+
295
+ @property
296
+ def sequence_number(self) -> int | None: ...
297
+
298
+ @property
299
+ def absolute_capture_timestamp(self) -> int | None: ...
300
+
301
+ @property
302
+ def type(self) -> SoraTransformableAudioFrameType: ...
303
+
304
+ @property
305
+ def audio_level(self) -> int | None: ...
306
+
307
+ @property
308
+ def receive_time(self) -> int | None: ...
309
+
310
+ class SoraTransformableVideoFrame(SoraTransformableFrame):
311
+ @property
312
+ def is_key_frame(self) -> bool: ...
313
+
314
+ @property
315
+ def frame_id(self) -> int | None: ...
316
+
317
+ @property
318
+ def frame_dependencies(self) -> Annotated[NDArray[numpy.int64], dict(shape=(None,), writable=False)]: ...
319
+
320
+ @property
321
+ def width(self) -> int: ...
322
+
323
+ @property
324
+ def height(self) -> int: ...
325
+
326
+ @property
327
+ def spatial_index(self) -> int: ...
328
+
329
+ @property
330
+ def temporal_index(self) -> int: ...
331
+
332
+ @property
333
+ def contributing_sources(self) -> Annotated[NDArray[numpy.uint32], dict(shape=(None,), writable=False)]: ...
334
+
335
+ class SoraFrameTransformer:
336
+ def enqueue(self, arg: SoraTransformableFrame, /) -> None: ...
337
+
338
+ def start_short_circuiting(self) -> None: ...
339
+
340
+ class SoraAudioFrameTransformer(SoraFrameTransformer):
341
+ def __init__(self) -> None: ...
342
+
343
+ def __del__(self) -> None: ...
344
+
345
+ @property
346
+ def on_transform(self) -> Callable[[SoraTransformableAudioFrame], None]: ...
347
+
348
+ @on_transform.setter
349
+ def on_transform(self, arg: Callable[[SoraTransformableAudioFrame], None], /) -> None: ...
350
+
351
+ class SoraVideoFrameTransformer(SoraFrameTransformer):
352
+ def __init__(self) -> None: ...
353
+
354
+ def __del__(self) -> None: ...
355
+
356
+ @property
357
+ def on_transform(self) -> Callable[[SoraTransformableVideoFrame], None]: ...
358
+
359
+ @on_transform.setter
360
+ def on_transform(self, arg: Callable[[SoraTransformableVideoFrame], None], /) -> None: ...
361
+
362
+ class SoraVideoCodecImplementation(enum.IntEnum):
363
+ INTERNAL = 0
364
+
365
+ CISCO_OPENH264 = 1
366
+
367
+ INTEL_VPL = 2
368
+
369
+ NVIDIA_VIDEO_CODEC_SDK = 3
370
+
371
+ AMD_AMF = 4
372
+
373
+ RASPI_V4L2M2M = 5
374
+
375
+ class SoraVideoCodecType(enum.IntEnum):
376
+ VP8 = 1
377
+
378
+ VP9 = 2
379
+
380
+ H264 = 4
381
+
382
+ H265 = 5
383
+
384
+ AV1 = 3
385
+
386
+ class SoraVideoCodecCapability:
387
+ @property
388
+ def engines(self) -> list[SoraVideoCodecCapability.Engine]: ...
389
+
390
+ def to_json(self) -> object: ...
391
+
392
+ class Parameters:
393
+ @property
394
+ def version(self) -> str | None: ...
395
+
396
+ @property
397
+ def openh264_path(self) -> str | None: ...
398
+
399
+ @property
400
+ def vpl_impl(self) -> str | None: ...
401
+
402
+ @property
403
+ def vpl_impl_value(self) -> int | None: ...
404
+
405
+ @property
406
+ def nvcodec_gpu_device_name(self) -> str | None: ...
407
+
408
+ @property
409
+ def amf_runtime_version(self) -> str | None: ...
410
+
411
+ @property
412
+ def amf_embedded_version(self) -> str | None: ...
413
+
414
+ class Codec:
415
+ @property
416
+ def type(self) -> SoraVideoCodecType: ...
417
+
418
+ @property
419
+ def encoder(self) -> bool: ...
420
+
421
+ @property
422
+ def decoder(self) -> bool: ...
423
+
424
+ @property
425
+ def parameters(self) -> SoraVideoCodecCapability.Parameters: ...
426
+
427
+ class Engine:
428
+ @property
429
+ def name(self) -> SoraVideoCodecImplementation: ...
430
+
431
+ @property
432
+ def codecs(self) -> list[SoraVideoCodecCapability.Codec]: ...
433
+
434
+ @property
435
+ def parameters(self) -> SoraVideoCodecCapability.Parameters: ...
436
+
437
+ def get_video_codec_capability(openh264: str | None = None) -> SoraVideoCodecCapability: ...
438
+
439
+ class SoraVideoCodecPreference:
440
+ def __init__(self, codecs: Sequence[SoraVideoCodecPreference.Codec] = []) -> None: ...
441
+
442
+ @property
443
+ def codecs(self) -> list[SoraVideoCodecPreference.Codec]: ...
444
+
445
+ @codecs.setter
446
+ def codecs(self, arg: Sequence[SoraVideoCodecPreference.Codec], /) -> None: ...
447
+
448
+ def to_json(self) -> object: ...
449
+
450
+ def find(self, arg: SoraVideoCodecType, /) -> int | None: ...
451
+
452
+ def get_or_add(self, arg: SoraVideoCodecType, /) -> int: ...
453
+
454
+ def has_implementation(self, arg: SoraVideoCodecImplementation, /) -> bool: ...
455
+
456
+ def merge(self, arg: SoraVideoCodecPreference, /) -> None: ...
457
+
458
+ class Parameters:
459
+ def __init__(self) -> None: ...
460
+
461
+ class Codec:
462
+ @overload
463
+ def __init__(self) -> None: ...
464
+
465
+ @overload
466
+ def __init__(self, type: SoraVideoCodecType, encoder: SoraVideoCodecImplementation | None = None, decoder: SoraVideoCodecImplementation | None = None, parameters: SoraVideoCodecPreference.Parameters | None = None) -> None: ...
467
+
468
+ @property
469
+ def type(self) -> SoraVideoCodecType: ...
470
+
471
+ @type.setter
472
+ def type(self, arg: SoraVideoCodecType, /) -> None: ...
473
+
474
+ @property
475
+ def encoder(self) -> SoraVideoCodecImplementation | None: ...
476
+
477
+ @encoder.setter
478
+ def encoder(self, arg: SoraVideoCodecImplementation, /) -> None: ...
479
+
480
+ @property
481
+ def decoder(self) -> SoraVideoCodecImplementation | None: ...
482
+
483
+ @decoder.setter
484
+ def decoder(self, arg: SoraVideoCodecImplementation, /) -> None: ...
485
+
486
+ @property
487
+ def parameters(self) -> SoraVideoCodecPreference.Parameters: ...
488
+
489
+ @parameters.setter
490
+ def parameters(self, arg: SoraVideoCodecPreference.Parameters, /) -> None: ...
491
+
492
+ def create_video_codec_preference_from_implementation(arg0: SoraVideoCodecCapability, arg1: SoraVideoCodecImplementation, /) -> SoraVideoCodecPreference: ...
493
+
494
+ class Sora:
495
+ def __init__(self, openh264: str | None = None, video_codec_preference: SoraVideoCodecPreference | None = None, force_i420_conversion: bool | None = None) -> None: ...
496
+
497
+ def create_connection(self, signaling_urls: list[str], role: str, channel_id: str, client_id: Optional[str] = None, bundle_id: Optional[str] = None, metadata: Optional[dict] = None, signaling_notify_metadata: Optional[dict] = None, audio_source: Optional[SoraTrackInterface] = None, video_source: Optional[SoraTrackInterface] = None, audio_frame_transformer: Optional[SoraAudioFrameTransformer] = None, video_frame_transformer: Optional[SoraVideoFrameTransformer] = None, audio: Optional[bool] = None, video: Optional[bool] = None, audio_codec_type: Optional[str] = None, video_codec_type: Optional[str] = None, video_bit_rate: Optional[int] = None, audio_bit_rate: Optional[int] = None, video_vp9_params: Optional[dict] = None, video_av1_params: Optional[dict] = None, video_h264_params: Optional[dict] = None, audio_opus_params: Optional[dict] = None, simulcast: Optional[bool] = None, spotlight: Optional[bool] = None, spotlight_number: Optional[int] = None, simulcast_rid: Optional[str] = None, spotlight_focus_rid: Optional[str] = None, spotlight_unfocus_rid: Optional[str] = None, forwarding_filter: Optional[dict] = None, forwarding_filters: Optional[list[dict]] = None, data_channels: Optional[list[dict]] = None, data_channel_signaling: Optional[bool] = None, ignore_disconnect_websocket: Optional[bool] = None, data_channel_signaling_timeout: Optional[int] = None, disconnect_wait_timeout: Optional[int] = None, websocket_close_timeout: Optional[int] = None, websocket_connection_timeout: Optional[int] = None, audio_streaming_language_code: Optional[str] = None, insecure: Optional[bool] = None, client_cert: Optional[bytes] = None, client_key: Optional[bytes] = None, ca_cert: Optional[bytes] = None, proxy_url: Optional[str] = None, proxy_username: Optional[str] = None, proxy_password: Optional[str] = None, proxy_agent: Optional[str] = None, degradation_preference: Optional[SoraDegradationPreference] = None, user_agent: Optional[str] = None) -> SoraConnection: ...
498
+
499
+ def create_audio_source(self, channels: int, sample_rate: int) -> SoraAudioSource: ...
500
+
501
+ def create_video_source(self) -> SoraVideoSource: ...
502
+
503
+ def create_libcamera_source(self, width: int, height: int, fps: int, native_frame_output: bool, controls: Optional[list[tuple[str, str]]] = None) -> SoraTrackInterface: ...
@@ -0,0 +1,259 @@
1
+ Metadata-Version: 2.4
2
+ Name: sora_sdk
3
+ Version: 2025.5.0.dev4
4
+ Summary: WebRTC SFU Sora Python SDK
5
+ Home-page: https://github.com/shiguredo/sora-python-sdk
6
+ Author-email: "Shiguredo Inc." <contact+pypi@shiguredo.jp>
7
+ License-Expression: Apache-2.0
8
+ Project-URL: Source, https://github.com/shiguredo/sora-python-sdk
9
+ Project-URL: Documentation, https://sora-python-sdk.shiguredo.jp
10
+ Project-URL: Discord, https://discord.gg/shiguredo
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Dynamic: home-page
19
+ Dynamic: license-file
20
+
21
+ # Sora Python SDK
22
+
23
+ [![PyPI](https://img.shields.io/pypi/v/sora_sdk)](https://pypi.org/project/sora-sdk/)
24
+ [![image](https://img.shields.io/pypi/pyversions/sora_sdk.svg)](https://pypi.python.org/pypi/sora_sdk)
25
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
26
+ [![Actions status](https://github.com/shiguredo/sora-python-sdk/workflows/build/badge.svg)](https://github.com/shiguredo/sora-python-sdk/actions)
27
+
28
+ Sora Python SDK は [WebRTC SFU Sora](https://sora.shiguredo.jp/) の Python クライアントアプリケーションを開発するためのライブラリです。[Sora C++ SDK](https://github.com/shiguredo/sora-cpp-sdk) をベースにしています。
29
+
30
+ ## About Shiguredo's open source software
31
+
32
+ We will not respond to PRs or issues that have not been discussed on Discord. Also, Discord is only available in Japanese.
33
+
34
+ Please read <https://github.com/shiguredo/oss/blob/master/README.en.md> before use.
35
+
36
+ ## 時雨堂のオープンソースソフトウェアについて
37
+
38
+ 利用前に <https://github.com/shiguredo/oss> をお読みください。
39
+
40
+ ## Sora Python SDK について
41
+
42
+ 様々なプラットフォームに対応しすぐに使い始められる WebRTC SFU Sora 向けの Python SDK です。
43
+
44
+ 音声や映像デバイスの処理を SDK から独立させているため、様々なライブラリを利用する事ができます。
45
+
46
+ ## 特徴
47
+
48
+ - [Sora C++ SDK](https://github.com/shiguredo/sora-cpp-sdk) ベース
49
+ - WebRTC 部分の機能は [libwebrtc](https://webrtc.googlesource.com/src/) を採用
50
+ - Windows / macOS / Linux (Ubuntu / Raspberry Pi OS) プラットフォームに対応
51
+ - [WebRTC 統計情報](https://www.w3.org/TR/webrtc-stats/) の取得が可能
52
+ - [WebRTC Encoded Transform](https://www.w3.org/TR/webrtc-encoded-transform/) に対応
53
+ - 回線が不安定になった際、解像度とフレームレートどちらを維持するかの設定をする [DegradationPreference](https://w3c.github.io/mst-content-hint/#degradation-preference-when-encoding) に対応
54
+ - MAINTAIN_FRAMERATE / MAINTAIN_RESOLUTION / BALANCED が指定できる
55
+ - 発話区間の検出が可能な VAD (Voice Activity Detection) に対応
56
+ - Intel / Apple / NVIDIA / Raspberry Pi のハードウェアデコーダー/エンコーダーに対応
57
+ - Apple Video Toolbox (H.264 / H.265)
58
+ - macOS arm64 で利用できる
59
+ - Intel VPL (AV1 / H.264 / H.265)
60
+ - Ubuntu x86_64 / Windows x86_64 で利用できる
61
+ - AMD AMF (VP9 /AV1 / H.264 / H.265)
62
+ - Ubuntu x86_64 / Windows x86_64 で利用できる
63
+ - AV1 エンコードは Windows x86_64 でのみ利用できる
64
+ - VP9 はデコードのみ利用できる
65
+ - NVIDIA Video Codec (VP8 / VP9 / AV1 / H.264 / H.265)
66
+ - Ubuntu x86_64 / Windows x86_64 で利用できる
67
+ - VP8 と VP9 はデコードのみ利用できる
68
+ - NVIDIA Jetson JetPack SDK (AV1 / H.264 / H.265)
69
+ - Raspberry Pi (H.264)
70
+ - Raspberry Pi 4 / Raspberry Pi 3 / Raspberry Pi 2 Model B v1.2 / Raspberry Pi Zero 2 W で利用できる
71
+ - V4L2-M2M API を利用している
72
+ - [各プラットフォームで利用可能な HWA への対応](https://github.com/shiguredo/sora-cpp-sdk?tab=readme-ov-file#%E7%89%B9%E5%BE%B4)
73
+ - [OpenH264](https://github.com/cisco/openh264) を利用した H.264 のソフトウェアエンコーダー/デコーダーに対応
74
+ - Ubuntu x86_64 / Ubuntu arm64 / Windows x86_64 / macOS arm64 で利用できる
75
+ - 音声デバイス処理に [sounddevice](https://pypi.org/project/sounddevice/) などが利用できる
76
+ - 映像デバイス処理に [opencv-python](https://pypi.org/project/opencv-python/) などが利用できる
77
+ - 音声認識などの入力に受信した音声を利用できる
78
+ - 物体検出などの入力に受信した映像を利用できる
79
+ - `uv add sora_sdk` や `pip install sora_sdk` でインストールできる
80
+ - Raspberry Pi 向けのパッケージも `uv add sora_sdk_rpi` でインストールできる
81
+ - Raspberry Pi 向けに libcamera 用の `create_libcamera_source` を提供
82
+ - [NVIDIA Jetson JetPack SDK](https://developer.nvidia.com/embedded/jetpack) に対応
83
+
84
+ ## 利用イメージ
85
+
86
+ - データチャンネルを利用して Python において映像、音声を解析した結果を Sora 経由で配信する
87
+ - Text to Speech の音声を Sora 経由で配信する
88
+ - 映像入力に対して Pillow などで加工した映像を Sora を経由で配信する
89
+ - A チャンネルの参加者からの映像と音声を B チャンネルに対して加工した上で Sora 経由で配信する
90
+
91
+ ## ドキュメント
92
+
93
+ [Sora Python SDK](https://sora-python-sdk.shiguredo.jp/)
94
+
95
+ ## サンプル集
96
+
97
+ [shiguredo/sora-python-sdk-examples](https://github.com/shiguredo/sora-python-sdk-examples)
98
+
99
+ ## sora_sdk パッケージの追加
100
+
101
+ [uv](https://docs.astral.sh/uv/) の利用を推奨します。
102
+
103
+ ```bash
104
+ uv add sora_sdk
105
+ ```
106
+
107
+ ### Raspberry Pi OS 向けパッケージ
108
+
109
+ ```bash
110
+ uv add sora_sdk_rpi
111
+ ```
112
+
113
+ ### NVIDIA Jetson 向けパッケージ
114
+
115
+ PyPI 経由ではインストールできません。
116
+ パッケージバイナリを配布しておりますので、そちらをご利用ください。
117
+
118
+ <https://github.com/shiguredo/sora-python-sdk/releases/tag/2024.3.0-jetson-jetpack-6.0.0.0>
119
+
120
+ ## システム条件
121
+
122
+ - WebRTC SFU Sora 2024.2.0 以降
123
+ - Python 3.11 以上
124
+
125
+ ## Python サポートポリシー
126
+
127
+ 直近の 3 バージョンの Python をサポートします。
128
+
129
+ ## 対応プラットフォーム
130
+
131
+ - Ubuntu 24.04 LTS x86_64
132
+ - Ubuntu 24.04 LTS arm64
133
+ - Ubuntu 22.04 LTS x86_64
134
+ - Ubuntu 22.04 LTS arm64
135
+ - macOS Sequoia 15 arm64
136
+ - macOS Ventura 14 arm64
137
+ - Windows 11 x86_64
138
+ - Windows Server 2025 x86_64
139
+ - Raspberry Pi OS armv8
140
+
141
+ ### Raspberry Pi OS 向け
142
+
143
+ - Raspberry Pi OS bookworm (64bit)
144
+ - Raspberry Pi 5
145
+ - Raspberry Pi 4
146
+ - Raspberry Pi 3
147
+ - Raspberry Pi 2 Model B v1.2
148
+ - Raspberry Pi Zero 2 W
149
+
150
+ > [!CAUTION]
151
+ >
152
+ > - Raspberry Pi 5 は H.264 ハードウェアエンコーダーが搭載されていません
153
+ > - Raspberry Pi 5 の H.265 ハードウェアデコーダーに対応していません
154
+
155
+ ### NVIDIA Jetson 向け
156
+
157
+ - Ubuntu 22.04 LTS arm64 (NVIDIA Jetson JetPack SDK 6)
158
+ - PyPI からではなくパッケージファイルを利用してください
159
+
160
+ ### macOS の対応バージョン
161
+
162
+ 直近の 2 バージョンをサポートします。
163
+
164
+ ### Ubuntu の対応バージョン
165
+
166
+ 直近の LTS 2 バージョンをサポートします。
167
+
168
+ ## 優先実装
169
+
170
+ 優先実装とは Sora のライセンスを契約頂いているお客様向けに Sora Python SDK の実装予定機能を有償にて前倒しで実装することです。
171
+
172
+ **詳細は Discord やメールなどでお気軽にお問い合わせください**
173
+
174
+ - DataChannel 対応
175
+ - [アダワープジャパン株式会社](https://adawarp.com/) 様
176
+ - Intel VPL H.265 対応
177
+ - [アダワープジャパン株式会社](https://adawarp.com/) 様
178
+
179
+ ### 優先実装が可能な機能一覧
180
+
181
+ - Windows 11 arm64
182
+ - Ubuntu 22.04 arm64 (NVIDIA Jetson JetPack SDK 6.1)
183
+ - Ubuntu 20.04 arm64 (NVIDIA Jetson JetPack SDK 5)
184
+
185
+ ## サポートについて
186
+
187
+ ### Discord
188
+
189
+ - **サポートしません**
190
+ - アドバイスします
191
+ - フィードバック歓迎します
192
+
193
+ 最新の状況などは Discord で共有しています。質問や相談も Discord でのみ受け付けています。
194
+
195
+ <https://discord.gg/shiguredo>
196
+
197
+ ### バグ報告
198
+
199
+ Discord へお願いします。
200
+
201
+ ## ライセンス
202
+
203
+ Apache License 2.0
204
+
205
+ ```text
206
+ Copyright 2023-2025, tnoho (Original Author)
207
+ Copyright 2023-2025, Wandbox LLC (Original Author)
208
+ Copyright 2023-2025, Shiguredo Inc.
209
+
210
+ Licensed under the Apache License, Version 2.0 (the "License");
211
+ you may not use this file except in compliance with the License.
212
+ You may obtain a copy of the License at
213
+
214
+ http://www.apache.org/licenses/LICENSE-2.0
215
+
216
+ Unless required by applicable law or agreed to in writing, software
217
+ distributed under the License is distributed on an "AS IS" BASIS,
218
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
219
+ See the License for the specific language governing permissions and
220
+ limitations under the License.
221
+ ```
222
+
223
+ ## OpenH264
224
+
225
+ <https://www.openh264.org/BINARY_LICENSE.txt>
226
+
227
+ ```text
228
+ "OpenH264 Video Codec provided by Cisco Systems, Inc."
229
+ ```
230
+
231
+ ## NVDIA Video Codec SDK
232
+
233
+ <https://docs.nvidia.com/video-technologies/video-codec-sdk/12.2/license/index.html>
234
+
235
+ ```text
236
+ “This software contains source code provided by NVIDIA Corporation.”
237
+ ```
238
+
239
+ ## H.264 (AVC) と H.265 (HEVC) のライセンスについて
240
+
241
+ **時雨堂が提供する libwebrtc のビルド済みバイナリには H.264 と H.265 のコーデックは含まれていません**
242
+
243
+ ### H.264
244
+
245
+ H.264 対応は [Via LA Licensing](https://www.via-la.com/) (旧 MPEG-LA) に連絡を取り、ロイヤリティの対象にならないことを確認しています。
246
+
247
+ > 時雨堂がエンドユーザーの PC /デバイスに既に存在する AVC / H.264 エンコーダー/デコーダーに依存する製品を提供する場合は、
248
+ > ソフトウェア製品は AVC ライセンスの対象外となり、ロイヤリティの対象にもなりません。
249
+
250
+ ### H.265
251
+
252
+ H.265 対応は以下の二つの団体に連絡を取り、H.265 ハードウェアアクセラレーターのみを利用し、
253
+ H.265 が利用可能なバイナリを配布する事は、ライセンスが不要であることを確認しています。
254
+
255
+ また、H.265 のハードウェアアクセラレーターのみを利用した H.265 対応の SDK を OSS で公開し、
256
+ ビルド済みバイナリを配布する事は、ライセンスが不要であることも確認しています。
257
+
258
+ - [Access Advance](https://accessadvance.com/ja/)
259
+ - [Via LA Licensing](https://www.via-la.com/)
@@ -0,0 +1,9 @@
1
+ sora_sdk-2025.5.0.dev4.data/purelib/sora_sdk/__init__.py,sha256=oIPJZylpxilyawkPEH8yjPEZ5wV-wdFnwL1DWH5Ksm0,2004
2
+ sora_sdk-2025.5.0.dev4.data/purelib/sora_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ sora_sdk-2025.5.0.dev4.data/purelib/sora_sdk/sora_sdk_ext.cpython-314-aarch64-linux-gnu.so,sha256=VU3ta5FNWnIumyp08AdkZKJWI0XgQul973zThZuDb6k,18489392
4
+ sora_sdk-2025.5.0.dev4.data/purelib/sora_sdk/sora_sdk_ext.pyi,sha256=_vSuS0PNtNbqGtVCtYEAPeAqziYMn0vWWJJ1RGISVL0,15785
5
+ sora_sdk-2025.5.0.dev4.dist-info/licenses/LICENSE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174
6
+ sora_sdk-2025.5.0.dev4.dist-info/METADATA,sha256=u8FV97PdvueYkjLOL7uTOeeNiC3LhTFwhBtySZE1UFs,10568
7
+ sora_sdk-2025.5.0.dev4.dist-info/WHEEL,sha256=X7Alh2BCOPVcMlZ_TwuJfQzCuQUKafDcBzfhrbZ9qFU,114
8
+ sora_sdk-2025.5.0.dev4.dist-info/top_level.txt,sha256=edTg20cFFAjWfRrB0APD_SXho5Qq24PwLESbyPoCVko,9
9
+ sora_sdk-2025.5.0.dev4.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp314-cp314-manylinux_2_31_aarch64
5
+
@@ -0,0 +1,177 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
@@ -0,0 +1 @@
1
+ sora_sdk