Skip to content

Conversation

DeveloperViraj
Copy link

Summary

Fixes issue #403 where WebRTC connections created via the Gradio UI were not visible through the Stream API endpoints.

What Changed

  • Added get_all_connections() in backend/fastrtc/stream.py to aggregate both server-side and UI-created connections.
  • Added /connections FastAPI route inside Stream.mount() to expose all active WebRTC connections.

Why

Ensures consistent connection tracking between UI and API, resolving sync issues in hybrid WebRTC setups.

Testing

  1. Run a FastAPI + Gradio example.
  2. Create a UI connection in the browser.
  3. Call GET /connections → both UI + API connections appear.

Closes #403

@marcusvaltonen
Copy link
Contributor

@DeveloperViraj Thank you for taking a stab at the Issue I raised. However, the scope of the current MR should probably just include the logic in get_all_connections, and revert all removals of comments, added endpoints, etc.

Copy link
Contributor

@marcusvaltonen marcusvaltonen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can heavily reduce the code changes for this MR

except Exception:
for k in wc.connections:
all_ids.add(str(k))
for alt_name in ("_connections", "_conn_map", "active_connections"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When are these naming conventions used? I cannot find them in the current code base.

for k in wc.connections.keys():
all_ids.add(str(k))
except Exception:
for k in wc.connections:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this ever happen?

@DeveloperViraj
Copy link
Author

Updated as per feedback

Reverted to the original structure and retained all comments

Kept the scope minimal, only added the get_all_connections() helper inside Stream

Removed extra endpoints and unrelated edits

Ready for re-review. Thanks for the detailed feedback, @marcusvaltonen 🙏

Copy link
Contributor

@marcusvaltonen marcusvaltonen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments

self.server_rtc_configuration = self.convert_to_aiortc_format(
server_rtc_configuration
)
self.verbose = verbose
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert changes: self.verbose, self._ui shouldn't change

self.verbose = verbose
self._ui = self._generate_default_ui(ui_args)
self._ui.launch = self._wrap_gradio_launch(self._ui.launch)
def get_all_connections(self) -> List[str]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo is using typing hints for Python 3.10+. It is enough (and preferred) to use [str]

self._ui.launch = self._wrap_gradio_launch(self._ui.launch)
def get_all_connections(self) -> List[str]:
all_ids = list(self.connections.keys()) # type: ignore
if self.webrtc_component and hasattr(self.webrtc_component, "connections"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is enough to check that if self.webrtc_component since it is guaranteed to have the attribute connections.

self._ui = self._generate_default_ui(ui_args)
self._ui.launch = self._wrap_gradio_launch(self._ui.launch)
def get_all_connections(self) -> List[str]:
all_ids = list(self.connections.keys()) # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why type ignore?

def get_all_connections(self) -> List[str]:
all_ids = list(self.connections.keys()) # type: ignore
if self.webrtc_component and hasattr(self.webrtc_component, "connections"):
all_ids += list(self.webrtc_component.connections.keys()) # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why type ignore?

self.verbose = verbose
self._ui = self._generate_default_ui(ui_args)
self._ui.launch = self._wrap_gradio_launch(self._ui.launch)
def get_all_connections(self) -> List[str]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing docstring. See e.g., #405

@marcusvaltonen
Copy link
Contributor

These type of things should ideally have unit tests as well, but it is up to @freddyaboulton to decide that.

@DeveloperViraj
Copy link
Author

Hey @marcusvaltonen !
I’ve made the updates based on your feedback:

Moved get_all_connections() out of init

Restored self.verbose, _ui, and _ui.launch

Switched to the modern list[str] type hint

Cleaned up the extra # type: ignore

Added a short docstring

Should be all set now, let me know if anything else needs tweaking

@marcusvaltonen
Copy link
Contributor

Hi @DeveloperViraj!

Thank you for taking time to look at my Issue and implement a possible remedy. I think the MR looks good in terms of finding connections; however, please see my updated discussion in #403, explaining why it does not solve all further downstream tasks, and you still have to rely on some awkward hacking.

I would recommend that we wait for @freddyaboulton to see this and share his thoughts, before you spend too much time going further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stream object does not have direct access to all WebRTC connections when using Gradio UI

2 participants