### Simple Loopback Example Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/index.md A basic example demonstrating a simple loopback of the video stream. This is a good starting point to verify the installation and basic functionality. ```python import streamlit as st from streamlit_webrtc import webrtc_streamer webrtc_streamer(key="loopback") ``` -------------------------------- ### Install streamlit-webrtc Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Install the library using pip. ```bash pip install streamlit-webrtc ``` -------------------------------- ### Install Dependencies Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Use this command to install project dependencies. ```bash uv sync ``` -------------------------------- ### Install Streamlit and Streamlit-WebRTC Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/index.md Install the necessary libraries using pip. This is the first step to using streamlit-webrtc. ```bash pip install streamlit streamlit-webrtc ``` -------------------------------- ### Install Dependencies with uv Source: https://github.com/whitphx/streamlit-webrtc/blob/main/CONTRIBUTING.md Installs project dependencies using the uv package manager. Ensure uv is installed and dependencies are listed in the project configuration. ```shell $ uv sync ``` -------------------------------- ### Start Frontend Development Server Source: https://github.com/whitphx/streamlit-webrtc/blob/main/CLAUDE.md Navigates to the frontend directory and starts the Vite development server. Ensure _RELEASE is set to False in streamlit_webrtc/component.py for development. ```bash # Set _RELEASE = False in streamlit_webrtc/component.py (development only, don't commit) # Start frontend dev server cd streamlit_webrtc/frontend pnpm dev ``` -------------------------------- ### Install Pre-commit Hooks Source: https://github.com/whitphx/streamlit-webrtc/blob/main/CONTRIBUTING.md Installs the pre-commit framework to manage and run pre-commit hooks. This ensures code quality and consistency before commits are made. ```shell $ pre-commit install ``` -------------------------------- ### Install streamlit-webrtc Source: https://github.com/whitphx/streamlit-webrtc/blob/main/README.md Install the streamlit-webrtc library using pip. This command ensures you have the latest version. ```shell pip install -U streamlit-webrtc ``` -------------------------------- ### Run Local Frontend Development Server Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Starts the local frontend development server. Ensure `_RELEASE = False` is set in `streamlit_webrtc/component.py` (do not commit this change). ```bash cd streamlit_webrtc/frontend && pnpm dev ``` -------------------------------- ### Install Git Hooks Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Installs Git hooks to enforce code quality and consistency before commits. ```bash pre-commit install ``` -------------------------------- ### Basic Streamlit-WebRTC App Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/tutorial.md Demonstrates the fundamental setup for a Streamlit-WebRTC application. Requires the `key` argument for `webrtc_streamer()`. ```python from streamlit_webrtc import webrtc_streamer webrtc_streamer(key="sample") ``` -------------------------------- ### Run Frontend Development Server Source: https://github.com/whitphx/streamlit-webrtc/blob/main/CONTRIBUTING.md Starts the frontend development server for streamlit-webrtc. This is used when `_RELEASE` is set to `False` in `streamlit_webrtc/component.py` for live frontend updates. ```shell cd streamlit_webrtc/frontend pnpm dev ``` -------------------------------- ### Basic Streamlit WebRTC Loopback Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Minimal example to stream webcam/microphone back to the browser unchanged. The `webrtc_streamer` function returns a context object to check the stream state. ```python import streamlit as st from streamlit_webrtc import webrtc_streamer, WebRtcMode import av # Minimal loopback — streams webcam/mic back to the browser unchanged ctx = webrtc_streamer(key="loopback") # Check playback state if ctx.state.playing: st.write("Stream is live!") ``` -------------------------------- ### Run Streamlit Application Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Starts the Streamlit application in a separate terminal. ```bash streamlit run home.py ``` -------------------------------- ### Configure STUN Server for Remote Deployment Source: https://github.com/whitphx/streamlit-webrtc/blob/main/README.md Add this `rtc_configuration` to your `webrtc_streamer` call to enable media stream connections when deployed on remote hosts. This example uses Google's public STUN server. ```python webrtc_streamer( # ... rtc_configuration={ "iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}] } # ... ) ``` -------------------------------- ### Serve App via HTTPS with ssl-proxy Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/deployment.md Use this tool during development to serve your Streamlit app over HTTPS. Ensure your app is running locally before starting the proxy. ```bash # Assume your app is running on http://localhost:8501 streamlit run your_app.py # Then, after downloading the binary from the GitHub page above to ./ssl-proxy ./ssl-proxy -from 0.0.0.0:8000 -to 127.0.0.1:8501 # Then access https://localhost:8000 ``` -------------------------------- ### Video Frame Processing with Callback Source: https://github.com/whitphx/streamlit-webrtc/blob/main/README.md Processes video frames by defining a callback function to manipulate them. This example vertically flips the video frames. The callback receives and returns an av.VideoFrame instance. ```python from streamlit_webrtc import webrtc_streamer import av def video_frame_callback(frame): img = frame.to_ndarray(format="bgr24") flipped = img[::-1,:,:] return av.VideoFrame.from_ndarray(flipped, format="bgr24") webrtc_streamer(key="example", video_frame_callback=video_frame_callback) ``` -------------------------------- ### webrtc_streamer with rtc_configuration Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Configures ICE servers for NAT traversal. Examples show using Google's public STUN server, Twilio's TURN servers, and Hugging Face's TURN servers. ```APIDOC ## webrtc_streamer with rtc_configuration ### Description Configures ICE servers for NAT traversal when hosting on remote/cloud servers. Both frontend (browser) and server-side (aiortc) can be configured independently. ### Method `webrtc_streamer` ### Parameters #### Keyword Arguments - **key** (str) - Required - A unique key for the streamlit component. - **rtc_configuration** (dict) - Optional - ICE servers configuration. ### Request Example ```python import os from streamlit_webrtc import webrtc_streamer, get_twilio_ice_servers # Option 1: Google's public STUN server webrtc_streamer( key="stun-only", rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]} ) # Option 2: Twilio TURN servers ice_servers = get_twilio_ice_servers( twilio_sid=os.environ["TWILIO_ACCOUNT_SID"], twilio_token=os.environ["TWILIO_AUTH_TOKEN"], ) webrtc_streamer( key="turn-enabled", rtc_configuration={"iceServers": ice_servers}, ) # Option 3: Hugging Face TURN server from streamlit_webrtc import get_hf_ice_servers ice_servers = get_hf_ice_servers(token=os.environ["HF_TOKEN"]) webrtc_streamer(key="hf-turn", rtc_configuration={"iceServers": ice_servers}) ``` ``` -------------------------------- ### webrtc_streamer with desired_playing_state Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Allows the Python script to start or stop the WebRTC stream programmatically based on application logic rather than user button clicks. ```APIDOC ## webrtc_streamer with desired_playing_state ### Description Allows the Python script to start or stop the WebRTC stream programmatically based on application logic rather than user button clicks. ### Method `webrtc_streamer` ### Parameters #### Keyword Arguments - **key** (str) - Required - A unique key for the streamlit component. - **desired_playing_state** (bool) - Optional - Programmatically control the playing state of the stream. - **mode** (WebRtcMode) - Optional - The mode of the WebRTC stream (e.g., SENDRECV). ### Request Example ```python import streamlit as st from streamlit_webrtc import webrtc_streamer, WebRtcMode playing = st.checkbox("Enable camera", value=True) webrtc_streamer( key="programmatic", desired_playing_state=playing, mode=WebRtcMode.SENDRECV, ) ``` ``` -------------------------------- ### Programmatic Play/Stop Control Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Control the WebRTC stream's playing state programmatically using the `desired_playing_state` parameter, allowing the Python script to start or stop the stream based on application logic. ```python import streamlit as st from streamlit_webrtc import webrtc_streamer, WebRtcMode playing = st.checkbox("Enable camera", value=True) webrtc_streamer( key="programmatic", desired_playing_state=playing, mode=WebRtcMode.SENDRECV, ) ``` -------------------------------- ### Perform Full Project Build Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Executes a full build of the project. ```bash make build ``` -------------------------------- ### Format Code Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Run this command to format both backend and frontend code before committing changes. ```bash make format ``` -------------------------------- ### Run Frontend Tests Source: https://github.com/whitphx/streamlit-webrtc/blob/main/CLAUDE.md Navigates to the frontend directory and runs frontend tests using Vitest. ```bash cd streamlit_webrtc/frontend pnpm test ``` -------------------------------- ### Run Frontend Tests Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Executes frontend tests. ```bash cd streamlit_webrtc/frontend && pnpm test ``` -------------------------------- ### Build Frontend Only Source: https://github.com/whitphx/streamlit-webrtc/blob/main/CLAUDE.md Builds only the frontend part of the streamlit-webrtc package. ```bash cd streamlit_webrtc/frontend pnpm run build ``` -------------------------------- ### Configure TURN Server with Twilio Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/deployment.md Integrate Twilio's Network Traversal Service for TURN server configuration. This provides a stable and easy-to-use solution for media streaming in challenging network environments. Ensure Twilio credentials are set as environment variables. ```python ## This sample code is from https://www.twilio.com/docs/stun-turn # Download the helper library from https://www.twilio.com/docs/python/install import os from twilio.rest import Client # Find your Account SID and Auth Token at twilio.com/console # and set the environment variables. See http://twil.io/secure account_sid = os.environ['TWILIO_ACCOUNT_SID'] auth_token = os.environ['TWILIO_AUTH_TOKEN'] client = Client(account_sid, auth_token) token = client.tokens.create() # Then, pass the ICE server information to webrtc_streamer(). webrtc_streamer( # ... rtc_configuration={ "iceServers": token.ice_servers } # ... ) ``` -------------------------------- ### Configure STUN Server for Remote Deployment Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/deployment.md Configure the STUN server using the `rtc_configuration` argument in `webrtc_streamer`. This is crucial for establishing media streaming connections when the server is hosted remotely. ```python --8<-- "./examples/deployment/05_stun_config.py" ``` -------------------------------- ### Format Backend Code with Ruff Source: https://github.com/whitphx/streamlit-webrtc/blob/main/CLAUDE.md Formats the backend Python code using Ruff. This command can be run individually or as part of the 'make format' command. ```bash uv run ruff format . ``` -------------------------------- ### Format Frontend Code Source: https://github.com/whitphx/streamlit-webrtc/blob/main/CLAUDE.md Formats the frontend code using pnpm. This command can be run individually or as part of the 'make format' command. ```bash cd streamlit_webrtc/frontend pnpm format ``` -------------------------------- ### Configure ICE Servers for NAT Traversal Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Use `rtc_configuration` to set up STUN/TURN servers for NAT traversal. Google's public STUN server is suitable for basic cases, while Twilio or Hugging Face TURN servers are recommended for deployment on platforms like Streamlit Community Cloud. ```python import os from streamlit_webrtc import webrtc_streamer, get_twilio_ice_servers # Option 1: Google's public STUN server (basic NAT traversal) webrtc_streamer( key="stun-only", rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]} ) # Option 2: Twilio TURN servers (required for Streamlit Community Cloud) ice_servers = get_twilio_ice_servers( twilio_sid=os.environ["TWILIO_ACCOUNT_SID"], twilio_token=os.environ["TWILIO_AUTH_TOKEN"], ) webrtc_streamer( key="turn-enabled", rtc_configuration={"iceServers": ice_servers}, ) # Option 3: Hugging Face TURN server from streamlit_webrtc import get_hf_ice_servers ice_servers = get_hf_ice_servers(token=os.environ["HF_TOKEN"]) webrtc_streamer(key="hf-turn", rtc_configuration={"iceServers": ice_servers}) ``` -------------------------------- ### Perform Frontend-Only Build Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Builds only the frontend components of the project. ```bash cd streamlit_webrtc/frontend && pnpm run build ``` -------------------------------- ### Passing Parameters to Video Callback Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/tutorial.md Illustrates how to pass parameters, like a boolean flag, to the video processing callback to control its behavior. The callback function must accept these parameters. ```python import av from streamlit_webrtc import webrtc_streamer, VideoTransformerBase import streamlit as st class FlippingTransformer(VideoTransformerBase): type = "flip" def __init__(self): self.is_flipped = True def transform(self, frame): if self.is_flipped: return frame.reaframing_from_ndarray(frame.to_ndarray()[::-1, :]) return frame app = webrtc_streamer(key="sample", video_transformer_factory=FlippingTransformer) if app.video_transformer: if st.checkbox("Flip video", value=app.video_transformer.is_flipped): app.video_transformer.is_flipped = True else: app.video_transformer.is_flipped = False ``` -------------------------------- ### Configuring Streaming Direction with WebRtcMode Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Demonstrates how to control the media flow direction using `WebRtcMode`. Options include full-duplex (SENDRECV), sending only (SENDONLY), and receiving only (RECVONLY). ```python from streamlit_webrtc import WebRtcMode, webrtc_streamer # SENDRECV (default) — browser sends, server processes, sends back webrtc_streamer(key="full-duplex", mode=WebRtcMode.SENDRECV) # SENDONLY — browser sends to server; nothing sent back (e.g., recording/analysis) webrtc_streamer(key="capture-only", mode=WebRtcMode.SENDONLY) # RECVONLY — server generates/sources media, browser receives only webrtc_streamer(key="playback-only", mode=WebRtcMode.RECVONLY) ``` -------------------------------- ### Adding Video Processing with Callback Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/tutorial.md Shows how to add video processing by defining a callback function passed to `video_frame_callback`. The callback receives and returns `av.VideoFrame` objects. ```python import av from streamlit_webrtc import webrtc_streamer, VideoTransformerBase class FlippingTransformer(VideoTransformerBase): def transform(self, frame): return frame.reaframing_from_ndarray(frame.to_ndarray()[::-1, :]) webrtc_streamer(key="sample", video_transformer_factory=FlippingTransformer) ``` -------------------------------- ### Create Changelog Fragment Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Generates a changelog fragment for a Pull Request. Use `--edit` to open an editor for manual content creation. ```bash scriv create ``` ```bash scriv create --edit ``` -------------------------------- ### Real-time Video and Audio Processing Source: https://github.com/whitphx/streamlit-webrtc/blob/main/docs/index.md Process both video and audio frames simultaneously using custom callback functions. This allows for synchronized media processing. ```python import av import streamlit as st from streamlit_webrtc import VideoTransformerBase, AudioProcessorBase, webrtc_streamer class BothTransformer(VideoTransformerBase, AudioProcessorBase): def transform(self, frame): # Process video frame img = frame.to_ndarray(format="bgr24") # ... video processing logic ... return av.VideoFrame.from_ndarray(img, format="bgr24") def recv(self, frame): # Process audio frame audio = frame.to_ndarray() # ... audio processing logic ... return av.AudioFrame.from_ndarray(audio, layout=frame.layout, samples=frame.samples) webrtc_streamer(key="both_transformer", transcoder_config=None, video_transformer=BothTransformer(), audio_processor=BothTransformer()) ``` -------------------------------- ### Fetch Hugging Face ICE Servers Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Retrieve TURN credentials from the Hugging Face FastRTC server using `get_hf_ice_servers` and an HF API token. Results are cached for 1 hour. ```python import os from streamlit_webrtc import get_hf_ice_servers, webrtc_streamer ice_servers = get_hf_ice_servers(token=os.environ["HF_TOKEN"]) webrtc_streamer( key="hf-app", rtc_configuration={"iceServers": ice_servers}, ) ``` -------------------------------- ### Create Programmatic Video Source Track Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Use `create_video_source_track` to generate video frames from a Python callback. The callback receives presentation timestamp and time base, and must return an `av.VideoFrame`. This is useful for pushing server-generated video to the browser in `RECVONLY` mode. ```python import fractions import time import av import cv2 import numpy as np from streamlit_webrtc import WebRtcMode, create_video_source_track, webrtc_streamer import streamlit as st fps = st.slider("FPS", 1, 30, 30) def video_source_callback(pts: int, time_base: fractions.Fraction) -> av.VideoFrame: buffer = np.zeros((480, 640, 3), dtype=np.uint8) buffer = cv2.putText(buffer, f"time: {time.time():.2f}", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 2) return av.VideoFrame.from_ndarray(buffer, format="bgr24") video_source_track = create_video_source_track( video_source_callback, key="gen-video", fps=fps ) def on_change(): ctx = st.session_state["player"] if not ctx.state.playing and not ctx.state.signalling: video_source_track.stop() webrtc_streamer( key="player", mode=WebRtcMode.RECVONLY, source_video_track=video_source_track, media_stream_constraints={"video": True, "audio": False}, on_change=on_change, ) ``` -------------------------------- ### Implement Stateful Video Processing Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Subclass `VideoProcessorBase` to create stateful video processors. Override the `recv()` method to process incoming frames. An instance is created per session via `video_processor_factory`, and the live instance can be accessed through `ctx.video_processor` for state mutation. ```python import av import streamlit as st from streamlit_webrtc import VideoProcessorBase, webrtc_streamer class BlurProcessor(VideoProcessorBase): def __init__(self): import cv2 self._cv2 = cv2 self.ksize = 15 # mutable from main thread def recv(self, frame: av.VideoFrame) -> av.VideoFrame: img = frame.to_ndarray(format="bgr24") blurred = self._cv2.GaussianBlur(img, (self.ksize | 1, self.ksize | 1), 0) return av.VideoFrame.from_ndarray(blurred, format="bgr24") ctx = webrtc_streamer( key="blur", video_processor_factory=BlurProcessor, ) if ctx.video_processor: # Mutate processor state from the main thread while it's running ctx.video_processor.ksize = st.slider("Blur kernel", 1, 51, 15, 2) ``` -------------------------------- ### Fetch Twilio ICE Servers Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Use `get_twilio_ice_servers` to obtain time-limited STUN/TURN credentials from Twilio. These are cached for 1 hour and returned as a list of `RTCIceServer` dictionaries. ```python import os from streamlit_webrtc import get_twilio_ice_servers, webrtc_streamer ice_servers = get_twilio_ice_servers( twilio_sid=os.environ["TWILIO_ACCOUNT_SID"], twilio_token=os.environ["TWILIO_AUTH_TOKEN"], ) # ice_servers → [{"urls": "turn:...", "username": "...", "credential": "..."}, ...] webrtc_streamer( key="cloud-app", rtc_configuration={"iceServers": ice_servers}, ) ``` -------------------------------- ### Record Incoming and Outgoing Media Streams Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Use `in_recorder_factory` and `out_recorder_factory` to save raw incoming and processed outgoing media streams to separate files. Ensure the `RECORD_DIR` exists before running. ```python import uuid from pathlib import Path import av import cv2 from aiortc.contrib.media import MediaRecorder from streamlit_webrtc import WebRtcMode, webrtc_streamer RECORD_DIR = Path("./records") RECORD_DIR.mkdir(exist_ok=True) prefix = str(uuid.uuid4()) in_file = RECORD_DIR / f"{prefix}_input.flv" out_file = RECORD_DIR / f"{prefix}_output.flv" def in_recorder_factory() -> MediaRecorder: return MediaRecorder(str(in_file), format="flv") def out_recorder_factory() -> MediaRecorder: return MediaRecorder(str(out_file), format="flv") def video_frame_callback(frame: av.VideoFrame) -> av.VideoFrame: img = frame.to_ndarray(format="bgr24") img = cv2.cvtColor(cv2.Canny(img, 100, 200), cv2.COLOR_GRAY2BGR) return av.VideoFrame.from_ndarray(img, format="bgr24") webrtc_streamer( key="record", mode=WebRtcMode.SENDRECV, media_stream_constraints={"video": True, "audio": True}, video_frame_callback=video_frame_callback, in_recorder_factory=in_recorder_factory, out_recorder_factory=out_recorder_factory, ) ``` -------------------------------- ### webrtc_streamer() - Core Streaming Component Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt The primary entry point for all streaming scenarios. Renders a START/STOP button widget and manages the full WebRTC lifecycle. Returns a `WebRtcStreamerContext` that carries the current state and references to processor instances and media tracks. ```APIDOC ## webrtc_streamer() ### Description This function renders a START/STOP button widget and manages the full WebRTC lifecycle. It returns a `WebRtcStreamerContext` object. ### Parameters - `key` (str) - Required - A unique key for the component. - `mode` (WebRtcMode) - Optional - Controls the streaming direction (default is `SENDRECV`). - `video_frame_callback` (callable) - Optional - A function to process incoming video frames. - `audio_frame_callback` (callable) - Optional - A function to process incoming audio frames. - `media_stream_constraints` (dict) - Optional - Constraints for media capture (e.g., camera resolution, audio sample rate). ### Returns - `WebRtcStreamerContext` - An object containing the current state and references to media tracks and processors. ### Example ```python import streamlit as st from streamlit_webrtc import webrtc_streamer, WebRtcMode ctx = webrtc_streamer(key="loopback") if ctx.state.playing: st.write("Stream is live!") ``` ``` -------------------------------- ### get_twilio_ice_servers() Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Fetches time-limited STUN/TURN credentials from the Twilio Network Traversal Service API, cached for 1 hour. Returns a list of RTCIceServer dicts ready to pass to rtc_configuration. ```APIDOC ## get_twilio_ice_servers() ### Description Fetches time-limited STUN/TURN credentials from the Twilio Network Traversal Service API, cached for 1 hour. Returns a list of `RTCIceServer` dicts ready to pass to `rtc_configuration`. ### Method `get_twilio_ice_servers(twilio_sid: str, twilio_token: str)` ### Parameters #### Arguments - **twilio_sid** (str) - Required - Your Twilio Account SID. - **twilio_token** (str) - Required - Your Twilio Auth Token. ### Returns - A list of `RTCIceServer` dictionaries, e.g., `[{"urls": "turn:...", "username": "...", "credential": "..."}, ...]`. ### Request Example ```python import os from streamlit_webrtc import get_twilio_ice_servers, webrtc_streamer ice_servers = get_twilio_ice_servers( twilio_sid=os.environ["TWILIO_ACCOUNT_SID"], twilio_token=os.environ["TWILIO_AUTH_TOKEN"], ) webrtc_streamer( key="cloud-app", rtc_configuration={"iceServers": ice_servers}, ) ``` ``` -------------------------------- ### Perform Backend Type Checking Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Runs mypy for backend type checking. ```bash uv run mypy . ``` -------------------------------- ### Run Backend Tests Source: https://github.com/whitphx/streamlit-webrtc/blob/main/AGENTS.md Executes backend tests using pytest. ```bash uv run pytest ``` -------------------------------- ### Create Programmatic Audio Source Track Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Use `create_audio_source_track` to generate audio frames from a Python callback. The callback receives presentation timestamp and time base, and must return an `av.AudioFrame`. This is suitable for synthesizing tones, streaming TTS audio, or injecting any audio signal into a WebRTC session. ```python import fractions import numpy as np import av from streamlit_webrtc import WebRtcMode, create_audio_source_track, webrtc_streamer import streamlit as st frequency = st.slider("Frequency (Hz)", 200, 2000, 440) sample_rate = 48000 ptime = 0.020 # 20 ms samples_per_frame = int(sample_rate * ptime) def audio_source_callback(pts: int, time_base: fractions.Fraction) -> av.AudioFrame: t_start = float(pts * time_base) t = np.linspace(t_start, t_start + ptime, samples_per_frame, False) audio_data = (np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16) frame = av.AudioFrame.from_ndarray(audio_data.reshape(1, -1), format="s16", layout="mono") frame.sample_rate = sample_rate return frame audio_track = create_audio_source_track( audio_source_callback, key="tone-gen", sample_rate=sample_rate, ptime=ptime, ) def on_change(): ctx = st.session_state["audio-out"] if not ctx.state.playing and not ctx.state.signalling: audio_track.stop() webrtc_streamer( key="audio-out", mode=WebRtcMode.RECVONLY, source_audio_track=audio_track, media_stream_constraints={"video": False, "audio": True}, on_change=on_change, ) ``` -------------------------------- ### Callback Data Extraction with Thread Safety Source: https://github.com/whitphx/streamlit-webrtc/blob/main/README.md Demonstrates how to extract data from a video frame callback to the main script thread safely. Uses threading.Lock for synchronization and a loop to poll for updated image data for analysis. ```python import threading import cv2 import streamlit as st from matplotlib import pyplot as plt from streamlit_webrtc import webrtc_streamer lock = threading.Lock() img_container = {"img": None} def video_frame_callback(frame): img = frame.to_ndarray(format="bgr24") with lock: img_container["img"] = img return frame ctx = webrtc_streamer(key="example", video_frame_callback=video_frame_callback) fig_place = st.empty() fig, ax = plt.subplots(1, 1) while ctx.state.playing: with lock: img = img_container["img"] if img is None: continue gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ax.cla() ax.hist(gray.ravel(), 256, [0, 256]) fig_place.pyplot(fig) ``` -------------------------------- ### Create a Multi-Input Mixer Track Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Use `create_mix_track` to combine frames from multiple input tracks into a single output track using a custom mixer callback. The mixer callback receives a list of frames and should return a single `av.VideoFrame`. ```python import math from typing import List import av import numpy as np from streamlit_webrtc import WebRtcMode, webrtc_streamer, create_mix_track, MediaStreamMixTrack from typing import cast def mixer_callback(frames: List[av.VideoFrame]) -> av.VideoFrame: buf_w, buf_h = 640, 480 buffer = np.zeros((buf_h, buf_w, 3), dtype=np.uint8) n = len(frames) cols = math.ceil(math.sqrt(n)) rows = math.ceil(n / cols) gw, gh = buf_w // cols, buf_h // rows for i, frame in enumerate(frames): if frame is None: continue img = frame.to_ndarray(format="bgr24") x, y = (i % cols) * gw, (i // cols) * gh import cv2 buffer[y:y+gh, x:x+gw] = cv2.resize(img, (gw, gh)) return av.VideoFrame.from_ndarray(buffer, format="bgr24") ctx1 = webrtc_streamer(key="in1", mode=WebRtcMode.SENDRECV, media_stream_constraints={"video": True, "audio": False}) ctx2 = webrtc_streamer(key="in2", mode=WebRtcMode.SENDRECV, media_stream_constraints={"video": True, "audio": False}) mix_track = create_mix_track(kind="video", mixer_callback=mixer_callback, key="mix") mix_ctx = webrtc_streamer( key="mix-output", mode=WebRtcMode.RECVONLY, source_video_track=mix_track, desired_playing_state=ctx1.state.playing or ctx2.state.playing, ) if mix_ctx.source_video_track and ctx1.output_video_track: cast(MediaStreamMixTrack, mix_ctx.source_video_track).add_input_track(ctx1.output_video_track) if mix_ctx.source_video_track and ctx2.output_video_track: cast(MediaStreamMixTrack, mix_ctx.source_video_track).add_input_track(ctx2.output_video_track) ``` -------------------------------- ### Serve App via HTTPS with SSL Proxy Source: https://github.com/whitphx/streamlit-webrtc/blob/main/README.md Use this command to proxy your Streamlit app (running on HTTP) through HTTPS for development purposes. Ensure the ssl-proxy binary is downloaded and accessible. ```shell $ streamlit run your_app.py # Assume your app is running on http://localhost:8501 # Then, after downloading the binary from the GitHub page above to ./ssl-proxy, $ ./ssl-proxy -from 0.0.0.0:8000 -to 127.0.0.1:8501 # Proxy the HTTP page from port 8501 to port 8000 via HTTPS # Then access https://localhost:8000 ``` -------------------------------- ### Configure Logging for Streamlit-WebRTC Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Configure logging for `streamlit-webrtc` and its internal dependencies using Python's standard `logging` module. This allows suppressing verbose INFO logs from `aioice` and `aiortc`, or enabling DEBUG level logging for detailed output. ```python import logging # Suppress verbose internal logs logging.getLogger("streamlit_webrtc").setLevel(logging.WARNING) logging.getLogger("aioice").setLevel(logging.WARNING) logging.getLogger("aiortc").setLevel(logging.WARNING) # Or configure via dictConfig for structured logging logging.basicConfig( level=logging.DEBUG, format="%(asctime)s %(name)s %(levelname)s %(message)s", ) ``` -------------------------------- ### Customize HTML Media Element Attributes Source: https://context7.com/whitphx/streamlit-webrtc/llms.txt Use `video_html_attrs` and `audio_html_attrs` to customize the appearance and behavior of the rendered HTML `