@@ -250,30 +250,56 @@ class MovieWriter(AbstractMovieWriter):
250
250
251
251
def __init__ (self , fps = 5 , codec = None , bitrate = None , extra_args = None ,
252
252
metadata = None ):
253
- '''MovieWriter
253
+ """
254
+ MovieWriter
254
255
255
256
Parameters
256
257
----------
257
258
fps: int
258
259
Framerate for movie.
260
+
259
261
codec: string or None, optional
260
262
The codec to use. If ``None`` (the default) the ``animation.codec``
261
263
rcParam is used.
264
+
262
265
bitrate: int or None, optional
263
266
The bitrate for the saved movie file, which is one way to control
264
267
the output file size and quality. The default value is ``None``,
265
268
which uses the ``animation.bitrate`` rcParam. A value of -1
266
269
implies that the bitrate should be determined automatically by the
267
270
underlying utility.
268
- extra_args: list of strings or None, optional
269
- A list of extra string arguments to be passed to the underlying
270
- movie utility. The default is ``None``, which passes the additional
271
- arguments in the ``animation.extra_args`` rcParam.
271
+
272
+ extra_args: list of strings, string or None, optional
273
+ Either a list of extra string arguments to be passed to the
274
+ underlying movie utility or a full command string
275
+ explained below. The default is ``None``,which passes the
276
+ additional arguments in the ``animation.extra_args`` rcParam.
277
+
272
278
metadata: Dict[str, str] or None
273
279
A dictionary of keys and values for metadata to include in the
274
280
output file. Some keys that may be of use include:
275
281
title, artist, genre, subject, copyright, srcform, comment.
276
- '''
282
+
283
+ Notes
284
+ -----
285
+ *extra_args* can be a string with the full command line argument used
286
+ in the ffmpeg, imagemagick and avconv writers. The string is then
287
+ formatted with the python method ``format``. Possible keywords for the
288
+ pipe based writers are::
289
+
290
+ path, fps, delay=100/fps, x_size, y_size (in pixels),
291
+ frame_format, codec, bitrate, outfile
292
+
293
+ and for the file bases writers::
294
+
295
+ path, fps, delay=100/fps, frame_format, temp_name,
296
+ N (number of frames ), codec, bitrate, outfile
297
+
298
+ an example command string is::
299
+
300
+ 'ffmpeg -r {fps} -i _tmp%07d.png -r 25 -y {outfile}'
301
+
302
+ """
277
303
self .fps = fps
278
304
self .frame_format = 'rgba'
279
305
@@ -292,6 +318,12 @@ def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,
292
318
else :
293
319
self .extra_args = extra_args
294
320
321
+ if type (self .extra_args ) == str :
322
+ self .full_command = extra_args
323
+ self .extra_args = None
324
+ else :
325
+ self .full_command = None
326
+
295
327
if metadata is None :
296
328
self .metadata = dict ()
297
329
else :
@@ -316,7 +348,7 @@ def _adjust_frame_size(self):
316
348
_log .debug ('frame size in pixels is %s x %s' , * self .frame_size )
317
349
return w , h
318
350
319
- def setup (self , fig , outfile , dpi = None ):
351
+ def setup (self , fig , outfile , dpi = None , run = True ):
320
352
'''
321
353
Perform setup for writing the movie file.
322
354
@@ -329,6 +361,8 @@ def setup(self, fig, outfile, dpi=None):
329
361
dpi : int, optional
330
362
The DPI (or resolution) for the file. This controls the size
331
363
in pixels of the resulting movie file. Default is fig.dpi.
364
+ run : bool, optional
365
+ The command to save the movie is run if set to True.
332
366
'''
333
367
self .outfile = outfile
334
368
self .fig = fig
@@ -339,7 +373,8 @@ def setup(self, fig, outfile, dpi=None):
339
373
340
374
# Run here so that grab_frame() can write the data to a pipe. This
341
375
# eliminates the need for temp files.
342
- self ._run ()
376
+ if run :
377
+ self ._run ()
343
378
344
379
def _run (self ):
345
380
# Uses subprocess to call the program for assembling frames into a
@@ -413,6 +448,44 @@ def isAvailable(cls):
413
448
'''
414
449
return shutil .which (cls .bin_path ()) is not None
415
450
451
+ def _get_full_command (self ):
452
+ """
453
+ Make string formating on the *full_command* string.
454
+
455
+ The string syntax should be '{path} -r {fps}' where possible keywords
456
+ are path, fps, delay=100/fps, x_size, y_size (in pixels), frame_format,
457
+ codec, bitrate, outfile.
458
+ """
459
+ arg_dict = dict (path = self .bin_path (),
460
+ fps = str (self .fps ),
461
+ delay = str (100. / self .fps ),
462
+ x_size = self .frame_size [0 ],
463
+ y_size = self .frame_size [1 ],
464
+ frame_format = self .frame_format ,
465
+ codec = self .codec ,
466
+ bitrate = self .bitrate ,
467
+ outfile = self .outfile )
468
+
469
+ return self .full_command .format (** arg_dict ).split ()
470
+
471
+ def get_command (self ):
472
+ """
473
+ Returns the command line as a string.
474
+
475
+ `.setup` should be called before `.get_command` so all variables are
476
+ set. This could either be done explicitely or by `.Animation.save`.
477
+ The first method results in an incorrect value of number of frames
478
+ where applicable.
479
+
480
+ The empty string is returned if not all variables where set or if the
481
+ writer don't use a command line.
482
+ """
483
+ try :
484
+ return ' ' .join (self ._args ())
485
+ except :
486
+ _log .warning ("The command line could not be show for this writer"
487
+ " or all variables where not set with setup." )
488
+ return ''
416
489
417
490
class FileMovieWriter (MovieWriter ):
418
491
'''`MovieWriter` for writing to individual files and stitching at the end.
@@ -543,6 +616,27 @@ def cleanup(self):
543
616
for fname in self ._temp_names :
544
617
os .remove (fname )
545
618
619
+ def _get_full_command (self ):
620
+ """
621
+ Make string formating on the *full_command* input string.
622
+
623
+ The string syntax should be '{path} -r {fps}' where possible keywords
624
+ are path, fps, delay=100/fps, frame_format, temp_name, N (number of
625
+ frames ), codec, bitrate, outfile.
626
+ """
627
+
628
+ arg_dict = dict (path = self .bin_path (),
629
+ fps = str (self .fps ),
630
+ delay = str (100. / self .fps ),
631
+ frame_format = self .frame_format ,
632
+ temp_name = self ._base_temp_name (),
633
+ N = str (self ._frame_counter ),
634
+ codec = self .codec ,
635
+ bitrate = self .bitrate ,
636
+ outfile = self .outfile )
637
+
638
+ return self .full_command .format (** arg_dict ).split ()
639
+
546
640
547
641
@writers .register ('pillow' )
548
642
class PillowWriter (MovieWriter ):
@@ -637,6 +731,8 @@ class FFMpegWriter(FFMpegBase, MovieWriter):
637
731
def _args (self ):
638
732
# Returns the command line parameters for subprocess to use
639
733
# ffmpeg to create a movie using a pipe.
734
+ if self .full_command :
735
+ return self ._get_full_command ()
640
736
args = [self .bin_path (), '-f' , 'rawvideo' , '-vcodec' , 'rawvideo' ,
641
737
'-s' , '%dx%d' % self .frame_size , '-pix_fmt' , self .frame_format ,
642
738
'-r' , str (self .fps )]
@@ -662,6 +758,8 @@ class FFMpegFileWriter(FFMpegBase, FileMovieWriter):
662
758
'pbm' , 'raw' , 'rgba' ]
663
759
664
760
def _args (self ):
761
+ if self .full_command :
762
+ return self ._get_full_command ()
665
763
# Returns the command line parameters for subprocess to use
666
764
# ffmpeg to create a movie using a collection of temp images
667
765
return [self .bin_path (), '-r' , str (self .fps ),
@@ -768,6 +866,8 @@ class ImageMagickWriter(ImageMagickBase, MovieWriter):
768
866
769
867
'''
770
868
def _args (self ):
869
+ if self .full_command :
870
+ return self ._get_full_command ()
771
871
return ([self .bin_path (),
772
872
'-size' , '%ix%i' % self .frame_size , '-depth' , '8' ,
773
873
'-delay' , str (self .delay ), '-loop' , '0' ,
@@ -792,8 +892,11 @@ class ImageMagickFileWriter(ImageMagickBase, FileMovieWriter):
792
892
'pbm' , 'raw' , 'rgba' ]
793
893
794
894
def _args (self ):
895
+ self .fname_format_str = '%s*.%s'
896
+ if self .full_command :
897
+ return self ._get_full_command ()
795
898
return ([self .bin_path (), '-delay' , str (self .delay ), '-loop' , '0' ,
796
- '%s*.%s' % ( self .temp_prefix , self . frame_format )]
899
+ self ._base_temp_name ( )]
797
900
+ self .output_args )
798
901
799
902
0 commit comments