Hosting a webcam connected to a server using streamlit

I’m trying to host a webcam connected locally to my server using the following code:

import numpy as np
import time
import cv2 # pip install opencv-python-headless
import gc

camera = cv2.VideoCapture(0) 
@st.cache_data(max_entries=5, ttl=10)
def get_frame(time): # we pass in time to make sure the cache is updated every call
    try: 
        _, frame = camera.read()
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        return frame
    except:
        return np.zeros((300, 300, 3))

def main():
    st.title("Live Camera Feed")
    run = st.checkbox('Run')
    if run:
        camera = cv2.VideoCapture(0) 
        try:
            FRAME_WINDOW = st.image([])
            while True:
                data = get_frame(time.time())
                FRAME_WINDOW.image(data)
                gc.collect()
        finally:
            camera.release()
            cv2.destroyAllWindows()
main()

This works (mostly) for a single user with a large delay between attempts, a second person trying to access the stream, or even one person closing it and reopening it within a minute or so and the entire thing fails until either the system is restarted or all users stop trying to access it for a few minutes.
Ive seen webrtc be suggested a few times in similar situations, but all examples of that i can find use a client side webcam. st.camera_input seems to have similar restrictions that it only uses the client’s webcam.

Is there a better way to do this that I’m missing?

Streamlit has a server-client structure. So yes, any command or component meant to work with Streamlit will access that camera through the client browser and stream it back to the Python server.

If you want to share a camera from the server, you’d need something that’s multithreading compatible as each client runs on their own thread. I suspect this is the difficulty here, but I don’t have a good solution.

1 Like