使用FFMPEG将OPENCV帧流到HTTP

发布于 2025-01-18 02:01:44 字数 1588 浏览 2 评论 0原文

我有一个小型 Python OpenCV 项目,想使用 ffmpeg 将处理后的帧流式传输到 HTTP。

为此,我使用了以下来源: 通过管道和 OpenCV 到 FFmpeg Python 中的音频流 RTMPhttps://github.com/kkroening/ffmpeg-python/blob/master/examples/README.md#stream-from-a-local-video-to-http-server

使内容更具可读性我使用了 ffmpeg-python 库,但据我了解,使用子进程打开管道或使用该库并不重要。

我遇到的问题是,当我用 ffplay 打开流时,我总是遇到管道损坏或“连接被拒绝”的情况。

import ffmpeg
import cv2

video_format = "flv"
server_url = "http://localhost:8080"

cap = cv2.VideoCapture(1)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))


process = (
    ffmpeg
    .input('pipe:', format='rawvideo',codec="rawvideo", pix_fmt='bgr24', s='{}x{}'.format(width, height))
    .output(
        server_url,
        #codec = "copy", # use same codecs of the original video
        listen=1, # enables HTTP server
        codec="libx264",
        pix_fmt="yuv420p",
        preset="ultrafast",
        f=video_format)
    .overwrite_output()
    .run()
)

while True:
    ret, frame = cap.read()
    if not ret:
        break
    print("Sending frame")
    process.stdin.write(frame.tobytes())

我还尝试仅使用 ffmpeg 和 FaceTime 进行流式传输,效果符合我的预期。

我的操作系统是 MacOS 12.3

也许有人知道如何解决这个问题。

感谢您的帮助

克里斯

I have a small Python OpenCV project and would like to stream my processed frames to HTTP using ffmpeg.

For this I used the following sources:
Pipe and OpenCV to FFmpeg with audio streaming RTMP in Python
and
https://github.com/kkroening/ffmpeg-python/blob/master/examples/README.md#stream-from-a-local-video-to-http-server

To make things more readable I used the ffmpeg-python library but as far as I understand, it doesn't matter if I open a pipe using subprocess or use the library.

The problem that I have is, that I always get a broken pipe or "Connection refused" when I open the stream with ffplay.

import ffmpeg
import cv2

video_format = "flv"
server_url = "http://localhost:8080"

cap = cv2.VideoCapture(1)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))


process = (
    ffmpeg
    .input('pipe:', format='rawvideo',codec="rawvideo", pix_fmt='bgr24', s='{}x{}'.format(width, height))
    .output(
        server_url,
        #codec = "copy", # use same codecs of the original video
        listen=1, # enables HTTP server
        codec="libx264",
        pix_fmt="yuv420p",
        preset="ultrafast",
        f=video_format)
    .overwrite_output()
    .run()
)

while True:
    ret, frame = cap.read()
    if not ret:
        break
    print("Sending frame")
    process.stdin.write(frame.tobytes())

I also tried to stream using only ffmpeg and FaceTime and that works as i expected.

My operation system is MacOS 12.3

Maybe someone knows how to fix this.

Thanks for your help

Chris

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我为君王 2025-01-25 02:01:44

好的,我通过运行进程异步解决了它。
唯一的问题是当客户关闭连接时,要牢固关闭管道。

import ffmpeg
import cv2
import subprocess

video_format = "flv"
server_url = "http://localhost:8080"




def start_streaming(width, height,fps):
    process = (
        ffmpeg
        .input('pipe:', format='rawvideo',codec="rawvideo", pix_fmt='bgr24', s='{}x{}'.format(width, height))
        .output(
            server_url + '/stream',
            #codec = "copy", # use same codecs of the original video
            listen=1, # enables HTTP server
            pix_fmt="yuv420p",
            preset="ultrafast",
            f=video_format
        )
        .overwrite_output()
        .run_async(pipe_stdin=True)
    )
    return process

def init_cap():
    cap = cv2.VideoCapture(1)
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    return cap, width, height

def run():
    cap, width, height = init_cap()
    fps = cap.get(cv2.CAP_PROP_FPS)
    streaming_process = start_streaming(width, height,fps)
    while True:
        ret, frame = cap.read()
        if ret:
            streaming_process.stdin.write(frame.tobytes())
        else:
            break
    streaming_process.stdin.close()
    streaming_process.wait()
    cap.release()

if __name__ == "__main__":
    run()

Ok i fixed it by running the process async.
The only problem left is to close the pipe securly when the client closes the connection.

import ffmpeg
import cv2
import subprocess

video_format = "flv"
server_url = "http://localhost:8080"




def start_streaming(width, height,fps):
    process = (
        ffmpeg
        .input('pipe:', format='rawvideo',codec="rawvideo", pix_fmt='bgr24', s='{}x{}'.format(width, height))
        .output(
            server_url + '/stream',
            #codec = "copy", # use same codecs of the original video
            listen=1, # enables HTTP server
            pix_fmt="yuv420p",
            preset="ultrafast",
            f=video_format
        )
        .overwrite_output()
        .run_async(pipe_stdin=True)
    )
    return process

def init_cap():
    cap = cv2.VideoCapture(1)
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    return cap, width, height

def run():
    cap, width, height = init_cap()
    fps = cap.get(cv2.CAP_PROP_FPS)
    streaming_process = start_streaming(width, height,fps)
    while True:
        ret, frame = cap.read()
        if ret:
            streaming_process.stdin.write(frame.tobytes())
        else:
            break
    streaming_process.stdin.close()
    streaming_process.wait()
    cap.release()

if __name__ == "__main__":
    run()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文