Czy można" strumieniowo " obrazy do ffmpeg konstruować wideo, zamiast zapisywać je na dysku?

Moja praca polega ostatnio na programowym tworzeniu filmów. W Pythonie typowy przepływ pracy wygląda mniej więcej tak:

import subprocess, Image, ImageDraw

for i in range(frames_per_second * video_duration_seconds):
    img = createFrame(i)
    img.save("%07d.png" % i)

subprocess.call(["ffmpeg","-y","-r",str(frames_per_second),"-i", "%07d.png","-vcodec","mpeg4", "-qscale","5", "-r", str(frames_per_second), "video.avi"])

Ten obieg pracy tworzy obraz dla każdej klatki wideo i zapisuje go na dysku. Po zapisaniu wszystkich obrazów wywoływany jest ffmpeg, który tworzy wideo ze wszystkich obrazów.

Zapisywanie obrazów na dysk (nie tworzenie obrazów w pamięci) pochłania większość cykli i nie wydaje się być konieczne. Czy jest jakiś sposób aby wykonać tę samą funkcję, ale bez zapisywania obrazów na dysk? Tak więc wywoływany byłby ffmpeg, a obrazy byłyby konstruowane i przekazywane do ffmpeg natychmiast po jego zbudowaniu.

Author: Brandon, 2012-11-08

1 answers

Ok, działa. dzięki sugestii LordNeckbeard do korzystania z image2pipe. Musiałem użyć kodowania jpg zamiast png, ponieważ image2pipe z png nie działa na mojej wersji ffmpeg . Pierwszy skrypt jest zasadniczo taki sam jak kod twojego pytania, z wyjątkiem zaimplementowanego prostego tworzenia obrazu, który po prostu tworzy obrazy przechodzące od czerni do czerwieni. Dodałem też trochę kodu do czasu wykonania.

Wykonanie szeregowe

import subprocess, Image

fps, duration = 24, 100
for i in range(fps * duration):
    im = Image.new("RGB", (300, 300), (i, 1, 1))
    im.save("%07d.jpg" % i)
subprocess.call(["ffmpeg","-y","-r",str(fps),"-i", "%07d.jpg","-vcodec","mpeg4", "-qscale","5", "-r", str(fps), "video.avi"])

Wykonanie równoległe (bez obrazy zapisane na dysku)

import Image
from subprocess import Popen, PIPE

fps, duration = 24, 100
p = Popen(['ffmpeg', '-y', '-f', 'image2pipe', '-vcodec', 'mjpeg', '-r', '24', '-i', '-', '-vcodec', 'mpeg4', '-qscale', '5', '-r', '24', 'video.avi'], stdin=PIPE)
for i in range(fps * duration):
    im = Image.new("RGB", (300, 300), (i, 1, 1))
    im.save(p.stdin, 'JPEG')
p.stdin.close()
p.wait()

Wyniki są ciekawe, uruchomiłem każdy skrypt 3 razy, aby porównać wydajność: serial:

12.9062321186
12.8965060711
12.9360799789

Parallel:

8.67797684669
8.57139396667
8.38926696777

Wygląda na to, że wersja równoległa jest szybsza około 1,5 razy.

 50
Author: Marwan Alsabbagh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-08 21:58:29