我看到很多有关将 raspivid 流直接传输到 FFMPEG 进行编码、复用和重新流传的信息,但这些用例大多是来自于 bash shell,类似于:
raspivid -n -w 480 -h 320 -b 300000 -fps 15 -t 0 -o - | ffmpeg -i - -f mpegts udp://192.168.1.2:8090ffmpeg
我希望利用 Picamera 库的功能,以便在使用 OpenCV 和类似工具进行并发处理的同时,仍然能够使用 FFMPEG 进行流传输。但我无法弄清如何正确地打开 FFMPEG 作为子进程,并将视频数据传输到它。我看到了很多尝试、未回答的帖子和声称已经完成此操作的人,但没有任何一个对我的树莓派有效。
我要使用 Picamera 创建视频缓冲区,然后将原始视频传输到 FFMPEG 吗?我可以使用 camera.capture_continuous() 并传递给 FFMPEG 我正在使用的 bgr24 图像来进行 OpenCV 计算吗?
我尝试了各种变化,但我不确定我是否只是误解了如何使用 subprocess 模块、FFMPEG,还是我只是缺少一些设置。我知道原始流没有任何元数据,但我不完全确定我需要为 FFMPEG 提供什么设置,以便它能够理解我正在传递给它的内容。
我有一个 Wowza 服务器,最终将流传输到那里,但我目前正在通过流传输到我的笔记本电脑上的 VLC 服务器进行测试。我目前尝试过这个:
import subprocess as sp
import picamera
import picamera.array
import numpy as np
npimage = np.empty(
(480, 640, 3),
dtype=np.uint8)
with picamera.PiCamera() as camera:
camera.resolution = (640, 480)
camera.framerate = 24
camera.start_recording('/dev/null', format='h264')
command = [
'ffmpeg',
'-y',
'-f', 'rawvideo',
'-video_size', '640x480',
'-pix_fmt', 'bgr24',
'-framerate', '24',
'-an',
'-i', '-',
'-f', 'mpegts', 'udp://192.168.1.54:1234']
pipe = sp.Popen(command, stdin=sp.PIPE,
stdout=sp.PIPE, stderr=sp.PIPE, bufsize=10**8)
if pipe.returncode != 0:
output, error = pipe.communicate()
print('Pipe failed: %d %s %s' % (pipe.returncode, output, error))
raise sp.CalledProcessError(pipe.returncode, command)
while True:
camera.wait_recording(0)
for i, image in enumerate(
camera.capture_continuous(
npimage,
format='bgr24',
use_video_port=True)):
pipe.stdout.write(npimage.tostring())
camera.stop_recording()
我也尝试将流写入类似文件的对象中,该对象仅创建FFMPEG子进程并将其写入stdin(在初始化picam时,camera.start_recording()可以提供此类对象):
class PipeClass():
"""Start pipes and load ffmpeg."""
def __init__(self):
"""Create FFMPEG subprocess."""
self.size = 0
command = [
'ffmpeg',
'-f', 'rawvideo',
'-s', '640x480',
'-r', '24',
'-i', '-',
'-an',
'-f', 'mpegts', 'udp://192.168.1.54:1234']
self.pipe = sp.Popen(command, stdin=sp.PIPE,
stdout=sp.PIPE, stderr=sp.PIPE)
if self.pipe.returncode != 0:
raise sp.CalledProcessError(self.pipe.returncode, command)
def write(self, s):
"""Write to the pipe."""
self.pipe.stdin.write(s)
def flush(self):
"""Flush pipe."""
print("Flushed")
usage:
(...)
with picamera.PiCamera() as camera:
p = PipeClass()
camera.start_recording(p, format='h264')
(...)
任何关于此事的帮助都非常棒!
.mp4
文件(ISO BMFF)。 - hobbs