0

I would like to send processed frames in OpenCV format from my python script to OBS Studio for display. I've tried to use the Flask method outlined here and add the generated webpage to OBS as "Browser", but it was buggy and slow when used from within my current python code.

Is there any way to just stream the OpenCV frames to OBS directly? E.g. generate an RTSP stream that I can then read in OBS with the "VLC Video Source" input?

Any help would be much appreciated.

Skeleton code:

import cv2

output_to_obs = True
output_to_cv2 = True

camera = cv2.VideoCapture(0)

def frame_to_obs(frame):
    # ==========================
    # don't know what to do here
    # ==========================
    pass

def process_frame(frame):
    # just an example
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    return frame_gray

while (camera.isOpened()):
    ret, frame = camera.read()
    if ret == True:
        frame = process_frame(frame)
        if output_to_obs:
            frame_to_obs(frame)
        if output_to_cv2:
            cv2.imshow('frame',frame)
            if cv2.waitKey(1) == 27:
                # escape was pressed
                break
    else:
        break
bozolino
  • 11
  • 2

1 Answers1

0

Try this here:

    import cv2
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst

output_to_obs = True
output_to_cv2 = True

camera = cv2.VideoCapture(0)

def frame_to_obs(frame):
    # Create a GStreamer pipeline
    pipeline = Gst.Pipeline.new("pipeline")

    # Create a source element that will read the OpenCV frames
    source = Gst.ElementFactory.make("appsrc", "source")
    source.set_property("format", Gst.Format.TIME)
    source.set_property("caps", Gst.Caps.from_string("video/x-raw, format=BGR"))
    source.set_property("is-live", True)
    source.connect("need-data", on_need_data, frame)

    # Create a sink element that will send the frames to OBS
    sink = Gst.ElementFactory.make("udpsink", "sink")
    sink.set_property("host", "127.0.0.1")
    sink.set_property("port", 5000)

    # Add the elements to the pipeline
    pipeline.add(source)
    pipeline.add(sink)

    # Link the elements
    source.link(sink)

    # Start the pipeline
    pipeline.set_state(Gst.State.PLAYING)

def on_need_data(source, user_data):
    # This function is called when the pipeline needs more data
    # to send to OBS. It will add the current frame to the pipeline
    # and then return.
    frame = user_data
    ret, buffer = cv2.imencode('.jpg', frame)
    if ret:
        source.emit("push-buffer", Gst.Buffer.new_wrapped(buffer.tobytes()))

def process_frame(frame):
    # just an example
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    return frame_gray

while (camera.isOpened()):
    ret, frame = camera.read()
    if ret == True:
        frame = process_frame(frame)
        if output_to_obs:
            frame_to_obs(frame)
        if output_to_cv2:
            cv2.imshow('frame',frame)
            if cv2.waitKey(1) == 27:
                # escape was pressed
                break
    else:
        break
Nes Elm
  • 87
  • 1
  • 3
  • 12
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 06 '23 at 23:00