whitphx HF staff commited on
Commit
1328fff
1 Parent(s): 9f9de5f

Fix all the demos to use Twilio STUN/TURN servers

Browse files
app.py CHANGED
@@ -15,6 +15,7 @@ import streamlit as st
15
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
16
 
17
  from sample_utils.download import download_file
 
18
 
19
  HERE = Path(__file__).parent
20
  ROOT = HERE
@@ -137,7 +138,7 @@ def video_frame_callback(frame: av.VideoFrame) -> av.VideoFrame:
137
  webrtc_ctx = webrtc_streamer(
138
  key="object-detection",
139
  mode=WebRtcMode.SENDRECV,
140
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
141
  video_frame_callback=video_frame_callback,
142
  media_stream_constraints={"video": True, "audio": False},
143
  async_processing=True,
 
15
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
16
 
17
  from sample_utils.download import download_file
18
+ from sample_utils.turn import get_ice_servers
19
 
20
  HERE = Path(__file__).parent
21
  ROOT = HERE
 
138
  webrtc_ctx = webrtc_streamer(
139
  key="object-detection",
140
  mode=WebRtcMode.SENDRECV,
141
+ rtc_configuration={"iceServers": get_ice_servers()},
142
  video_frame_callback=video_frame_callback,
143
  media_stream_constraints={"video": True, "audio": False},
144
  async_processing=True,
pages/10_sendonly_audio.py CHANGED
@@ -11,6 +11,8 @@ import pydub
11
  import streamlit as st
12
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
13
 
 
 
14
  logger = logging.getLogger(__name__)
15
 
16
 
@@ -18,7 +20,7 @@ webrtc_ctx = webrtc_streamer(
18
  key="sendonly-audio",
19
  mode=WebRtcMode.SENDONLY,
20
  audio_receiver_size=256,
21
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
22
  media_stream_constraints={"audio": True},
23
  )
24
 
 
11
  import streamlit as st
12
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
13
 
14
+ from sample_utils.turn import get_ice_servers
15
+
16
  logger = logging.getLogger(__name__)
17
 
18
 
 
20
  key="sendonly-audio",
21
  mode=WebRtcMode.SENDONLY,
22
  audio_receiver_size=256,
23
+ rtc_configuration={"iceServers": get_ice_servers()},
24
  media_stream_constraints={"audio": True},
25
  )
26
 
pages/11_programatic_control_playing.py CHANGED
@@ -3,11 +3,13 @@
3
  import streamlit as st
4
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
5
 
 
 
6
  playing = st.checkbox("Playing", value=True)
7
 
8
  webrtc_streamer(
9
  key="programatic_control",
10
  desired_playing_state=playing,
11
  mode=WebRtcMode.SENDRECV,
12
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
13
  )
 
3
  import streamlit as st
4
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
5
 
6
+ from sample_utils.turn import get_ice_servers
7
+
8
  playing = st.checkbox("Playing", value=True)
9
 
10
  webrtc_streamer(
11
  key="programatic_control",
12
  desired_playing_state=playing,
13
  mode=WebRtcMode.SENDRECV,
14
+ rtc_configuration={"iceServers": get_ice_servers()},
15
  )
pages/12_media_constraints_configs.py CHANGED
@@ -3,11 +3,13 @@
3
  import streamlit as st
4
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
5
 
 
 
6
  frame_rate = 5
7
  webrtc_streamer(
8
  key="media-constraints",
9
  mode=WebRtcMode.SENDRECV,
10
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
11
  media_stream_constraints={
12
  "video": {"frameRate": {"ideal": frame_rate}},
13
  },
 
3
  import streamlit as st
4
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
5
 
6
+ from sample_utils.turn import get_ice_servers
7
+
8
  frame_rate = 5
9
  webrtc_streamer(
10
  key="media-constraints",
11
  mode=WebRtcMode.SENDRECV,
12
+ rtc_configuration={"iceServers": get_ice_servers()},
13
  media_stream_constraints={
14
  "video": {"frameRate": {"ideal": frame_rate}},
15
  },
pages/13_ui_texts_customization.py CHANGED
@@ -1,8 +1,10 @@
1
  from streamlit_webrtc import webrtc_streamer
2
 
 
 
3
  webrtc_streamer(
4
  key="custom_ui_texts",
5
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
6
  translations={
7
  "start": "開始",
8
  "stop": "停止",
 
1
  from streamlit_webrtc import webrtc_streamer
2
 
3
+ from sample_utils.turn import get_ice_servers
4
+
5
  webrtc_streamer(
6
  key="custom_ui_texts",
7
+ rtc_configuration={"iceServers": get_ice_servers()},
8
  translations={
9
  "start": "開始",
10
  "stop": "停止",
pages/2_opencv_filters.py CHANGED
@@ -5,6 +5,8 @@ import cv2
5
  import streamlit as st
6
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
7
 
 
 
8
  _type = st.radio("Select transform type", ("noop", "cartoon", "edges", "rotate"))
9
 
10
 
@@ -49,7 +51,7 @@ def callback(frame: av.VideoFrame) -> av.VideoFrame:
49
  webrtc_streamer(
50
  key="opencv-filter",
51
  mode=WebRtcMode.SENDRECV,
52
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
53
  video_frame_callback=callback,
54
  media_stream_constraints={"video": True, "audio": False},
55
  async_processing=True,
 
5
  import streamlit as st
6
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
7
 
8
+ from sample_utils.turn import get_ice_servers
9
+
10
  _type = st.radio("Select transform type", ("noop", "cartoon", "edges", "rotate"))
11
 
12
 
 
51
  webrtc_streamer(
52
  key="opencv-filter",
53
  mode=WebRtcMode.SENDRECV,
54
+ rtc_configuration={"iceServers": get_ice_servers()},
55
  video_frame_callback=callback,
56
  media_stream_constraints={"video": True, "audio": False},
57
  async_processing=True,
pages/3_audio_filter.py CHANGED
@@ -4,6 +4,8 @@ import pydub
4
  import streamlit as st
5
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
6
 
 
 
7
  gain = st.slider("Gain", -10.0, +20.0, 1.0, 0.05)
8
 
9
 
@@ -32,7 +34,7 @@ def process_audio(frame: av.AudioFrame) -> av.AudioFrame:
32
  webrtc_streamer(
33
  key="audio-filter",
34
  mode=WebRtcMode.SENDRECV,
35
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
36
  audio_frame_callback=process_audio,
37
  async_processing=True,
38
  )
 
4
  import streamlit as st
5
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
6
 
7
+ from sample_utils.turn import get_ice_servers
8
+
9
  gain = st.slider("Gain", -10.0, +20.0, 1.0, 0.05)
10
 
11
 
 
34
  webrtc_streamer(
35
  key="audio-filter",
36
  mode=WebRtcMode.SENDRECV,
37
+ rtc_configuration={"iceServers": get_ice_servers()},
38
  audio_frame_callback=process_audio,
39
  async_processing=True,
40
  )
pages/4_delayed_echo.py CHANGED
@@ -6,6 +6,8 @@ import av
6
  import streamlit as st
7
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
8
 
 
 
9
  logger = logging.getLogger(__name__)
10
 
11
 
@@ -34,7 +36,7 @@ async def queued_audio_frames_callback(
34
  webrtc_streamer(
35
  key="delay",
36
  mode=WebRtcMode.SENDRECV,
37
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
38
  queued_video_frames_callback=queued_video_frames_callback,
39
  queued_audio_frames_callback=queued_audio_frames_callback,
40
  async_processing=True,
 
6
  import streamlit as st
7
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
8
 
9
+ from sample_utils.turn import get_ice_servers
10
+
11
  logger = logging.getLogger(__name__)
12
 
13
 
 
36
  webrtc_streamer(
37
  key="delay",
38
  mode=WebRtcMode.SENDRECV,
39
+ rtc_configuration={"iceServers": get_ice_servers()},
40
  queued_video_frames_callback=queued_video_frames_callback,
41
  queued_audio_frames_callback=queued_audio_frames_callback,
42
  async_processing=True,
pages/5_fork_multi_outputs.py CHANGED
@@ -10,6 +10,8 @@ import cv2
10
  import streamlit as st
11
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
12
 
 
 
13
  st.markdown(
14
  """
15
  Fork one input to multiple outputs with different video filters.
@@ -60,7 +62,7 @@ def make_video_frame_callback(_type: VideoFilterType):
60
  return callback
61
 
62
 
63
- COMMON_RTC_CONFIG = {"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]}
64
 
65
  st.header("Input")
66
  ctx = webrtc_streamer(
 
10
  import streamlit as st
11
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
12
 
13
+ from sample_utils.turn import get_ice_servers
14
+
15
  st.markdown(
16
  """
17
  Fork one input to multiple outputs with different video filters.
 
62
  return callback
63
 
64
 
65
+ COMMON_RTC_CONFIG = {"iceServers": get_ice_servers()}
66
 
67
  st.header("Input")
68
  ctx = webrtc_streamer(
pages/6_mix_multi_inputs.py CHANGED
@@ -17,6 +17,8 @@ from streamlit_webrtc import (
17
  webrtc_streamer,
18
  )
19
 
 
 
20
  st.markdown(
21
  """
22
  Mix multiple inputs with different video filters into one stream.
@@ -112,7 +114,7 @@ def mixer_callback(frames: List[av.VideoFrame]) -> av.VideoFrame:
112
  return new_frame
113
 
114
 
115
- COMMON_RTC_CONFIG = {"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]}
116
 
117
  st.header("Input 1")
118
  input1_ctx = webrtc_streamer(
 
17
  webrtc_streamer,
18
  )
19
 
20
+ from sample_utils.turn import get_ice_servers
21
+
22
  st.markdown(
23
  """
24
  Mix multiple inputs with different video filters into one stream.
 
114
  return new_frame
115
 
116
 
117
+ COMMON_RTC_CONFIG = {"iceServers": get_ice_servers()}
118
 
119
  st.header("Input 1")
120
  input1_ctx = webrtc_streamer(
pages/7_record.py CHANGED
@@ -7,6 +7,8 @@ import streamlit as st
7
  from aiortc.contrib.media import MediaRecorder
8
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
9
 
 
 
10
 
11
  def video_frame_callback(frame: av.VideoFrame) -> av.VideoFrame:
12
  img = frame.to_ndarray(format="bgr24")
@@ -39,7 +41,7 @@ def app():
39
  webrtc_streamer(
40
  key="record",
41
  mode=WebRtcMode.SENDRECV,
42
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
43
  media_stream_constraints={
44
  "video": True,
45
  "audio": True,
 
7
  from aiortc.contrib.media import MediaRecorder
8
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
9
 
10
+ from sample_utils.turn import get_ice_servers
11
+
12
 
13
  def video_frame_callback(frame: av.VideoFrame) -> av.VideoFrame:
14
  img = frame.to_ndarray(format="bgr24")
 
41
  webrtc_streamer(
42
  key="record",
43
  mode=WebRtcMode.SENDRECV,
44
+ rtc_configuration={"iceServers": get_ice_servers()},
45
  media_stream_constraints={
46
  "video": True,
47
  "audio": True,
pages/8_media_files_streaming.py CHANGED
@@ -10,6 +10,7 @@ from aiortc.contrib.media import MediaPlayer
10
  from streamlit_webrtc import WebRtcMode, WebRtcStreamerContext, webrtc_streamer
11
 
12
  from sample_utils.download import download_file
 
13
 
14
  HERE = Path(__file__).parent
15
  ROOT = HERE.parent
@@ -112,7 +113,7 @@ def video_frame_callback(frame: av.VideoFrame) -> av.VideoFrame:
112
  webrtc_streamer(
113
  key=key,
114
  mode=WebRtcMode.RECVONLY,
115
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
116
  media_stream_constraints={
117
  "video": media_file_info["type"] == "video",
118
  "audio": media_file_info["type"] == "audio",
 
10
  from streamlit_webrtc import WebRtcMode, WebRtcStreamerContext, webrtc_streamer
11
 
12
  from sample_utils.download import download_file
13
+ from sample_utils.turn import get_ice_servers
14
 
15
  HERE = Path(__file__).parent
16
  ROOT = HERE.parent
 
113
  webrtc_streamer(
114
  key=key,
115
  mode=WebRtcMode.RECVONLY,
116
+ rtc_configuration={"iceServers": get_ice_servers()},
117
  media_stream_constraints={
118
  "video": media_file_info["type"] == "video",
119
  "audio": media_file_info["type"] == "audio",
pages/9_sendonly_video.py CHANGED
@@ -7,13 +7,15 @@ import queue
7
  import streamlit as st
8
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
9
 
 
 
10
  logger = logging.getLogger(__name__)
11
 
12
 
13
  webrtc_ctx = webrtc_streamer(
14
  key="video-sendonly",
15
  mode=WebRtcMode.SENDONLY,
16
- rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
17
  media_stream_constraints={"video": True},
18
  )
19
 
 
7
  import streamlit as st
8
  from streamlit_webrtc import WebRtcMode, webrtc_streamer
9
 
10
+ from sample_utils.turn import get_ice_servers
11
+
12
  logger = logging.getLogger(__name__)
13
 
14
 
15
  webrtc_ctx = webrtc_streamer(
16
  key="video-sendonly",
17
  mode=WebRtcMode.SENDONLY,
18
+ rtc_configuration={"iceServers": get_ice_servers()},
19
  media_stream_constraints={"video": True},
20
  )
21
 
sample_utils/turn.py CHANGED
@@ -1,17 +1,25 @@
1
  import logging
2
  import os
3
 
4
- from twilio.rest import Client
5
  import streamlit as st
 
6
 
7
  logger = logging.getLogger(__name__)
8
 
9
 
10
  @st.cache_data
11
  def get_ice_servers():
 
 
 
 
 
 
 
 
12
  try:
13
- account_sid = os.environ['TWILIO_ACCOUNT_SID']
14
- auth_token = os.environ['TWILIO_AUTH_TOKEN']
15
  except KeyError:
16
  logger.warning(
17
  "Twilio credentials are not set. Fallback to a free STUN server from Google." # noqa: E501
 
1
  import logging
2
  import os
3
 
 
4
  import streamlit as st
5
+ from twilio.rest import Client
6
 
7
  logger = logging.getLogger(__name__)
8
 
9
 
10
  @st.cache_data
11
  def get_ice_servers():
12
+ """Use Twilio's TURN server because Streamlit Community Cloud has changed
13
+ its infrastructure and WebRTC connection cannot be established without TURN server now. # noqa: E501
14
+ We considered Open Relay Project (https://www.metered.ca/tools/openrelay/) too,
15
+ but it is not stable and hardly works as some people reported like https://github.com/aiortc/aiortc/issues/832#issuecomment-1482420656 # noqa: E501
16
+ See https://github.com/whitphx/streamlit-webrtc/issues/1213
17
+ """
18
+
19
+ # Ref: https://www.twilio.com/docs/stun-turn/api
20
  try:
21
+ account_sid = os.environ["TWILIO_ACCOUNT_SID"]
22
+ auth_token = os.environ["TWILIO_AUTH_TOKEN"]
23
  except KeyError:
24
  logger.warning(
25
  "Twilio credentials are not set. Fallback to a free STUN server from Google." # noqa: E501