Ich sehe eine Menge Informationen darüber, wie man einen raspivid Stream direkt an FFMPEG zum Encodieren, Muxen und Restreaming leitet, aber diese Anwendungsfälle sind meistens bash; ähnlich wie:Wie man Picamera Video zu FFMPEG mit Subprozess (Python) pipettiert
raspivid -n -w 480 -h 320 -b 300000 -fps 15 -t 0 -o - | ffmpeg -i - -f mpegts udp: //192.168.1.2: 8090ffmpeg
Ich hoffe, die Funktionalität der Picamera-Bibliothek zu nutzen, so dass ich gleichzeitige Verarbeitung mit OpenCV und ähnlichen während des Streamings mit FFMPEG machen kann. Aber ich kann nicht herausfinden, wie man FFMPEG als Subprozess richtig öffnet und Videodaten an ihn leitet. Ich habe viele Versuche gesehen, unanswered posts, und Leute claiming to have done it, aber nichts davon scheint auf meinem Pi zu funktionieren.
Sollte ich einen Videopuffer mit Picamera erstellen und das rohe Video zu FFMPEG pipen? Kann ich camera.capture_continuous() verwenden und FFMPEG die bgr24-Bilder übergeben, die ich für meine OpenCV-Berechnung verwende?
Ich habe alle möglichen Varianten ausprobiert und ich bin mir nicht sicher, ob ich nur missverstanden habe, wie man das Subprozessmodul FFMPEG benutzt oder mir einfach ein paar Einstellungen versagt. Ich verstehe, dass der Rohdatenstrom keine Metadaten hat, aber ich bin mir nicht ganz sicher, welche Einstellungen ich FFMPEG geben muss, damit er versteht, was ich ihm gebe.
Ich habe einen Wowza-Server, den ich irgendwann streamen werde, aber ich teste gerade, indem ich auf meinem Laptop zu einem VLC-Server streame. Ich habe dies zur Zeit versucht:
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()
ich auch den Strom in eine Datei-ähnliches Objekt versucht haben, zu schreiben, die einfach die FFMPEG subprocess erstellt und schreibt in die stdin davon (camera.start_recording() gegeben werden kann, ein Objekt wie dieses, wenn Sie die Picam initialisieren):
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')
(...)
Jede Hilfe mit diesem wäre erstaunlich!
mit
testOutput.exe ORIGINAL_SOURCE RTMP_OUTPUT nennen - funktioniert das überhaupt? In jedem Fall streamt OP als TS auf UDP, so dass dieser Teil unter Kontrolle ist. – hobbs
Scheint für mich zu arbeiten! Die Ausgabe ist in omxplayer abspielbar. Aber ich bin offen für Verbesserungsvorschläge! –
Genau das habe ich gebraucht! Ich habe die Pipes eindeutig zu dem Subprozess missbraucht, aber es hat mir geholfen, ein paar der Einstellungen zu realisieren, die ich in FFMPEG verwenden wollte, gab mir auch Probleme. Vielen Dank! – VeniVidiReliqui