我有一个小型 Python OpenCV 项目,想使用 ffmpeg 将我处理过的帧流式传输到 HTTP。
为此,我使用了以下资源: Pipe and OpenCV to FFmpeg with audio streaming RTMP in Python 和 https://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
也许有人知道如何解决这个问题。
谢谢你的帮助
克里斯
最佳答案
好的,我通过异步运行进程修复了它。 剩下的唯一问题是在客户端关闭连接时安全地关闭管道。
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()
关于python - 使用 ffmpeg 将 OpenCV 帧流式传输到 http,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71696078/