Package toon :: Module mencoder
[hide private]
[frames] | no frames]

Source Code for Module toon.mencoder

  1  #!/usr/bin/env python 
  2  # 
  3  # Toonloop for Python 
  4  # 
  5  # Copyright 2008 Alexandre Quessy & Tristan Matthews 
  6  # http://toonloop.com 
  7  #  
  8  # Original idea by Alexandre Quessy 
  9  # http://alexandre.quessy.net 
 10  # 
 11  # Toonloop is free software: you can redistribute it and/or modify 
 12  # it under the terms of the GNU General Public License as published by 
 13  # the Free Software Foundation, either version 3 of the License, or 
 14  # (at your option) any later version. 
 15  # 
 16  # Toonloop is distributed in the hope that it will be useful, 
 17  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 18  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 19  # GNU General Public License for more details. 
 20  # 
 21  # You should have received a copy of the gnu general public license 
 22  # along with Toonloop.  If not, see <http://www.gnu.org/licenses/>. 
 23  # 
 24  """ 
 25  Converts a series a JPEG images to a MJPEG-4 video file using mencoder. 
 26   
 27  The output will be in the same dirctory than the inputs.  
 28  It is possible to append the path to the mencoder executable like this : 
 29  os.environ['PATH'] += ":/Applications/Toonloop.app/Contents/Resources/bin" 
 30   
 31  An other useful beautiful line of code : mencoder -oac copy -ovc copy *.mov -o final_movie.mov 
 32  """ 
 33   
 34  import os 
 35  import pprint 
 36  import sys 
 37  import traceback 
 38  try: 
 39      import cStringIO as StringIO 
 40  except ImportError: 
 41      import StringIO 
 42  from twisted.internet import defer 
 43  from twisted.internet import reactor 
 44  from twisted.internet import protocol 
 45  from twisted.internet import utils 
 46  from twisted.python import failure 
 47  from twisted.python import procutils 
 48  # TODO: import twisted log 
 49   
 50  # variables 
 51  mencoder_executable = '' 
 52  try: 
 53      mencoder_executable = procutils.which('mencoder')[0] # gets the executable 
 54  except IndexError: 
 55      print "mencoder must be in your $PATH" 
 56      print "mencoder conversion is disabled" 
 57      # sys.exit(1) 
 58  movie_name_suffix = "" 
 59   
60 -class MencoderError(Exception):
61 """ 62 Any error this module can raise. 63 """ 64 pass
65
66 -def cb_error(command_failure, args):
67 print "FAILURE" 68 pprint.pprint({'failure':command_failure, 'exception':sys.exc_info(), 'args':args}) 69 # traceback.print_tb(sys.exc_info()[2]) 70 print '>>>> Exception message : %s' % (command_failure.value.message)
71
72 -def cb_success(result, args):
73 """ 74 Called once a bunch of child processes are done. 75 76 @param success_results a tuple of (boolean,str) tuples 77 @param commands is a list of the provided commands 78 @param callback is a callback to call once done. 79 80 Args are: the command that it the results if from, text data resulting from it, callback to call once done. 81 callback should be called with the same arguments. command, results, callback (but results can be something else than text) 82 83 This is the default callback for commands. 84 You should provide an other callback as argument to the commands starter functions. 85 You can copy-paste this one to start with. 86 """ 87 print "SUCCESSFULLY converted JPEG images to movie" 88 print "mencoder arguments:", args 89 print "\nmencoder output:" 90 print result[0] # stdout
91 92 # success, results_infos = result 93 # command = commands[i] 94 # print ">>>>>>>>>>>>>>>> command : %s <<<<<<<<<<<<<<<" % (command) 95 # if isinstance(results_infos, failure.Failure): 96 # print ">>>> FAILURE : ", results_infos.getErrorMessage() # if there is an error, the programmer should fix it. 97 # else: 98 # stdout, stderr, signal_or_code = results_infos 99 # print ">>>> stdout: %s" % (stdout) 100 # print ">>>> stderr: %s" % (stderr) 101 # if success: 102 # print ">>>> Success !" 103 # print ">>>> code is ", signal_or_code 104 # else: 105 # print ">>>> Failure !" 106 # print ">>>> signal is ", signal_or_code 107
108 -def jpeg_to_movie(filename_pattern, path='.', fps=12, verbose=False, w=640, h=480):
109 """ 110 Converts a series a JPEG images to a MJPEG movie. 111 112 :param input_files: string with a wildcard such as "spam_*.jpg" 113 :param output_file: string such as "output.mov" 114 """ 115 global mencoder_executable 116 global movie_name_suffix 117 if mencoder_executable is '': 118 msg = "mencoder not currently installed. Cannot save to movie." 119 return failure.Failure(MencoderError(msg)) 120 else: 121 abs_filename = os.path.join(path, filename_pattern) 122 jpegs = "mf://%s*.jpg" % (abs_filename) 123 output_file = "%s%s.mov" % (abs_filename, movie_name_suffix) 124 #txt_args = """%s -quiet -mf w=%d:h=%d:fps=%s:type=jpg -ovc copy -oac copy -o %s""" % (jpegs, w, h, fps, output_file) 125 txt_args = """%s -quiet -mf w=%d:h=%d:fps=%s:type=jpg -ovc lavc -lavcopts vcodec=mjpeg -oac copy -of lavf -lavfopts format=mov -o %s""" % (jpegs, w, h, fps, output_file) 126 args = txt_args.split() 127 if verbose: 128 print "$ mencoder %s" % (txt_args) 129 try: 130 deferred = utils.getProcessOutputAndValue(mencoder_executable, args, os.environ, path, reactor) 131 # TODO: get rid of this and, instead, change utils.commands and add it a 132 # ProcessProtocol which supports a timeout. 133 except Exception,e: 134 print "error :", sys.exc_info() 135 log.critical('Cannot start the command %s. Reason: %s' % (executable, str(e.message))) 136 # raise 137 else: 138 deferred.addErrback(cb_error, args) 139 #deferred.addCallback(cb_success, args) 140 return deferred
141 142 if __name__ == '__main__':
143 - def stop(arg):
144 print "stopping reactor", arg 145 reactor.stop()
146 - def start(filename_pattern, path, fps):
147 deferred = jpeg_to_movie(filename_pattern, path, fps) 148 deferred.addCallback(cb_success, args) 149 #deferred.addCallback(stop) 150 deferred.addErrback(stop)
151 152 print "#################################################################" 153 path = '.' 154 #path = '/home/aalex/src/toonloop/trunk/py/toon' 155 filename_pattern = "2009-03-07_05h13m49_" 156 fps = 12 157 reactor.callLater(0, start, filename_pattern, path, fps, True) 158 print "starting reactor" 159 reactor.run() 160