Skip to content

Commit

Permalink
Progress bars and messages now with Proglog
Browse files Browse the repository at this point in the history
  • Loading branch information
Zulko committed Dec 16, 2018
1 parent dbc9ab1 commit bfad5ea
Show file tree
Hide file tree
Showing 13 changed files with 109 additions and 152 deletions.
2 changes: 1 addition & 1 deletion docs/examples/quick_recipes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Getting the average frame of a video
clip = VideoFileClip("video.mp4")
fps= 1.0 # take one frame per second
nframes = clip.duration*fps # total number of frames used
total_image = sum(clip.iter_frames(fps,dtype=float,progress_bar=True))
total_image = sum(clip.iter_frames(fps,dtype=float,logger='bar'))
average_image = ImageClip(total_image/ nframes)
average_image.save_frame("average_test.png")

28 changes: 11 additions & 17 deletions moviepy/Clip.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
convert_to_seconds,
use_clip_fps_by_default)
from tqdm import tqdm
import proglog


class Clip:
Expand Down Expand Up @@ -443,7 +444,7 @@ def cutout(self, ta, tb):

@requires_duration
@use_clip_fps_by_default
def iter_frames(self, fps=None, with_times = False, progress_bar=False,
def iter_frames(self, fps=None, with_times = False, logger=None,
dtype=None):
""" Iterates over all the frames of the clip.
Expand All @@ -469,22 +470,15 @@ def iter_frames(self, fps=None, with_times = False, progress_bar=False,
>>> print ( [frame[0,:,0].max()
for frame in myclip.iter_frames()])
"""

def generator():
for t in np.arange(0, self.duration, 1.0/fps):
frame = self.get_frame(t)
if (dtype is not None) and (frame.dtype != dtype):
frame = frame.astype(dtype)
if with_times:
yield t, frame
else:
yield frame

if progress_bar:
nframes = int(self.duration*fps)+1
return tqdm(generator(), total=nframes)

return generator()
logger = proglog.default_bar_logger(logger)
for t in logger.iter_bar(t=np.arange(0, self.duration, 1.0/fps)):
frame = self.get_frame(t)
if (dtype is not None) and (frame.dtype != dtype):
frame = frame.astype(dtype)
if with_times:
yield t, frame
else:
yield frame

def close(self):
"""
Expand Down
36 changes: 16 additions & 20 deletions moviepy/audio/AudioClip.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import numpy as np
import proglog
from moviepy.audio.io.ffmpeg_audiowriter import ffmpeg_audiowrite
from moviepy.decorators import requires_duration
from moviepy.tools import deprecated_version_of, extensions_dict
Expand Down Expand Up @@ -61,11 +62,12 @@ def __init__(self, make_frame=None, duration=None, fps=None):

@requires_duration
def iter_chunks(self, chunksize=None, chunk_duration=None, fps=None,
quantize=False, nbytes=2, progress_bar=False):
quantize=False, nbytes=2, logger=None):
""" Iterator that returns the whole sound array of the clip by chunks
"""
if fps is None:
fps = self.fps
logger = proglog.default_bar_logger(logger)
if chunk_duration is not None:
chunksize = int(chunk_duration*fps)

Expand All @@ -74,19 +76,13 @@ def iter_chunks(self, chunksize=None, chunk_duration=None, fps=None,
nchunks = totalsize // chunksize + 1

pospos = np.linspace(0, totalsize, nchunks + 1, endpoint=True, dtype=int)

def generator():
for i in range(nchunks):
size = pospos[i+1] - pospos[i]
assert(size <= chunksize)
tt = (1.0/fps)*np.arange(pospos[i], pospos[i+1])
yield self.to_soundarray(tt, nbytes=nbytes, quantize=quantize,
fps=fps, buffersize=chunksize)

if progress_bar:
return tqdm(generator(), total=nchunks)
else:
return generator()

for i in logger.iter_bar(chunk=list(range(nchunks))):
size = pospos[i+1] - pospos[i]
assert(size <= chunksize)
tt = (1.0/fps)*np.arange(pospos[i], pospos[i+1])
yield self.to_soundarray(tt, nbytes=nbytes, quantize=quantize,
fps=fps, buffersize=chunksize)

@requires_duration
def to_soundarray(self, tt=None, fps=None, quantize=False, nbytes=2, buffersize=50000):
Expand Down Expand Up @@ -136,19 +132,19 @@ def to_soundarray(self, tt=None, fps=None, quantize=False, nbytes=2, buffersize=

return snd_array

def max_volume(self, stereo=False, chunksize=50000, progress_bar=False):
def max_volume(self, stereo=False, chunksize=50000, logger=None):

stereo = stereo and (self.nchannels == 2)

maxi = np.array([0, 0]) if stereo else 0
for chunk in self.iter_chunks(chunksize=chunksize, progress_bar=progress_bar):
for chunk in self.iter_chunks(chunksize=chunksize,logger=logger):
maxi = np.maximum(maxi, abs(chunk).max(axis=0)) if stereo else max(maxi, abs(chunk).max())
return maxi

@requires_duration
def write_audiofile(self, filename, fps=None, nbytes=2, buffersize=2000,
codec=None, bitrate=None, ffmpeg_params=None,
write_logfile=False, verbose=True, progress_bar=True):
write_logfile=False, verbose=True, logger='bar'):
""" Writes an audio file from the AudioClip.
Expand Down Expand Up @@ -187,8 +183,8 @@ def write_audiofile(self, filename, fps=None, nbytes=2, buffersize=2000,
verbose
Boolean indicating whether to print infomation
progress_bar
Boolean indicating whether to show the progress bar.
logger
Either 'bar' or None or any Proglog logger
"""
if not fps:
Expand All @@ -210,7 +206,7 @@ def write_audiofile(self, filename, fps=None, nbytes=2, buffersize=2000,
codec=codec, bitrate=bitrate,
write_logfile=write_logfile, verbose=verbose,
ffmpeg_params=ffmpeg_params,
progress_bar=progress_bar)
logger=logger)


# The to_audiofile method is replaced by the more explicit write_audiofile.
Expand Down
35 changes: 9 additions & 26 deletions moviepy/audio/io/ffmpeg_audiowriter.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import subprocess as sp
import os
import proglog

from moviepy.compat import DEVNULL

import os

from moviepy.config import get_setting
from moviepy.decorators import requires_duration

from moviepy.tools import verbose_print


class FFMPEG_AudioWriter:
"""
Expand Down Expand Up @@ -146,19 +144,20 @@ def __exit__(self, exc_type, exc_value, traceback):
def ffmpeg_audiowrite(clip, filename, fps, nbytes, buffersize,
codec='libvorbis', bitrate=None,
write_logfile=False, verbose=True,
ffmpeg_params=None, progress_bar=True):
ffmpeg_params=None, logger='bar'):
"""
A function that wraps the FFMPEG_AudioWriter to write an AudioClip
to a file.
NOTE: verbose is deprecated.
"""

if write_logfile:
logfile = open(filename + ".log", 'w+')
else:
logfile = None

verbose_print(verbose, "[MoviePy] Writing audio in %s\n"%filename)

logger = proglog.default_bar_logger(logger)
logger(message="MoviePy - Writing audio in %s")
writer = FFMPEG_AudioWriter(filename, fps, nbytes, clip.nchannels,
codec=codec, bitrate=bitrate,
logfile=logfile,
Expand All @@ -167,27 +166,11 @@ def ffmpeg_audiowrite(clip, filename, fps, nbytes, buffersize,
for chunk in clip.iter_chunks(chunksize=buffersize,
quantize=True,
nbytes=nbytes, fps=fps,
progress_bar=progress_bar):
logger=logger):
writer.write_frames(chunk)

"""
totalsize = int(fps*clip.duration)
if (totalsize % buffersize == 0):
nchunks = totalsize // buffersize
else:
nchunks = totalsize // buffersize + 1
pospos = list(range(0, totalsize, buffersize))+[totalsize]
for i in tqdm(range(nchunks)):
tt = (1.0/fps)*np.arange(pospos[i],pospos[i+1])
sndarray = clip.to_soundarray(tt, nbytes= nbytes)
writer.write_frames(sndarray)
"""

writer.close()

if write_logfile:
logfile.close()

verbose_print(verbose, "[MoviePy] Done.\n")
logger(message="MoviePy - Done.")
17 changes: 11 additions & 6 deletions moviepy/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import sys
import warnings
import re
import proglog

import os
from .compat import DEVNULL
Expand All @@ -27,10 +28,13 @@ def verbose_print(verbose, s):
sys_write_flush(s)


def subprocess_call(cmd, verbose=True, errorprint=True):
""" Executes the given subprocess command."""

verbose_print(verbose, "\n[MoviePy] Running:\n>>> "+ " ".join(cmd))
def subprocess_call(cmd, logger='bar', errorprint=True):
""" Executes the given subprocess command.
Set logger to None or a custom Proglog logger to avoid printings.
"""
logger = proglog.default_bar_logger(logger)
logger(message='Moviepy - Running:\n>>> "+ " ".join(cmd)')

popen_params = {"stdout": DEVNULL,
"stderr": sp.PIPE,
Expand All @@ -45,10 +49,11 @@ def subprocess_call(cmd, verbose=True, errorprint=True):
proc.stderr.close()

if proc.returncode:
verbose_print(errorprint, "\n[MoviePy] This command returned an error !")
if errorprint:
logger(message='Moviepy - Command returned an error')
raise IOError(err.decode('utf8'))
else:
verbose_print(verbose, "\n... command successful.\n")
logger(message='Moviepy - Command successful')

del proc

Expand Down
Loading

0 comments on commit bfad5ea

Please sign in to comment.