streamlit-webrtc 0.51.3__py3-none-any.whl → 0.53.0__py3-none-any.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.
- streamlit_webrtc/__init__.py +0 -2
- streamlit_webrtc/component.py +62 -72
- streamlit_webrtc/config.py +46 -1
- streamlit_webrtc/credentials.py +29 -2
- streamlit_webrtc/webrtc.py +3 -2
- {streamlit_webrtc-0.51.3.dist-info → streamlit_webrtc-0.53.0.dist-info}/METADATA +1 -1
- {streamlit_webrtc-0.51.3.dist-info → streamlit_webrtc-0.53.0.dist-info}/RECORD +9 -9
- {streamlit_webrtc-0.51.3.dist-info → streamlit_webrtc-0.53.0.dist-info}/WHEEL +0 -0
- {streamlit_webrtc-0.51.3.dist-info → streamlit_webrtc-0.53.0.dist-info}/licenses/LICENSE +0 -0
streamlit_webrtc/__init__.py
CHANGED
@@ -7,7 +7,6 @@ except ModuleNotFoundError:
|
|
7
7
|
import importlib_metadata # type: ignore
|
8
8
|
|
9
9
|
from .component import (
|
10
|
-
ClientSettings,
|
11
10
|
WebRtcStreamerContext,
|
12
11
|
WebRtcStreamerState,
|
13
12
|
webrtc_streamer,
|
@@ -58,7 +57,6 @@ VideoTransformerFactory = VideoProcessorFactory
|
|
58
57
|
|
59
58
|
__all__ = [
|
60
59
|
"webrtc_streamer",
|
61
|
-
"ClientSettings",
|
62
60
|
"AudioProcessorBase",
|
63
61
|
"AudioProcessorFactory",
|
64
62
|
"AudioReceiver",
|
streamlit_webrtc/component.py
CHANGED
@@ -11,7 +11,6 @@ from typing import (
|
|
11
11
|
Generic,
|
12
12
|
NamedTuple,
|
13
13
|
Optional,
|
14
|
-
TypedDict,
|
15
14
|
Union,
|
16
15
|
cast,
|
17
16
|
overload,
|
@@ -19,6 +18,7 @@ from typing import (
|
|
19
18
|
|
20
19
|
import streamlit as st
|
21
20
|
import streamlit.components.v1 as components
|
21
|
+
from aiortc import RTCConfiguration as AiortcRTCConfiguration
|
22
22
|
from aiortc.mediastreams import MediaStreamTrack
|
23
23
|
|
24
24
|
from streamlit_webrtc.models import (
|
@@ -40,10 +40,11 @@ from .config import (
|
|
40
40
|
RTCConfiguration,
|
41
41
|
Translations,
|
42
42
|
VideoHTMLAttributes,
|
43
|
+
compile_ice_servers,
|
44
|
+
compile_rtc_configuration,
|
43
45
|
)
|
44
46
|
from .credentials import (
|
45
|
-
|
46
|
-
get_twilio_ice_servers,
|
47
|
+
get_available_ice_servers,
|
47
48
|
)
|
48
49
|
from .session_info import get_script_run_count, get_this_session_info
|
49
50
|
from .webrtc import (
|
@@ -75,11 +76,6 @@ else:
|
|
75
76
|
_component_func = components.declare_component("webrtc_streamer", path=build_dir)
|
76
77
|
|
77
78
|
|
78
|
-
class ClientSettings(TypedDict, total=False):
|
79
|
-
rtc_configuration: RTCConfiguration
|
80
|
-
media_stream_constraints: MediaStreamConstraints
|
81
|
-
|
82
|
-
|
83
79
|
class WebRtcStreamerState(NamedTuple):
|
84
80
|
playing: bool
|
85
81
|
signalling: bool
|
@@ -96,7 +92,7 @@ class WebRtcStreamerContext(Generic[VideoProcessorT, AudioProcessorT]):
|
|
96
92
|
_worker_ref: "Optional[weakref.ReferenceType[WebRtcWorker[VideoProcessorT, AudioProcessorT]]]" # noqa
|
97
93
|
|
98
94
|
_component_value_snapshot: Union[ComponentValueSnapshot, None]
|
99
|
-
|
95
|
+
_frontend_rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]]
|
100
96
|
|
101
97
|
def __init__(
|
102
98
|
self,
|
@@ -106,7 +102,7 @@ class WebRtcStreamerContext(Generic[VideoProcessorT, AudioProcessorT]):
|
|
106
102
|
self._set_worker(worker)
|
107
103
|
self._set_state(state)
|
108
104
|
self._component_value_snapshot = None
|
109
|
-
self.
|
105
|
+
self._frontend_rtc_configuration = None
|
110
106
|
|
111
107
|
def _set_worker(
|
112
108
|
self, worker: Optional[WebRtcWorker[VideoProcessorT, AudioProcessorT]]
|
@@ -223,7 +219,10 @@ def compile_state(component_value) -> WebRtcStreamerState:
|
|
223
219
|
def webrtc_streamer(
|
224
220
|
key: str,
|
225
221
|
mode: WebRtcMode = WebRtcMode.SENDRECV,
|
226
|
-
|
222
|
+
server_rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
223
|
+
frontend_rtc_configuration: Optional[
|
224
|
+
Union[Dict[str, Any], RTCConfiguration]
|
225
|
+
] = None,
|
227
226
|
media_stream_constraints: Optional[Union[Dict, MediaStreamConstraints]] = None,
|
228
227
|
desired_playing_state: Optional[bool] = None,
|
229
228
|
player_factory: Optional[MediaPlayerFactory] = None,
|
@@ -249,9 +248,9 @@ def webrtc_streamer(
|
|
249
248
|
translations: Optional[Translations] = None,
|
250
249
|
on_change: Optional[Callable] = None,
|
251
250
|
# Deprecated. Just for backward compatibility
|
252
|
-
client_settings: Optional[Union[ClientSettings, Dict]] = None,
|
253
251
|
video_transformer_factory: None = None,
|
254
252
|
async_transform: Optional[bool] = None,
|
253
|
+
rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
255
254
|
) -> WebRtcStreamerContext:
|
256
255
|
# XXX: We wanted something like `WebRtcStreamerContext[None, None]`
|
257
256
|
# as the return value, but could not find a good solution
|
@@ -264,7 +263,10 @@ def webrtc_streamer(
|
|
264
263
|
def webrtc_streamer(
|
265
264
|
key: str,
|
266
265
|
mode: WebRtcMode = WebRtcMode.SENDRECV,
|
267
|
-
|
266
|
+
server_rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
267
|
+
frontend_rtc_configuration: Optional[
|
268
|
+
Union[Dict[str, Any], RTCConfiguration]
|
269
|
+
] = None,
|
268
270
|
media_stream_constraints: Optional[Union[Dict, MediaStreamConstraints]] = None,
|
269
271
|
desired_playing_state: Optional[bool] = None,
|
270
272
|
player_factory: Optional[MediaPlayerFactory] = None,
|
@@ -290,9 +292,9 @@ def webrtc_streamer(
|
|
290
292
|
translations: Optional[Translations] = None,
|
291
293
|
on_change: Optional[Callable] = None,
|
292
294
|
# Deprecated. Just for backward compatibility
|
293
|
-
client_settings: Optional[Union[ClientSettings, Dict]] = None,
|
294
295
|
video_transformer_factory: None = None,
|
295
296
|
async_transform: Optional[bool] = None,
|
297
|
+
rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
296
298
|
) -> WebRtcStreamerContext[VideoProcessorT, Any]:
|
297
299
|
pass
|
298
300
|
|
@@ -301,7 +303,10 @@ def webrtc_streamer(
|
|
301
303
|
def webrtc_streamer(
|
302
304
|
key: str,
|
303
305
|
mode: WebRtcMode = WebRtcMode.SENDRECV,
|
304
|
-
|
306
|
+
server_rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
307
|
+
frontend_rtc_configuration: Optional[
|
308
|
+
Union[Dict[str, Any], RTCConfiguration]
|
309
|
+
] = None,
|
305
310
|
media_stream_constraints: Optional[Union[Dict, MediaStreamConstraints]] = None,
|
306
311
|
desired_playing_state: Optional[bool] = None,
|
307
312
|
player_factory: Optional[MediaPlayerFactory] = None,
|
@@ -327,9 +332,9 @@ def webrtc_streamer(
|
|
327
332
|
translations: Optional[Translations] = None,
|
328
333
|
on_change: Optional[Callable] = None,
|
329
334
|
# Deprecated. Just for backward compatibility
|
330
|
-
client_settings: Optional[Union[ClientSettings, Dict]] = None,
|
331
335
|
video_transformer_factory: None = None,
|
332
336
|
async_transform: Optional[bool] = None,
|
337
|
+
rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
333
338
|
) -> WebRtcStreamerContext[Any, AudioProcessorT]:
|
334
339
|
pass
|
335
340
|
|
@@ -338,7 +343,10 @@ def webrtc_streamer(
|
|
338
343
|
def webrtc_streamer(
|
339
344
|
key: str,
|
340
345
|
mode: WebRtcMode = WebRtcMode.SENDRECV,
|
341
|
-
|
346
|
+
server_rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
347
|
+
frontend_rtc_configuration: Optional[
|
348
|
+
Union[Dict[str, Any], RTCConfiguration]
|
349
|
+
] = None,
|
342
350
|
media_stream_constraints: Optional[Union[Dict, MediaStreamConstraints]] = None,
|
343
351
|
desired_playing_state: Optional[bool] = None,
|
344
352
|
player_factory: Optional[MediaPlayerFactory] = None,
|
@@ -364,9 +372,9 @@ def webrtc_streamer(
|
|
364
372
|
translations: Optional[Translations] = None,
|
365
373
|
on_change: Optional[Callable] = None,
|
366
374
|
# Deprecated. Just for backward compatibility
|
367
|
-
client_settings: Optional[Union[ClientSettings, Dict]] = None,
|
368
375
|
video_transformer_factory: None = None,
|
369
376
|
async_transform: Optional[bool] = None,
|
377
|
+
rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
370
378
|
) -> WebRtcStreamerContext[VideoProcessorT, AudioProcessorT]:
|
371
379
|
pass
|
372
380
|
|
@@ -374,7 +382,10 @@ def webrtc_streamer(
|
|
374
382
|
def webrtc_streamer(
|
375
383
|
key: str,
|
376
384
|
mode: WebRtcMode = WebRtcMode.SENDRECV,
|
377
|
-
|
385
|
+
server_rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
386
|
+
frontend_rtc_configuration: Optional[
|
387
|
+
Union[Dict[str, Any], RTCConfiguration]
|
388
|
+
] = None,
|
378
389
|
media_stream_constraints: Optional[Union[Dict, MediaStreamConstraints]] = None,
|
379
390
|
desired_playing_state: Optional[bool] = None,
|
380
391
|
player_factory: Optional[MediaPlayerFactory] = None,
|
@@ -400,16 +411,16 @@ def webrtc_streamer(
|
|
400
411
|
translations: Optional[Translations] = None,
|
401
412
|
on_change: Optional[Callable] = None,
|
402
413
|
# Deprecated. Just for backward compatibility
|
403
|
-
client_settings: Optional[Union[ClientSettings, Dict]] = None,
|
404
414
|
video_transformer_factory=None,
|
405
415
|
async_transform: Optional[bool] = None,
|
416
|
+
rtc_configuration: Optional[Union[Dict[str, Any], RTCConfiguration]] = None,
|
406
417
|
) -> WebRtcStreamerContext[VideoProcessorT, AudioProcessorT]:
|
407
418
|
# Backward compatibility
|
408
419
|
if video_transformer_factory is not None:
|
409
420
|
warnings.warn(
|
410
421
|
"The argument video_transformer_factory is deprecated. "
|
411
422
|
"Use video_processor_factory instead.\n"
|
412
|
-
"See https://github.com/whitphx/streamlit-webrtc#for-users-since-versions-020",
|
423
|
+
"See https://github.com/whitphx/streamlit-webrtc#for-users-since-versions-020",
|
413
424
|
DeprecationWarning,
|
414
425
|
stacklevel=2,
|
415
426
|
)
|
@@ -418,24 +429,19 @@ def webrtc_streamer(
|
|
418
429
|
warnings.warn(
|
419
430
|
"The argument async_transform is deprecated. "
|
420
431
|
"Use async_processing instead.\n"
|
421
|
-
"See https://github.com/whitphx/streamlit-webrtc#for-users-since-versions-020",
|
432
|
+
"See https://github.com/whitphx/streamlit-webrtc#for-users-since-versions-020",
|
422
433
|
DeprecationWarning,
|
423
434
|
stacklevel=2,
|
424
435
|
)
|
425
436
|
async_processing = async_transform
|
426
|
-
if
|
437
|
+
if rtc_configuration is not None:
|
427
438
|
warnings.warn(
|
428
|
-
"The argument
|
429
|
-
"Use
|
439
|
+
"The argument rtc_configuration is deprecated. "
|
440
|
+
"Use frontend_rtc_configuration and server_rtc_configuration instead.\n",
|
430
441
|
DeprecationWarning,
|
431
442
|
stacklevel=2,
|
432
443
|
)
|
433
|
-
|
434
|
-
client_settings.get("rtc_configuration") if client_settings else None
|
435
|
-
)
|
436
|
-
media_stream_constraints = (
|
437
|
-
client_settings.get("media_stream_constraints") if client_settings else None
|
438
|
-
)
|
444
|
+
frontend_rtc_configuration = rtc_configuration
|
439
445
|
|
440
446
|
if media_stream_constraints is None:
|
441
447
|
media_stream_constraints = DEFAULT_MEDIA_STREAM_CONSTRAINTS
|
@@ -463,45 +469,17 @@ def webrtc_streamer(
|
|
463
469
|
)
|
464
470
|
st.session_state[key] = context
|
465
471
|
|
466
|
-
if context.
|
467
|
-
context.
|
468
|
-
if context.
|
469
|
-
|
470
|
-
|
471
|
-
):
|
472
|
+
if context._frontend_rtc_configuration is None:
|
473
|
+
context._frontend_rtc_configuration = copy.deepcopy(frontend_rtc_configuration)
|
474
|
+
if context._frontend_rtc_configuration is None:
|
475
|
+
context._frontend_rtc_configuration = {}
|
476
|
+
if context._frontend_rtc_configuration.get("iceServers") is None:
|
472
477
|
LOGGER.info(
|
473
|
-
"
|
478
|
+
"No iceServers found in the rtc_configuration for the frontend. Set the default value to use Google STUN server."
|
474
479
|
)
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
ice_servers = get_hf_ice_servers(hf_token)
|
479
|
-
if context._rtc_configuration is None:
|
480
|
-
context._rtc_configuration = {}
|
481
|
-
LOGGER.info("Successfully got TURN credentials from Hugging Face.")
|
482
|
-
context._rtc_configuration["iceServers"] = ice_servers
|
483
|
-
except Exception as e:
|
484
|
-
LOGGER.error("Failed to get TURN credentials from Hugging Face: %s", e)
|
485
|
-
elif os.getenv("TWILIO_ACCOUNT_SID") and os.getenv("TWILIO_AUTH_TOKEN"):
|
486
|
-
LOGGER.info("Try to use TURN server from Twilio.")
|
487
|
-
twilio_sid = os.getenv("TWILIO_ACCOUNT_SID")
|
488
|
-
twilio_token = os.getenv("TWILIO_AUTH_TOKEN")
|
489
|
-
try:
|
490
|
-
ice_servers = get_twilio_ice_servers(twilio_sid, twilio_token)
|
491
|
-
if context._rtc_configuration is None:
|
492
|
-
context._rtc_configuration = {}
|
493
|
-
LOGGER.info("Successfully got TURN credentials from Twilio.")
|
494
|
-
context._rtc_configuration["iceServers"] = ice_servers
|
495
|
-
except Exception as e:
|
496
|
-
LOGGER.error("Failed to get TURN credentials from Twilio: %s", e)
|
497
|
-
else:
|
498
|
-
LOGGER.info("Use STUN server from Google.")
|
499
|
-
if context._rtc_configuration is None:
|
500
|
-
context._rtc_configuration = {}
|
501
|
-
LOGGER.info("Successfully got STUN server from Google.")
|
502
|
-
context._rtc_configuration["iceServers"] = [
|
503
|
-
{"urls": "stun:stun.l.google.com:19302"}
|
504
|
-
]
|
480
|
+
context._frontend_rtc_configuration["iceServers"] = [
|
481
|
+
{"urls": "stun:stun.l.google.com:19302"}
|
482
|
+
]
|
505
483
|
|
506
484
|
webrtc_worker = context._get_worker()
|
507
485
|
|
@@ -539,8 +517,7 @@ def webrtc_streamer(
|
|
539
517
|
key=frontend_key,
|
540
518
|
sdp_answer_json=sdp_answer_json,
|
541
519
|
mode=mode.name,
|
542
|
-
|
543
|
-
rtc_configuration=context._rtc_configuration,
|
520
|
+
rtc_configuration=context._frontend_rtc_configuration,
|
544
521
|
media_stream_constraints=media_stream_constraints,
|
545
522
|
video_html_attrs=video_html_attrs,
|
546
523
|
audio_html_attrs=audio_html_attrs,
|
@@ -597,8 +574,6 @@ def webrtc_streamer(
|
|
597
574
|
context._set_worker(None)
|
598
575
|
webrtc_worker = None
|
599
576
|
|
600
|
-
context._rtc_configuration = None
|
601
|
-
|
602
577
|
# Rerun to unset the SDP answer from the frontend args
|
603
578
|
rerun()
|
604
579
|
|
@@ -622,8 +597,23 @@ def webrtc_streamer(
|
|
622
597
|
'Create a new worker (key="%s").',
|
623
598
|
key,
|
624
599
|
)
|
600
|
+
|
601
|
+
aiortc_rtc_configuration = (
|
602
|
+
compile_rtc_configuration(server_rtc_configuration)
|
603
|
+
if server_rtc_configuration and isinstance(server_rtc_configuration, dict)
|
604
|
+
else AiortcRTCConfiguration()
|
605
|
+
)
|
606
|
+
|
607
|
+
if aiortc_rtc_configuration.iceServers is None:
|
608
|
+
LOGGER.info(
|
609
|
+
"rtc_configuration.iceServers is not set. Try to set it automatically."
|
610
|
+
)
|
611
|
+
ice_servers = get_available_ice_servers()
|
612
|
+
aiortc_rtc_configuration.iceServers = compile_ice_servers(ice_servers)
|
613
|
+
|
625
614
|
webrtc_worker = WebRtcWorker(
|
626
615
|
mode=mode,
|
616
|
+
rtc_configuration=aiortc_rtc_configuration,
|
627
617
|
player_factory=player_factory,
|
628
618
|
in_recorder_factory=in_recorder_factory,
|
629
619
|
out_recorder_factory=out_recorder_factory,
|
streamlit_webrtc/config.py
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
from typing import Dict, List, Optional, TypedDict, Union
|
1
|
+
from typing import Any, Dict, List, Optional, TypedDict, Union
|
2
|
+
|
3
|
+
from aiortc import (
|
4
|
+
RTCConfiguration as AiortcRTCConfiguration,
|
5
|
+
)
|
6
|
+
from aiortc import (
|
7
|
+
RTCIceServer as AiortcRTCIceServer,
|
8
|
+
)
|
2
9
|
|
3
10
|
RTCIceServer = TypedDict(
|
4
11
|
"RTCIceServer",
|
@@ -15,6 +22,44 @@ class RTCConfiguration(TypedDict, total=False):
|
|
15
22
|
iceServers: Optional[List[RTCIceServer]]
|
16
23
|
|
17
24
|
|
25
|
+
def compile_rtc_ice_server(
|
26
|
+
ice_server: Union[RTCIceServer, dict[str, Any]],
|
27
|
+
) -> AiortcRTCIceServer:
|
28
|
+
if not isinstance(ice_server, dict):
|
29
|
+
raise ValueError("ice_server must be a dict")
|
30
|
+
if "urls" not in ice_server:
|
31
|
+
raise ValueError("ice_server must have a urls key")
|
32
|
+
|
33
|
+
return AiortcRTCIceServer(
|
34
|
+
urls=ice_server["urls"], # type: ignore # aiortc's type def is incorrect
|
35
|
+
username=ice_server.get("username"),
|
36
|
+
credential=ice_server.get("credential"),
|
37
|
+
)
|
38
|
+
|
39
|
+
|
40
|
+
def compile_ice_servers(
|
41
|
+
ice_servers: Union[List[RTCIceServer], List[dict[str, Any]]],
|
42
|
+
) -> List[AiortcRTCIceServer]:
|
43
|
+
return [
|
44
|
+
compile_rtc_ice_server(server)
|
45
|
+
for server in ice_servers
|
46
|
+
if isinstance(server, dict) and "urls" in server
|
47
|
+
]
|
48
|
+
|
49
|
+
|
50
|
+
def compile_rtc_configuration(
|
51
|
+
rtc_configuration: Union[RTCConfiguration, dict[str, Any]],
|
52
|
+
) -> AiortcRTCConfiguration:
|
53
|
+
if not isinstance(rtc_configuration, dict):
|
54
|
+
raise ValueError("rtc_configuration must be a dict")
|
55
|
+
ice_servers = rtc_configuration.get("iceServers", [])
|
56
|
+
if not isinstance(ice_servers, list):
|
57
|
+
raise ValueError("iceServers must be a list")
|
58
|
+
return AiortcRTCConfiguration(
|
59
|
+
iceServers=compile_ice_servers(ice_servers),
|
60
|
+
)
|
61
|
+
|
62
|
+
|
18
63
|
Number = Union[int, float]
|
19
64
|
|
20
65
|
|
streamlit_webrtc/credentials.py
CHANGED
@@ -24,6 +24,7 @@ SOFTWARE.
|
|
24
24
|
# Original: https://github.com/freddyaboulton/fastrtc/blob/66f0a81b76684c5d58761464fb67642891066f93/LICENSE
|
25
25
|
|
26
26
|
import json
|
27
|
+
import logging
|
27
28
|
import os
|
28
29
|
import urllib.error
|
29
30
|
import urllib.request
|
@@ -31,6 +32,8 @@ from typing import List, Optional
|
|
31
32
|
|
32
33
|
from .config import RTCIceServer
|
33
34
|
|
35
|
+
LOGGER = logging.getLogger(__name__)
|
36
|
+
|
34
37
|
|
35
38
|
def get_hf_ice_servers(token: Optional[str] = None) -> List[RTCIceServer]:
|
36
39
|
if token is None:
|
@@ -67,11 +70,35 @@ def get_twilio_ice_servers(
|
|
67
70
|
raise ImportError("Please install twilio with `pip install twilio`")
|
68
71
|
|
69
72
|
if not twilio_sid and not twilio_token:
|
70
|
-
twilio_sid = os.
|
71
|
-
twilio_token = os.
|
73
|
+
twilio_sid = os.getenv("TWILIO_ACCOUNT_SID")
|
74
|
+
twilio_token = os.getenv("TWILIO_AUTH_TOKEN")
|
75
|
+
|
76
|
+
if twilio_sid is None or twilio_token is None:
|
77
|
+
raise ValueError("TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN must be set")
|
72
78
|
|
73
79
|
client = Client(twilio_sid, twilio_token)
|
74
80
|
|
75
81
|
token = client.tokens.create()
|
76
82
|
|
77
83
|
return token.ice_servers
|
84
|
+
|
85
|
+
|
86
|
+
def get_available_ice_servers() -> List[RTCIceServer]:
|
87
|
+
try:
|
88
|
+
LOGGER.info("Try to use TURN server from Hugging Face.")
|
89
|
+
ice_servers = get_hf_ice_servers()
|
90
|
+
LOGGER.info("Successfully got TURN credentials from Hugging Face.")
|
91
|
+
return ice_servers
|
92
|
+
except Exception as e:
|
93
|
+
LOGGER.info("Failed to get TURN credentials from Hugging Face: %s", e)
|
94
|
+
|
95
|
+
try:
|
96
|
+
LOGGER.info("Try to use TURN server from Twilio.")
|
97
|
+
ice_servers = get_twilio_ice_servers()
|
98
|
+
LOGGER.info("Successfully got TURN credentials from Twilio.")
|
99
|
+
return ice_servers
|
100
|
+
except Exception as e:
|
101
|
+
LOGGER.info("Failed to get TURN credentials from Twilio: %s", e)
|
102
|
+
|
103
|
+
LOGGER.info("Use STUN server from Google.")
|
104
|
+
return [RTCIceServer(urls="stun:stun.l.google.com:19302")]
|
streamlit_webrtc/webrtc.py
CHANGED
@@ -6,7 +6,7 @@ import queue
|
|
6
6
|
import threading
|
7
7
|
from typing import Callable, Generic, Literal, Optional, Union, cast
|
8
8
|
|
9
|
-
from aiortc import RTCPeerConnection, RTCSessionDescription
|
9
|
+
from aiortc import RTCConfiguration, RTCPeerConnection, RTCSessionDescription
|
10
10
|
from aiortc.contrib.media import MediaPlayer, MediaRecorder, MediaRelay
|
11
11
|
from aiortc.mediastreams import MediaStreamTrack
|
12
12
|
|
@@ -339,6 +339,7 @@ class WebRtcWorker(Generic[VideoProcessorT, AudioProcessorT]):
|
|
339
339
|
def __init__(
|
340
340
|
self,
|
341
341
|
mode: WebRtcMode,
|
342
|
+
rtc_configuration: Optional[RTCConfiguration],
|
342
343
|
source_video_track: Optional[MediaStreamTrack],
|
343
344
|
source_audio_track: Optional[MediaStreamTrack],
|
344
345
|
player_factory: Optional[MediaPlayerFactory],
|
@@ -359,7 +360,7 @@ class WebRtcWorker(Generic[VideoProcessorT, AudioProcessorT]):
|
|
359
360
|
sendback_audio: bool,
|
360
361
|
) -> None:
|
361
362
|
self._process_offer_thread: Union[threading.Thread, None] = None
|
362
|
-
self.pc = RTCPeerConnection()
|
363
|
+
self.pc = RTCPeerConnection(rtc_configuration)
|
363
364
|
self._answer_queue: queue.Queue = queue.Queue()
|
364
365
|
|
365
366
|
self.mode = mode
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: streamlit-webrtc
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.53.0
|
4
4
|
Summary: Real-time video and audio processing on Streamlit
|
5
5
|
Project-URL: Repository, https://github.com/whitphx/streamlit-webrtc
|
6
6
|
Author-email: "Yuichiro Tachibana (Tsuchiya)" <t.yic.yt@gmail.com>
|
@@ -1,9 +1,9 @@
|
|
1
|
-
streamlit_webrtc/__init__.py,sha256=
|
1
|
+
streamlit_webrtc/__init__.py,sha256=lZzJSUXeHE4Qt3dwSeQ01Hcrf4hUR3f4_rB7Qqyb85g,2397
|
2
2
|
streamlit_webrtc/_compat.py,sha256=43RUwFoGdRBq8EkOdf6inWkl-qogs5lF8tc-sYrVd1s,4128
|
3
|
-
streamlit_webrtc/component.py,sha256=
|
3
|
+
streamlit_webrtc/component.py,sha256=k9O3CwqUddbIU61gVr9gjhjvfspi_F8jm_r-RTC1-W4,26003
|
4
4
|
streamlit_webrtc/components_callbacks.py,sha256=tdrj2TlV8qcexFEdjm4PVkz8JwHffo4A8imoXOtjNHA,2401
|
5
|
-
streamlit_webrtc/config.py,sha256=
|
6
|
-
streamlit_webrtc/credentials.py,sha256=
|
5
|
+
streamlit_webrtc/config.py,sha256=yKFIVjIoX2F62_G2qcDrNYm2Qe_qx1E9E0YqAnAibMo,5544
|
6
|
+
streamlit_webrtc/credentials.py,sha256=XUSAsKfx50VZstknG99dFq_iBYGbutsvHiGIetyvWKM,3725
|
7
7
|
streamlit_webrtc/eventloop.py,sha256=AFmxGlRRxVdl0cTS9pKpRZR2Mnq6v6DgudVZZ425IVw,1333
|
8
8
|
streamlit_webrtc/factory.py,sha256=T35kCwNU8Vm4KL6KJ5HbNVtaouNw13Ilew49XSnm6X8,6820
|
9
9
|
streamlit_webrtc/mix.py,sha256=Uh9gJviP3VLxwBQ-i3RftJ8GQ5qDPGqJKgm2M-vQYo4,8775
|
@@ -16,10 +16,10 @@ streamlit_webrtc/server.py,sha256=5o9E2MRIPoS18lfGPJkyhbd23RWyTwblNVVuAA2kKrA,14
|
|
16
16
|
streamlit_webrtc/session_info.py,sha256=pg_2RFexR18UfwpZT5ENcPfedEiWuAxBuXc2RRuFCaE,2341
|
17
17
|
streamlit_webrtc/shutdown.py,sha256=rbWMhOIrbOBZDlqqBTzCfs4MuHQ0UEhljkNvvXoeTz0,2171
|
18
18
|
streamlit_webrtc/source.py,sha256=haPqMZ50Xh8tg7Z1yN8Frfk8v7D3oOuKteaD59asbzs,2263
|
19
|
-
streamlit_webrtc/webrtc.py,sha256=
|
19
|
+
streamlit_webrtc/webrtc.py,sha256=UBWoa2-u3X3tAaIj3NSUY9Thptk9CH50qeQS-tRY2tY,27278
|
20
20
|
streamlit_webrtc/frontend/dist/index.html,sha256=1iOx-PsDxdqWKzx6SFPeQH17DsdM8NJSkfOm-XjFl5Q,527
|
21
21
|
streamlit_webrtc/frontend/dist/assets/index-1ywg1u80.js,sha256=6DS5LiYVHfQac1QqoUOdw2ALfo86UUrpvdn4Cdz-GaY,582648
|
22
|
-
streamlit_webrtc-0.
|
23
|
-
streamlit_webrtc-0.
|
24
|
-
streamlit_webrtc-0.
|
25
|
-
streamlit_webrtc-0.
|
22
|
+
streamlit_webrtc-0.53.0.dist-info/METADATA,sha256=AwTulfkdVNoYvakEG5jB9dZEwYKNjM_PG8Ht56yC3UU,18640
|
23
|
+
streamlit_webrtc-0.53.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
24
|
+
streamlit_webrtc-0.53.0.dist-info/licenses/LICENSE,sha256=pwccNHVA7r4rYofGlMU10aKEU90GLUlQr8uY80PR0NQ,1081
|
25
|
+
streamlit_webrtc-0.53.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|