- Timestamp:
- 07/03/09 10:03:30 (13 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
plumimediaqueue/trunk/src/plumimediaqueue/queues/transcoding.py
r656 r922 4 4 5 5 from plumimediaqueue.models import Queue, NetworkMediaItem 6 7 import logging 8 import os6 from plumimediaqueue.events.interfaces import IJobResetEvent 7 8 import logging , os , traceback , time, subprocess 9 9 10 10 class ITranscodingQueue(IQueue): … … 14 14 ) 15 15 16 mencoder_installed_location = Text( 17 title = u"MEncoder", 18 description=u"The file path to a MEncoder executable" 19 ) 20 21 ffmpeg2theora_installed_location = Text( 22 title = u"ffmpeg2theora", 23 description=u"The file path to a ffmpeg2theora executable" 24 ) 25 26 flvtool_installed_location = Text( 27 title = u"flvtool2", 28 description=u"The file path to a flvtool2 executable" 29 ) 30 16 31 mencoder_flv_options = Text( 17 32 title = u"MEncoder command line to produce FLV files.", 18 33 description=u"The set of options to pass to MEncoder when transcoding" 19 34 ) 35 36 ffmpeg2theora_options = Text( 37 title = u"ffmpeg2theora command line to produce OGV files.", 38 description=u"The set of options to pass to ffmpeg2theora when transcoding" 39 ) 40 41 42 mencoder_flv_highquality_options = Text( 43 title = u"MEncoder command line to produce high quality FLV files.", 44 description=u"The set of options to pass to MEncoder when transcoding" 45 ) 46 47 ffmpeg2theora_highquality_options = Text( 48 title = u"ffmpeg2theora command line to produce high-quality OGV files.", 49 description=u"The set of options to pass to ffmpeg2theora when transcoding" 50 ) 51 52 nice_level = Text( 53 title = u"Unix nice level", 54 description=u"The level to 'renice' the transcoding processes" 55 ) 56 57 20 58 21 59 file_extensions = List( … … 25 63 ) 26 64 27 flowplayer_URL_SWF = URI (28 title=u'URL of Flowplayer SWF',29 description=u'Network address of FlowPlayer movie to serve.'30 )31 32 videohost_URL = URI (33 title=u'URL of transcoded media server.',34 description=u'Network domain name for transcoded media server.'35 )36 37 38 65 class TranscodingQueue(Queue): 39 66 grok.implements(ITranscodingQueue) 40 67 41 68 #set a sensible default for downloading 42 transcoding_dir=os.path.join(os.getcwd(),'download_queue_files') 69 transcoding_dir=os.path.join(os.getcwd(),'transcoding_queue_files') 70 71 mencoder_installed_location = '/usr/local/bin/mencoder' 72 ffmpeg2theora_installed_location = '/usr/bin/ffmpeg2theora' 73 flvtool_installed_location = '/usr/bin/flvtool2' 43 74 44 75 mencoder_flv_options='-really-quiet -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:keyint=50:vbitrate=150:mbd=2:mv0:trell:v4mv:cbp:last_pred=3 -vf scale=320:240 -srate 22050' 45 76 77 mencoder_flv_highquality_options='-really-quiet -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:keyint=50:vbitrate=250:mbd=2:mv0:trell:v4mv:cbp:last_pred=3 -vf scale=720:480 -srate 22050' 78 46 79 file_extensions=['.avi','.qt','.mov','.mpeg','.mp4','.mpg','.asf','.wmv','.3gp','.m4v','.ogm','.ogg','.divx','flv'] 47 80 48 flowplayer_URL_SWF = 'http://flv.plumi.org/flowplayer/FlowPlayer.swf' 49 50 videohost_URL = '' 81 ffmpeg2theora_options = '-p preview' 82 83 ffmpeg2theora_highquality_options = '-p pro' 84 85 nice_level = '10' 51 86 52 87 def __init__(self,id=None): … … 63 98 64 99 @grok.subscribe(NetworkMediaItem, grok.IObjectAddedEvent) 100 @grok.subscribe(NetworkMediaItem, IJobResetEvent) 65 101 def handle(obj, event): 66 102 #check if the JobItem is STARTING … … 78 114 79 115 def attempt_transcode_file(transcoding_queue, networkmediaitem): 80 """Start the transcoding attempt with file 'f'. Converts to FLV format, and OGG/Theora. Produces HTML snippets for including the players appropriate for the produced video format. At the moment, this is FlowPlayer/JW Player for FLV, and Cortado java applet for OGG/Theora"""116 """Start the transcoding attempt with file 'f'. Converts to FLV format, and OGG/Theora. XXX other mobile formats """ 81 117 #whether or not the transcoding worked for the given file 'f' 82 118 worked = False 119 120 #from this queue, we can get our sibling queue 'download' 121 #XXX abstract the names in app.py , and give them constants 122 dld_dir=transcoding_queue.__parent__['download'].download_dir 83 123 84 124 #get filepath, and then split into stem and extension, and return false straight away if not in recognised set. … … 89 129 90 130 #setup filenames we will need. 91 videofile = f92 lockfile = f+".trans_lock" # we are encoding already93 skipfile = f+".trans_skip" # we tried and failed, don't bother again94 flvfile = transcoding_queue.transcoding_dir + stem + ".flv" # output FLV file95 theorafile = transcoding_queue.transcoding_dir + ".ogg" # output OGGfile96 includefile = self.INCLUDE_FILE_DIRECTORY+stem+self.INCLUDE_FILE_SUFFIX97 logging.info("using %s, %s, %s %s %s " % (lockfile, skipfile, flvfile, theorafile, includefile))131 original_videofile = f 132 video_file = f.replace(dld_dir,transcoding_queue.transcoding_dir) 133 lockfile = video_file+".trans_lock" # we are encoding already 134 skipfile = video_file+".trans_skip" # we tried and failed, don't bother again 135 flvfile = video_file + ".flv" # output FLV file 136 theorafile = video_file + ".ogv" # output OGG file 137 logging.info("using %s, %s, %s, %s %s " % (video_file, lockfile, skipfile, flvfile, theorafile)) 98 138 99 139 #check that another encoder isnt already processing this file (lockfile) or that we havent tried and failed before (skipfile) 100 if os.path.exists(skipfile) or os.path (lockfile):140 if os.path.exists(skipfile) or os.path.exists(lockfile): 101 141 #dont do it 102 142 return False 103 143 104 144 #OK, valid video file ready to try to transcode 105 logging.info(" Checking file %s, using extension %s " % (videofile, extension))145 logging.info("Using original file %s, using extension %s " % (original_videofile, extension)) 106 146 try: 147 #lets make sure all the directories are created 148 try: 149 os.makedirs(os.path.dirname(lockfile)) 150 except: 151 #the dirs may already exist 152 pass 153 107 154 # touch the lock file 108 155 #we should catch the exception here, and return FALSE! … … 112 159 logging.info("lock file creation failed! ABORTING. %s " % lockfile) 113 160 return False 114 #lets make sure all the directories are created115 try:116 os.makedirs(os.path.dirname(flvfile))117 except:118 #the dirs may already exist119 pass120 161 121 logging.info('OK to try encoding: '+ videofile)162 logging.info('OK to try encoding: '+original_videofile) 122 163 #mencoder flv conversion 123 164 start_time=time.time() 124 encoder_command = self.MENCODER_LOCATION + " -quiet " + videofile + " -o " + flvfile + " " + self.MENCODER_OPTIONS125 encoder_command_string = 'nice -n '+ self.BE_HOW_NICE+' '+encoder_command165 encoder_command = transcoding_queue.mencoder_installed_location + " -quiet " + original_videofile + " -o " + flvfile + " " + transcoding_queue.mencoder_flv_options 166 encoder_command_string = 'nice -n '+ transcoding_queue.nice_level +' '+encoder_command 126 167 output,error = subprocess.Popen([encoder_command_string],shell=True,stdout=subprocess.PIPE,cwd=os.getcwd()).communicate() 127 168 logging.debug("FLV transcoder output: %s ; error: %s" %(output,error)) 128 flvtool_command = self.FLVTOOL_LOCATION+" -U stdin "+flvfile129 flvtool_command_string = "cat "+ flvfile +" | "+ 'nice -n '+ self.BE_HOW_NICE+' '+flvtool_command169 flvtool_command = transcoding_queue.flvtool_installed_location+" -U stdin "+flvfile 170 flvtool_command_string = "cat "+ flvfile +" | "+ 'nice -n '+ transcoding_queue.nice_level + ' '+flvtool_command 130 171 output,error = subprocess.Popen([flvtool_command_string],shell=True,stdout=subprocess.PIPE,cwd=os.getcwd()).communicate() 131 172 logging.debug("FLV tool output: %s ; error: %s" %(output,error)) 132 173 #XXX update the set of transformed file paths on the item. 133 174 finish_time=time.time() 134 logging.info("Encoded %s in %.2f seconds, using cmd -- %s" % ( videofile,finish_time-start_time,encoder_command_string))175 logging.info("Encoded %s in %.2f seconds, using cmd -- %s" % (original_videofile,finish_time-start_time,encoder_command_string)) 135 176 136 177 #ffmpeg2theora , theora/ogg conversion 137 178 start_time=time.time() 138 theora_cmd = self.FFMPEG2THEORA_COMMAND + ' ' + videofile + " -o " + theorafile139 theora_cmd_string='nice -n '+ self.BE_HOW_NICE+' '+ theora_cmd179 theora_cmd = transcoding_queue.ffmpeg2theora_installed_location + ' ' + transcoding_queue.ffmpeg2theora_options + " -o " + theorafile + ' ' + original_videofile 180 theora_cmd_string='nice -n '+ transcoding_queue.nice_level+ ' '+ theora_cmd 140 181 output,error = subprocess.Popen([theora_cmd_string],shell=True,stdout=subprocess.PIPE,cwd=os.getcwd()).communicate() 141 182 logging.debug("Theora output: %s ; error: %s" %(output,error)) 142 183 #XXX update the set of transformed file paths on the item. 143 184 finish_time=time.time() 144 logging.info("Encoded %s in %.2f seconds, using cmd -- %s" % ( videofile,finish_time-start_time,theora_cmd_string))185 logging.info("Encoded %s in %.2f seconds, using cmd -- %s" % (original_videofile,finish_time-start_time,theora_cmd_string)) 145 186 146 187 if os.path.exists(flvfile) and os.path.getsize(flvfile)>0 and os.path.exists(theorafile) and os.path.getsize(theorafile)>0: 147 188 # OK ! It Worked. 189 190 #update the object with the details of the new file paths. 191 networkmediaitem.processed_filepaths=(flvfile,theorafile) 192 148 193 worked = True 149 194 else: … … 154 199 return False 155 200 156 #Now, make the flash HTML snippet if the flv and Theora got created correctly.157 #XXX todo, separate out the flv and ogg theora (java applet) html snippet158 if os.path.exists(flvfile) and os.path.getsize(flvfile)>0:159 #lets make sure all the directories are created160 try:161 os.makedirs(os.path.dirname(includefile))162 except:163 #the dirs may already exist164 pass165 166 logging.info("Making html template - original size of %s: %.1fMB, Encoded size: %.1fMB" % (videofile,os.path.getsize(videofile)/1000000.0,os.path.getsize(flvfile)/1000000.0))167 data_map={168 'flowplayer_location':self.FLOWPLAYER_LOCATION,169 'videofile':flvfile,170 'videobaseurl':self.VIDEO_SERVER_URL,171 'splashbaseurl':self.SPLASH_IMAGE_BASE,172 'splashfile':self.SPLASH_IMAGE_FILE,173 'cortado_location':self.CORTADO_LOCATION,174 'oggfile':theorafile,175 }176 template = Template(file=self.INCLUDE_TEMPLATE, searchList=[data_map])177 file_template=open(includefile, 'w')178 file_template.write(template.respond())179 file_template.close()180 181 182 201 except: 183 logging.info("Error while processing %s: %s" % ( videofile,traceback.format_exc()))202 logging.info("Error while processing %s: %s" % (original_videofile,traceback.format_exc())) 184 203 #catch exception to remove lock file. 185 204 os.remove(lockfile) 186 205 return False 187 206 207 os.remove(lockfile) 188 208 #return a status value if we managed to get all the way here. 189 209 return worked
