generated from thinkode/modelRepository
initial commit and version 1.0
This commit is contained in:
137
moviepy/video/io/ffplay_previewer.py
Normal file
137
moviepy/video/io/ffplay_previewer.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""
|
||||
On the long term this will implement several methods to make videos
|
||||
out of VideoClips
|
||||
"""
|
||||
|
||||
import subprocess as sp
|
||||
|
||||
from moviepy.config import FFPLAY_BINARY
|
||||
from moviepy.tools import cross_platform_popen_params
|
||||
|
||||
|
||||
class FFPLAY_VideoPreviewer:
|
||||
"""A class for FFPLAY-based video preview.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
size : tuple or list
|
||||
Size of the output video in pixels (width, height).
|
||||
|
||||
fps : int
|
||||
Frames per second in the output video file.
|
||||
|
||||
pixel_format : str
|
||||
Pixel format for the output video file, ``rgb24`` for normal video, ``rgba``
|
||||
if video with mask.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
size,
|
||||
fps,
|
||||
pixel_format,
|
||||
):
|
||||
# order is important
|
||||
cmd = [
|
||||
FFPLAY_BINARY,
|
||||
"-autoexit", # If you don't precise, ffplay won't stop at end
|
||||
"-f",
|
||||
"rawvideo",
|
||||
"-pixel_format",
|
||||
pixel_format,
|
||||
"-video_size",
|
||||
"%dx%d" % (size[0], size[1]),
|
||||
"-framerate",
|
||||
"%.02f" % fps,
|
||||
"-",
|
||||
]
|
||||
|
||||
popen_params = cross_platform_popen_params(
|
||||
{"stdout": sp.DEVNULL, "stderr": sp.STDOUT, "stdin": sp.PIPE}
|
||||
)
|
||||
|
||||
self.proc = sp.Popen(cmd, **popen_params)
|
||||
|
||||
def show_frame(self, img_array):
|
||||
"""Writes one frame in the file."""
|
||||
try:
|
||||
self.proc.stdin.write(img_array.tobytes())
|
||||
except IOError as err:
|
||||
_, ffplay_error = self.proc.communicate()
|
||||
if ffplay_error is not None:
|
||||
ffplay_error = ffplay_error.decode()
|
||||
|
||||
error = (
|
||||
f"{err}\n\nMoviePy error: FFPLAY encountered the following error while "
|
||||
f"previewing clip :\n\n {ffplay_error}"
|
||||
)
|
||||
|
||||
raise IOError(error)
|
||||
|
||||
def close(self):
|
||||
"""Closes the writer, terminating the subprocess if is still alive."""
|
||||
if self.proc:
|
||||
self.proc.stdin.close()
|
||||
if self.proc.stderr is not None:
|
||||
self.proc.stderr.close()
|
||||
self.proc.wait()
|
||||
|
||||
self.proc = None
|
||||
|
||||
# Support the Context Manager protocol, to ensure that resources are cleaned up.
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.close()
|
||||
|
||||
|
||||
def ffplay_preview_video(
|
||||
clip, fps, pixel_format="rgb24", audio_flag=None, video_flag=None
|
||||
):
|
||||
"""Preview the clip using ffplay. See VideoClip.preview for details
|
||||
on the parameters.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
clip : VideoClip
|
||||
The clip to preview
|
||||
|
||||
fps : int
|
||||
Number of frames per seconds in the displayed video.
|
||||
|
||||
pixel_format : str, optional
|
||||
Warning: This is not used anywhere in the code and should probably
|
||||
be removed.
|
||||
It is believed pixel format rgb24 does not work properly for now because
|
||||
it requires applying a mask on CompositeVideoClip and that is believed to
|
||||
not be working.
|
||||
|
||||
Pixel format for the output video file, ``rgb24`` for normal video, ``rgba``
|
||||
if video with mask
|
||||
|
||||
audio_flag : Thread.Event, optional
|
||||
A thread event that video will wait for. If not provided we ignore audio
|
||||
|
||||
video_flag : Thread.Event, optional
|
||||
A thread event that video will set after first frame has been shown. If not
|
||||
provided, we simply ignore
|
||||
"""
|
||||
with FFPLAY_VideoPreviewer(clip.size, fps, pixel_format) as previewer:
|
||||
first_frame = True
|
||||
for t, frame in clip.iter_frames(with_times=True, fps=fps, dtype="uint8"):
|
||||
previewer.show_frame(frame)
|
||||
|
||||
# After first frame is shown, if we have audio/video flag, set video ready
|
||||
# and wait for audio
|
||||
if first_frame:
|
||||
first_frame = False
|
||||
|
||||
if video_flag:
|
||||
video_flag.set() # say to the audio: video is ready
|
||||
|
||||
if audio_flag:
|
||||
audio_flag.wait() # wait for the audio to be ready
|
||||
Reference in New Issue
Block a user