whitphx / streamlit-webrtc

Real-time video and audio processing on Streamlit
https://discuss.streamlit.io/t/new-component-streamlit-webrtc-a-new-way-to-deal-with-real-time-media-streams/8669
MIT License
1.36k stars 182 forks source link

Camera not working with ssh bindigs #832

Closed nicolalandro closed 2 years ago

nicolalandro commented 2 years ago

I run streamlit on a server at 127.0.0.1 and after I bind it in local via ssh, streamlit work good, also if I select the webcam I can see the preview correctly but when I click start It does not work. Maybe that issue can be related to camera not working on hosted streamlit site?

My python error log is the following:

...
2022-04-27 13:35:25.940 Exception in callback Transaction.__retry()
handle: <TimerHandle when=6210564.143044465 Transaction.__retry()>
Traceback (most recent call last):
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 1002, in sendto
    self._sock.sendto(data, addr)
AttributeError: 'NoneType' object has no attribute 'sendto'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "/home/supreme/nic/wash_youy_hand/django_wyh/venv/lib/python3.7/site-packages/aioice/stun.py", line 309, in __retry
    self.__protocol.send_stun(self.__request, self.__addr)
  File "/home/supreme/nic/wash_youy_hand/django_wyh/venv/lib/python3.7/site-packages/aioice/ice.py", line 243, in send_stun
    self.transport.sendto(bytes(message), addr)
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 1011, in sendto
    exc, 'Fatal write error on datagram transport')
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 677, in _fatal_error
    self._loop.call_exception_handler({
AttributeError: 'NoneType' object has no attribute 'call_exception_handler'
2022-04-27 13:35:27.664 Track audio received
2022-04-27 13:35:27.664 Add a track <aiortc.rtcrtpreceiver.RemoteStreamTrack object at 0x7f68dc606a90> of kind audio to <aiortc.rtcpeerconnection.RTCPeerConnection object at 0x7f68f402a250>
2022-04-27 13:35:27.664 Track video received
2022-04-27 13:35:27.664 Add a track <aiortc.rtcrtpreceiver.RemoteStreamTrack object at 0x7f68dc5d2690> of kind video to <aiortc.rtcpeerconnection.RTCPeerConnection object at 0x7f68f402a250>
2022-04-27 13:35:27.689 Connection(14) Check CandidatePair(('193.206.183.137', 34024) -> ('192.168.1.202', 57480)) State.FROZEN -> State.WAITING
2022-04-27 13:35:27.689 Connection(14) Check CandidatePair(('172.17.0.1', 32858) -> ('192.168.1.202', 57480)) State.FROZEN -> State.WAITING
2022-04-27 13:35:27.689 ICE connection state is checking
2022-04-27 13:35:27.689 Connection(14) Check CandidatePair(('193.206.183.137', 34024) -> ('192.168.1.202', 57480)) State.WAITING -> State.IN_PROGRESS
2022-04-27 13:35:28.210 Connection(14) Check CandidatePair(('172.17.0.1', 32858) -> ('192.168.1.202', 57480)) State.WAITING -> State.IN_PROGRESS
2022-04-27 13:35:43.741 ICE connection state is closed
2022-04-27 13:35:59.218 Exception in callback Transaction.__retry()
handle: <TimerHandle when=6210597.419380681 Transaction.__retry()>
Traceback (most recent call last):
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 1002, in sendto
    self._sock.sendto(data, addr)
AttributeError: 'NoneType' object has no attribute 'sendto'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "/home/supreme/nic/wash_youy_hand/django_wyh/venv/lib/python3.7/site-packages/aioice/stun.py", line 309, in __retry
    self.__protocol.send_stun(self.__request, self.__addr)
  File "/home/supreme/nic/wash_youy_hand/django_wyh/venv/lib/python3.7/site-packages/aioice/ice.py", line 243, in send_stun
    self.transport.sendto(bytes(message), addr)
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 1011, in sendto
    exc, 'Fatal write error on datagram transport')
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 677, in _fatal_error
    self._loop.call_exception_handler({
AttributeError: 'NoneType' object has no attribute 'call_exception_handler'
2022-04-27 13:35:59.946 Exception in callback Transaction.__retry()
handle: <TimerHandle when=6210598.148990241 Transaction.__retry()>
Traceback (most recent call last):
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 1002, in sendto
    self._sock.sendto(data, addr)
AttributeError: 'NoneType' object has no attribute 'sendto'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "/home/supreme/nic/wash_youy_hand/django_wyh/venv/lib/python3.7/site-packages/aioice/stun.py", line 309, in __retry
    self.__protocol.send_stun(self.__request, self.__addr)
  File "/home/supreme/nic/wash_youy_hand/django_wyh/venv/lib/python3.7/site-packages/aioice/ice.py", line 243, in send_stun
    self.transport.sendto(bytes(message), addr)
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 1011, in sendto
    exc, 'Fatal write error on datagram transport')
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 677, in _fatal_error
    self._loop.call_exception_handler({
AttributeError: 'NoneType' object has no attribute 'call_exception_handler'

And into the browser I can see:

...
index.ts:192 iceconnectionstatechange disconnected
index.ts:142 RTCConfiguration: {}
index.ts:160 MediaStreamConstraints: {audio: {…}, video: {…}}
index.ts:189 transceivers (2) [RTCRtpTransceiver, RTCRtpTransceiver]
index.ts:20 Created offer: RTCSessionDescription {type: 'offer', sdp: 'v=0\r\no=- 6734696340128911811 2 IN IP4 127.0.0.1\r\ns…1262 label:73d0a03a-221a-452a-8882-dbbad8b89b3e\r\n'}
index.ts:24 Wait for ICE gethering...
index.ts:239 Receive answer sdpOffer {sdp: 'v=0\r\no=- 3860047952 3860047952 IN IP4 0.0.0.0\r\ns=-…D:6A:78:B0:8C:FB:4F:2A:5F:81:EB\r\na=setup:active\r\n', type: 'answer'}
index.ts:192 iceconnectionstatechange checking
index.ts:242 Remote description is set
reducer.ts:95 Send SDP offer RTCSessionDescription {type: 'offer', sdp: 'v=0\r\no=- 6734696340128911811 2 IN IP4 127.0.0.1\r\ns…1262 label:73d0a03a-221a-452a-8882-dbbad8b89b3e\r\n'}
index.ts:192 iceconnectionstatechange disconnected
nicolalandro commented 2 years ago

I solved it by adding RTC config:

from streamlit_webrtc import webrtc_streamer, WebRtcMode, RTCConfiguration

RTC_CONFIGURATION = RTCConfiguration(
    {"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]}
)

webrtc_ctx = webrtc_streamer(
    key="WYH",
    mode=WebRtcMode.SENDRECV,
    rtc_configuration=RTC_CONFIGURATION,
    media_stream_constraints={"video": True, "audio": False},
    async_processing=False,
)

What exactly do this configuration?

whitphx commented 2 years ago

This article section would be an entry point for this topic.

Python WebRTC basics with aiortc may also helps to understand WebRTC basics and what this extension is doing.

For more details, please google the keyword such as "WebRTC STUN server". You will find articles like https://www.3cx.com/pbx/what-is-a-stun-server/.