I have a FastAPI application running inside a Docker container that is trying to stream video from an RTSP camera URL using OpenCV. The setup works fine locally, but when running inside Docker, the /video
endpoint does not return a stream and times out. Below are the details of the issue.
Docker Setup:
Dockerfile:
FROM python:3.10.12
RUN apt-get update && apt-get install -y \
libgl1-mesa-glx \
libglib2.0-0
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
- Docker Compose:
services:
api:
build: ./api
ports:
- "8000:8000"
depends_on:
- redis
- mongo
networks:
- app_network
volumes:
- ./api:/app
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379
- MONGO_URI=mongodb://mongo:27017/app_db
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- api
networks:
- app_network
volumes:
- ./frontend:/app
- /app/node_modules
redis:
image: "redis:alpine"
restart: always
networks:
- app_network
volumes:
- redis_data:/data
mongo:
image: "mongo:latest"
restart: always
networks:
- app_network
volumes:
- mongo_data:/data/db
networks:
app_network:
driver: bridge
volumes:
redis_data:
mongo_data:
Issue:
When I try to access the /video
endpoint, the following warnings appear:
[ WARN:[email protected]] global cap_ffmpeg_impl.hpp:453 _opencv_ffmpeg_interrupt_callback Stream timeout triggered after 30037.268665 ms
However, locally, the RTSP stream works fine using OpenCV with the same code.
Additional Information:
- Network: The Docker container can successfully ping the camera IP (
10.100.10.94
). - Local Video: I can read frames from a local video file without issues.
- RTSP Stream: I am able to access the RTSP stream directly using OpenCV locally, but not inside the Docker container.
Code:
Here's the relevant part of the code in my api/app.py
:
import cv2
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
RTSP_URL = "rtsp://deneme:[email protected]:554/axis-media/media.amp?adjustablelivestream=1&fps=10"
def generate_frames():
cap = cv2.VideoCapture(RTSP_URL)
if not cap.isOpened():
print("Failed to connect to RTSP stream.")
return
while True:
success, frame = cap.read()
if not success:
print("Failed to capture frame.")
break
_, buffer = cv2.imencode(".jpg", frame)
frame_bytes = buffer.tobytes()
yield (
b"--frame\r\n" b"Content-Type: image/jpeg\r\n\r\n" + frame_bytes + b"\r\n"
)
cap.release()
@app.get("/video")
async def video_feed():
"""Return MJPEG stream to the browser."""
return StreamingResponse(
generate_frames(), media_type="multipart/x-mixed-replace; boundary=frame"
)
Has anyone faced similar issues or have suggestions on how to resolve this?