RTSP Live Camera in Django Server or React App

I wanna stream camera live videos in my website using django and react.

in VLC -> Media -> Open Network Stream I set this RTSP url in Network tab and I can see live camera video perfectly:

rtsp://user:password%40123@ip:port

But I can't do it in django. or maybe I don't need to do this on django and can do it on react only.

best I could achieve was this code which only worked in local with a VPN:

class VideoCamera:
    def __init__(self):
        url = "rtsp://user:password%40123@ip:port"
        self.video = cv2.VideoCapture(url, cv2.CAP_FFMPEG)

        if not self.video.isOpened():
            print("Failed to open RTSP stream")
            self.running = False
            return
        
        self.running = True
        self.grabbed, self.frame = self.video.read()
        self.lock = threading.Lock()  # Prevents race conditions
        self.thread = threading.Thread(target=self.update, daemon=True)
        self.thread.start()

    def update(self):
        while self.running:
            grabbed, frame = self.video.read()
            if not grabbed:
                print("Failed to grab frame, retrying...")
                continue  # Prevents self.frame from being None
            with self.lock:
                self.frame = frame

    def get_frame(self):
        with self.lock:
            if self.frame is None:
                return None

            success, jpeg = cv2.imencode('.jpg', self.frame)
            if not success:
                print("Encoding failed")
                return None  # Prevent sending invalid data

            return jpeg.tobytes()


    def stop(self):
        self.running = False
        self.thread.join()  # Ensures clean exit
        self.video.release()

def get_camera(camera):
    while camera.running:
        frame = camera.get_frame()
        if frame:
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
        else:
            print("No frame available")

def stream_video(request):
    cam = VideoCamera()
    if not cam.running:
        return StreamingHttpResponse("Failed to open RTSP stream", status=500)

    try:
        return StreamingHttpResponse(
            get_camera(cam),
            content_type='multipart/x-mixed-replace; boundary=frame'
        )
    except Exception as e:
        print(f"Error occurred: {e}")
        cam.stop()
    
    return StreamingHttpResponse("Stream stopped", status=500)

but when I put this code in server, I can't see the video in website. frames were printed correctly though.

I also tested this WebRTC code but didn't work:

import asyncio
import subprocess
from channels.generic.websocket import AsyncWebsocketConsumer

class StreamConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        print("WebSocket connect attempt")
        # Accept WebSocket connection
        await self.accept()

        # Start FFmpeg process to capture RTSP stream
        try:
            self.ffmpeg_process = subprocess.Popen(
                [
                    'ffmpeg',
                    '-i', 'rtsp://admin:Admin%40123@192.168.10.11:554',  # Replace with your RTSP stream URL
                    '-f', 'mjpeg',  # MJPEG format
                    '-q:v', '5',  # Set quality level
                    '-'
                ],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )

            print("FFmpeg process started")

            # Start sending frames asynchronously
            asyncio.create_task(self.stream_video())

        except Exception as e:
            print(f"Error starting FFmpeg process: {e}")
            await self.close()

    async def stream_video(self):
        try:
            while True:
                # Read the video data (frame) from FFmpeg
                frame = self.ffmpeg_process.stdout.read(1024)
                if not frame:
                    print("No frame received. Exiting.")
                    break

                print("Sending frame to WebSocket")
                # Send the frame to WebSocket
                await self.send(bytes_data=frame)
        except Exception as e:
            print(f"Error while streaming video: {e}")

    async def disconnect(self, close_code):
        print(f"WebSocket disconnected with code {close_code}")
        if self.ffmpeg_process:
            self.ffmpeg_process.kill()
            print("FFmpeg process killed")

I also tested Hls and got 1 minute video but it's not real-time and not enough:

first I used this to create stream segments from rtsp:

ffmpeg -i rtsp://user:password%40123@ip:port -c:v libx264 -f hls -hls_time 10 -hls_list_size 6 -hls_flags delete_segments stream.m3u8

then used this to make it available on port 2025:

http-server . -p 2025

and finally:

<video width="100%" height="auto" controls>
  <source src="http://ip:2025/cam.mp4" type="video/mp4" />
</video>

I need a reliable solution to stream live camera video in my django website. plz help me.

Вернуться на верх