Package imagizer :: Module NommeVideo
[hide private]
[frames] | no frames]

Source Code for Module imagizer.NommeVideo

  1  #!/usr/bin/env python 
  2  # -*- coding: UTF-8 -*- 
  3  #Written by Jerome Kieffer 20100420 Licence GPLv3+ 
  4  #Find all the videos and renames them, compress then .... and write an html file to set online 
  5   
  6  import os.path as OP 
  7  import os, sys, tempfile, shutil, datetime, time, locale 
  8  from hachoir_core.error import HachoirError 
  9  from hachoir_core.cmd_line import unicodeFilename 
 10  from hachoir_parser import createParser 
 11  #from hachoir_core.tools import makePrintable 
 12  from hachoir_metadata import extractMetadata 
 13  #from hachoir_core.i18n import getTerminalCharset 
 14   
 15  local = locale.getdefaultlocale()[1] 
 16  webEncoding = "latin1" 
 17  fileEncoding = "UTF8" 
 18   
 19  VBitrate = 600 
 20  ABitRate = 64 
 21  x264opts = "subq=7:nr=100:me=umh:partitions=all:direct_pred=auto:b_pyramid:bframes=3:frameref=5 -ofps 24" 
 22  mplayer = "/usr/bin/mplayer" 
 23  mencoder = "/usr/bin/mencoder" 
 24  sox = "/usr/bin/sox" 
 25  convert = "/usr/bin/convert" 
 26  avimerge = "/usr/bin/avimerge" 
 27   
 28  VideoExts = [".avi", ".mpeg", ".mpg", ".mp4", ".divx", ".mov"] 
 29  ThumbExts = [".thm", ".jpg"] 
 30   
 31  RootDir = os.getcwd() 
 32  UpperDir = OP.split(RootDir)[0] 
 33   
 34   
35 -class Video:
36 """main Video class"""
37 - def __init__(self, infile):
38 """initialise the class""" 39 self.FullPath = OP.abspath(infile) 40 print "Processing %s" % self.FullPath 41 [self.Path, self.Video] = OP.split(self.FullPath) 42 self.title = u"" 43 self.Width = 0 44 self.Height = 0 45 self.Rotate = None 46 self.Duration = 0 47 self.Producer = "Imagizer" 48 self.data = {} 49 self.DateTime = datetime.datetime.fromtimestamp(OP.getmtime(self.FullPath)) 50 self.LoadMetadata() 51 if self.Producer.lower().strip() in ["mencoder", "transcode", "imagizer"]: 52 if self.Video.lower().startswith("dscf") :self.Producer = "Fuji" 53 elif self.Video.lower().startswith("mvi_"):self.Producer = "Canon" 54 elif self.Video.lower().startswith("mov") :self.Producer = "Sony" 55 elif self.Video.lower().startswith("sdc") :self.Producer = "Samsung" 56 print "DEBUG", self.Video.lower(), self.Producer 57 dirname = OP.split(self.Path)[1] 58 dirdate = None 59 if len(dirname) >= 10: 60 if dirname[0] == "M": dirname = dirname[1:] 61 try: 62 dirdate = datetime.datetime.fromtimestamp(time.mktime(time.strptime(dirname[:10], "%Y-%m-%d"))) 63 except: 64 pass 65 if dirdate: 66 if dirdate.date() < self.DateTime.date(): 67 self.DateTime = datetime.datetime.combine(dirdate.date(), self.DateTime.time()) 68 self.data["ICRD"] = self.DateTime.strftime("%Y-%m-%d") 69 self.data["ISRF"] = self.Producer 70 self.data["IARL"] = self.Video.replace("-H264", "") 71 self.CommentFile = OP.splitext(self.FullPath.replace(" ", "_"))[0] + ".txt" 72 if OP.isfile(self.CommentFile): 73 for l in open(OP.splitext(self.FullPath.replace(" ", "_"))[0] + ".txt").readlines(): 74 if len(l) > 2: 75 k, d = l.decode(fileEncoding).split(None, 1) 76 self.data[k] = d.strip() 77 self.Date = datetime.datetime.fromtimestamp(time.mktime(time.strptime(self.data["ICRD"], "%Y-%m-%d"))) 78 if self.Date.date < self.DateTime.date: 79 self.DateTime = datetime.datetime.combine(self.Date.date(), self.DateTime.time()) 80 self.Producer = self.data["ISRF"]
81
82 - def __repr__(self):
83 """Returns some information on the current video flux""" 84 txt = u"%s\n" % self.Video 85 txt += "Producer: %s\tWidth= %i\tHeigth= %i\n" % (self.Producer, self.Width, self.Height) 86 txt += "Type: %s,\t title:%s\n" % (type(self.title), self.title) 87 for i in self.data: 88 txt += "\t%s:\t%s\n" % (i, self.data[i]) 89 return txt
90
91 - def MkDir(self):
92 if not OP.isdir("%s/%s" % (UpperDir, self.DateTime.date().isoformat())): 93 os.mkdir("%s/%s" % (UpperDir, self.DateTime.date().isoformat())) 94 self.DestFile = os.path.join(UpperDir, self.DateTime.date().isoformat(), "%s-%s.avi" % (self.DateTime.strftime("%Hh%Mm%Ss"), self.Producer)) 95 if OP.isfile(self.DestFile): 96 print "*" * 80 + "\n** Warning Destination file exists ! **\n" + "*" * 80
97
98 - def LoadMetadata(self):
99 """Load the metadata, either using Hachoir, ... either using mplayer""" 100 if len(self.Video) != 0: 101 filename = OP.join(self.Path, self.Video) 102 filename, realname = unicodeFilename(filename), filename 103 parser = createParser(filename, realname) 104 try: 105 self.metadata = extractMetadata(parser) 106 except HachoirError, err: 107 print "Metadata extraction error: %s" % unicode(err) 108 self.metadata = None 109 if self.metadata: 110 DoMplayer = False 111 try: 112 self.DateTime = self.metadata.get("creation_date") 113 except: 114 pass 115 if type(self.DateTime) == type(datetime.date(2000, 10, 10)): 116 try: 117 hour = datetime.time(*time.strptime(self.Video[:9], "%Hh%Mm%Ss")[3:6]) 118 except: 119 hour = datetime.time(0, 0, 0) 120 self.DateTime = datetime.datetime.combine(self.DateTime, hour) 121 self.Duration = self.metadata.get("duration") 122 self.Width = self.metadata.get("width") 123 try: 124 self.title = self.metadata.get("title") 125 except: 126 self.title = "" 127 convertLatin1ToUTF8 = False 128 for i in self.title: 129 #print i, ord(i) 130 if ord(i) > 127: convertLatin1ToUTF8 = True 131 if convertLatin1ToUTF8: 132 self.title = self.title.encode("latin1").decode("UTF8") 133 #Work-around for latin1 related bug 134 self.Height = self.metadata.get("height") 135 try: 136 self.FrameRate = self.metadata.get("frame_rate") 137 except: 138 self.FrameRate = 24 #default value for Canon G11 139 try: 140 self.BitRate = self.metadata.get("bit_rate") 141 except: 142 self.BitRate = None 143 try: 144 self.Producer = self.metadata.get("producer").replace(" ", "_") 145 except: 146 self.Producer = "Imagizer" 147 try: 148 self.metadata.iterGroups() 149 except: 150 DoMplayer = True 151 if DoMplayer: 152 self.MplayerMetadata() 153 else: 154 for n in self.metadata.iterGroups(): 155 if n.header.find("Video stream") == 0: 156 self.VideoCodec = n.get("compression") 157 self.VideoBpP = n.get("bits_per_pixel") 158 elif n.header.find("Audio stream") == 0: 159 self.AudioCodec = n.get("compression") 160 self.AudioBitRate = n.get("bit_rate") 161 self.VideoBitRate = self.BitRate - self.AudioBitRate 162 self.AudioChannel = n.get("nb_channel") 163 self.AudioSampleRate = n.get("sample_rate") 164 try: 165 self.AudioBits = n.get("bits_per_sample") 166 except: 167 self.AudioBits = None 168 else:#Doing it in the not clean way, i.e. parse mplayer output ! 169 self.MplayerMetadata()
170
171 - def MplayerMetadata(self):
172 """Extract metadata using Mplayer""" 173 for i in os.popen('%s "%s" -identify -vo null -ao null -frames 0 ' % (mplayer, self.FullPath)).readlines(): 174 if i.find("ID_AUDIO_NCH") == 0:self.AudioChannel = int(i.split("=")[1].strip()) 175 elif i.find("ID_AUDIO_CODEC") == 0:self.AudioCodec = i.split("=")[1].strip() 176 elif i.find("ID_AUDIO_RATE") == 0:self.AudioSampleRate = int(i.split("=")[1].strip()) 177 elif i.find("ID_AUDIO_BITRATE") == 0:self.AudioBitRate = int(i.split("=")[1].strip()) 178 elif i.find("ID_VIDEO_CODEC") == 0:self.VideoCodec = i.split("=")[1].strip() 179 elif i.find("ID_LENGTH") == 0:self.Duration = float(i.split("=")[1].strip()) 180 elif i.find("ID_VIDEO_FPS") == 0:self.FrameRate = float(i.split("=")[1].strip()) 181 elif i.find("ID_VIDEO_HEIGHT") == 0:self.Height = int(i.split("=")[1].strip()) 182 elif i.find("ID_VIDEO_WIDTH") == 0:self.Width = int(i.split("=")[1].strip())
183
184 - def FindThumb(self):
185 """scan the current directory for the thumbnail image""" 186 for i in os.listdir(self.Path): 187 b, e = OP.splitext(i) 188 if self.Video.find(b) == 0 and e.lower() in ThumbExts: 189 self.Thumb = i 190 filename = OP.join(self.Path, self.Thumb) 191 filename, realname = unicodeFilename(filename), filename 192 parser = createParser(filename, realname) 193 try: 194 exif = extractMetadata(parser) 195 except: 196 return 197 try: 198 self.Rotate = exif.get("image_orientation") 199 except: 200 self.Rotate = None 201 print self.Rotate 202 ThmDate = exif.get("creation_date") 203 if (self.DateTime - ThmDate).days > 0:self.DateTime = ThmDate
204 - def PlayVideo(self):
205 """Plays the video using mplayer, tries to rotate the video of needed""" 206 if self.Rotate: 207 if self.Rotate == u"Rotated 90 clock-wise": 208 os.system('mplayer -vf rotate=1 "%s"' % self.FullPath) 209 elif self.Rotate == u"Rotated 90 counter clock-wise": 210 os.system('mplayer -vf rotate=2 "%s"' % self.FullPath) 211 else: 212 os.system('mplayer "%s"' % self.FullPath) 213 else: 214 os.system('mplayer "%s"' % self.FullPath) 215 rotate = raw_input("What rotation should be applied to the file ? [0] ") 216 rotate = rotate.strip().lower().decode(local) 217 print rotate 218 if rotate in ["90", "cw"]: 219 self.Rotate = u"Rotated 90 clock-wise" 220 elif rotate in ["-90", "270", "ccw"]: 221 self.Rotate = u"Rotated 90 counter clock-wise" 222 else: 223 self.Rotate = u"Horizontal (normal)"
224 - def SetTitle(self):
225 """asks for a Title and comments for the video""" 226 print "Processing file %s" % self.FullPath 227 print "Producer : %s" % self.Producer 228 if self.data.has_key("INAM"): 229 print "Former title: %s" % self.data["INAM"] 230 title = raw_input("Title (INAM): ").decode(local) 231 if len(title) > 0: 232 self.data["INAM"] = title.strip() 233 if self.data.has_key("IKEY"): 234 print "Former keywords: " + "\t".join(self.data["IKEY"].split(";")) 235 keywords = raw_input("Keywords (IKEY): ").decode(local).split() 236 if len(keywords) > 0: 237 self.data["IKEY"] = ";".join(keywords) 238 f = open(self.CommentFile, "w") 239 for i in self.data: 240 f.write((u"%s %s\n" % (i, self.data[i])).encode(fileEncoding)) 241 f.close()
242
243 - def Rencode(self):
244 """re-encode the video to the given quality""" 245 if self.Rotate: 246 if self.Rotate == u"Rotated 90 clock-wise": 247 rotate = " -vf rotate=1 " 248 elif self.Rotate == u"Rotated 90 counter clock-wise": 249 rotate = " -vf rotate=2 " 250 else: 251 rotate = " " 252 DoAudio = (self.AudioCodec.lower().find("pcm") >= 0) 253 #print "Audio spec= " + self.AudioCodec 254 DoVideo = (not (self.VideoCodec.lower().find("h264") >= 0 or self.VideoCodec.lower().find("avc1") >= 0)) or self.Video.lower().endswith(".mov") 255 print "DoAudio=%s\tDoVideo=%s" % (DoAudio, DoVideo) 256 if DoAudio: 257 __, rawaudio = tempfile.mkstemp(suffix=".raw") 258 os.system(mplayer + " %s -dumpaudio -dumpfile %s " % (self.FullPath, rawaudio)) 259 __, wavaudio = tempfile.mkstemp(suffix=".wav") 260 print "AudioSampleRate= %s" % self.AudioSampleRate 261 if self.AudioSampleRate == 44100: 262 os.system(sox + " -r %s -c %s -u -b -t raw %s -r 44100 %s " % (self.AudioSampleRate, self.AudioChannel, rawaudio, wavaudio)) 263 else: 264 os.system(sox + " -r %s -c %s -u -b -t raw %s -r 44100 %s resample " % (self.AudioSampleRate, self.AudioChannel, rawaudio, wavaudio)) 265 # os.remove(rawaudio) 266 __, tmpavi = tempfile.mkstemp(suffix=".avi") 267 if False: 268 #if DoVideo: 269 os.system(mencoder + rotate + " -nosound -ovc x264 -x264encopts bitrate=%s:pass=1:turbo=1:%s -o %s %s" % (VBitrate, x264opts, tmpavi, self.FullPath)) 270 os.remove(tmpavi) 271 os.system(mencoder + rotate + " -nosound -ovc x264 -x264encopts bitrate=%s:pass=3:%s -o %s %s" % (VBitrate, x264opts, tmpavi, self.FullPath)) 272 os.remove(tmpavi) 273 if DoAudio: 274 os.system(mencoder + rotate + "-oac mp3lame -lameopts mode=3:vbr=3:br=%s -audiofile %s -ovc x264 -x264encopts bitrate=%s:pass=3:%s -o %s %s " % (ABitRate, wavaudio, VBitrate, x264opts, tmpavi, self.FullPath)) 275 # os.remove(wavaudio) 276 else: 277 os.system(mencoder + rotate + "-oac copy -ovc x264 -x264encopts bitrate=%s:pass=3:%s -o %s %s" % (VBitrate, x264opts, tmpavi, self.FullPath)) 278 if os.path.isfile("divx2pass.log"):os.remove("divx2pass.log") 279 if os.path.isfile("divx2pass.log.temp"):os.remove("divx2pass.log.temp") 280 else: 281 shutil.copy(self.FullPath, tmpavi) 282 print "%s -o %s -i %s -f %s" % (avimerge, self.DestFile, tmpavi, self.CommentFile) 283 os.system("%s -o %s -i %s -f %s" % (avimerge, self.DestFile, tmpavi, self.CommentFile))
284 # os.remove(tmpavi) 285
286 - def PBSRencode(self):
287 """re-encode the video to the given quality, using the PBS queuing system""" 288 pbsFilename = os.path.splitext(self.FullPath.replace(" ", "_"))[0] + ".pbs" 289 pbsfile = open(pbsFilename, "w") 290 pbsfile.write("#!/bin/bash\nif [ -d /tmp/$PBS_JOBID ] ; then cd /tmp/$PBS_JOBID ;else cd /tmp; fi\n") 291 if self.Rotate: 292 if self.Rotate == u"Rotated 90 clock-wise": 293 rotate = " -vf rotate=1 " 294 elif self.Rotate == u"Rotated 90 counter clock-wise": 295 rotate = " -vf rotate=2 " 296 else: 297 rotate = " " 298 Resize = False 299 DoAudio = (self.AudioCodec.lower().find("pcm") >= 0) 300 # DoResize = (self.Width == 1280) and (self.Height == 720) 301 DoResize = (self.Width > 640) 302 DoAudio = DoAudio or DoResize 303 DoVideo = DoResize or not (self.Video.lower().endswith(".avi")) 304 DoVideo = DoVideo or not (self.VideoCodec.lower().find("h264") >= 0 or self.VideoCodec.lower().find("avc1") >= 0) 305 if DoAudio: 306 newSampleRate = 44100 307 wavaudio = "audio-%s.wav" % newSampleRate 308 if (self.AudioSampleRate == 11024) and (self.AudioChannel == 1): #specific Ixus 309 rawaudio = "audio-%s.raw" % self.AudioSampleRate 310 pbsfile.write(mplayer + ' "%s" -dumpaudio -dumpfile %s \n' % (self.FullPath, rawaudio)) 311 pbsfile.write(sox + " -r %s -c %s -u -b -t raw %s -r 44100 %s resample \n" % (self.AudioSampleRate, self.AudioChannel, rawaudio, wavaudio)) 312 pbsfile.write("rm %s \n" % rawaudio) 313 else: 314 rawaudio = "audio-%s.wav" % self.AudioSampleRate 315 pbsfile.write(mplayer + ' -ao pcm:fast:file=%s -vo null "%s" \n' % (rawaudio, self.FullPath)) 316 if self.AudioSampleRate == 44100: 317 wavaudio = rawaudio 318 else: 319 pbsfile.write(sox + " %s -r %s %s resample \n" % (rawaudio, newSampleRate, wavaudio)) 320 pbsfile.write("rm %s \n" % rawaudio) 321 322 tmpavi = "temporary.avi" 323 if DoResize: 324 #Resize = " -vf scale=736:416 " 325 Resize = " -vf scale=640:%i " % (self.Height * 640 / self.Width) 326 #Resize = " " 327 else: 328 Resize = " " 329 if DoVideo: 330 pbsfile.write(mencoder + rotate + Resize + ' -nosound -ovc x264 -x264encopts bitrate=%s:pass=1:turbo=1:%s -o %s "%s" \n' % (VBitrate, x264opts, tmpavi, self.FullPath)) 331 pbsfile.write("rm %s \n" % tmpavi) 332 pbsfile.write(mencoder + rotate + Resize + ' -nosound -ovc x264 -x264encopts bitrate=%s:pass=3:%s -o %s "%s" \n' % (VBitrate, x264opts, tmpavi, self.FullPath)) 333 pbsfile.write("rm %s \n" % tmpavi) 334 if DoAudio: 335 pbsfile.write(mencoder + rotate + Resize + ' -oac mp3lame -lameopts mode=3:vbr=3:br=%s -audiofile %s -ovc x264 -x264encopts bitrate=%s:pass=3:%s -o %s "%s" \n' % (ABitRate, wavaudio, VBitrate, x264opts, tmpavi, self.FullPath)) 336 pbsfile.write("rm %s \n" % wavaudio) 337 else: 338 pbsfile.write(mencoder + rotate + Resize + '-oac copy -ovc x264 -x264encopts bitrate=%s:pass=3:%s -o %s "%s" \n' % (VBitrate, x264opts, tmpavi, self.FullPath)) 339 pbsfile.write("if [ -f divx2pass.log ]; then rm divx2pass.log ; fi\n") 340 pbsfile.write("if [ -f divx2pass.log.temp ]; then rm divx2pass.log.temp ; fi\n") 341 else: 342 pbsfile.write("cp %s %s\n" % (self.FullPath, tmpavi)) 343 # shutil.copy(self.FullPath, tmpavi) 344 pbsfile.write('%s -o %s -i %s -f "%s" \n' % (avimerge, self.DestFile, tmpavi, self.CommentFile)) 345 pbsfile.write("rm %s \n" % tmpavi) 346 pbsfile.close() 347 os.system('qsub "%s"' % pbsFilename)
348
349 - def GenThumb(self, size=160):
350 """Generate a thumbnail for the image""" 351 Thumbdir = tempfile.mkdtemp() 352 os.system("%s %s -vo jpeg:outdir=%s -ao null -frames 1 " % (mplayer, self.FullPath, Thumbdir)) 353 self.ThumbName = OP.splitext(self.FullPath)[0] + "--Thumb.jpg" 354 os.system("%s -geometry %ix%i %s/*.jpg %s" % (convert, size, size, Thumbdir, self.ThumbName)) 355 for i in os.listdir(Thumbdir):os.remove(OP.join(Thumbdir, i)) 356 os.rmdir(Thumbdir)
357 358 359 360 361 362 363
364 -def FindFile(RootDir):
365 """returns a list of the files with the given suffix in the given dir 366 files=os.system('find "%s" -iname "*.%s"'%(RootDir,suffix)).readlines() 367 """ 368 files = [] 369 for i in VideoExts: 370 files += parser().FindExts(RootDir, i) 371 good = [] 372 l = len(RootDir) + 1 373 for i in files: good.append(i.strip()[l:]) 374 good.sort() 375 return good
376
377 -class parser:
378 """this class searches all the jpeg files"""
379 - def __init__(self):
380 self.imagelist = []
381
382 - def OneDir(self, curent):
383 """ append all the imagesfiles to the list, then goes recursively to the subdirectories""" 384 ls = os.listdir(curent) 385 for i in ls: 386 a = os.path.join(curent, i) 387 if os.path.isdir(a): 388 self.OneDir(a) 389 if os.path.isfile(a): 390 if i.lower().endswith(self.suffix): 391 self.imagelist.append(os.path.join(curent, i))
392 - def FindExts(self, root, suffix):
393 self.root = root 394 self.suffix = suffix 395 self.OneDir(self.root) 396 return self.imagelist
397
398 -class HTML:
399 - def __init__(self, title="Test", enc="latin1", favicon=None):
400 self.txt = u"" 401 self.enc = enc 402 self.header(title, enc, favicon)
403 - def header(self, title, enc, favicon):
404 self.txt += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n<html>\n<head>\n' 405 if favicon: 406 self.txt += '<link rel="icon" type="image/%s" href="%s" />\n' % (OP.splitext(favicon)[1][1:], favicon) 407 if enc:self.txt += '<content="text/html; charset=%s">\n' % enc 408 self.txt += "<title>%s</title>\n" % title 409 self.txt += "</head>\n"
410 - def footer(self):
411 self.txt += "</html>\n"
412 - def write(self, filename):
413 self.footer() 414 f = open(filename, "w") 415 f.write(self.txt.encode(self.enc)) 416 f.close()
417 - def start(self, tag, dico={}):
418 self.txt += "<%s" % tag 419 for i in dico: 420 self.txt += ' %s="%s" ' % (i, dico[i]) 421 self.txt += " >\n"
422 - def stop(self, tag):
423 self.txt += "</%s>\n" % tag
424 - def data(self, donnee, cod=""):
425 if cod: 426 d = donnee.decode(cod) 427 else: 428 d = donnee 429 self.txt += d.replace(u"&", u"&amp;").replace(u"<", u"&lt;").replace(u">", u"&gt;").replace(u'\xb0', u"&deg;").replace(u"\xb9", u"&sup1;").replace(u"\xb2", u"&sup2;").replace(u"\xb3", u"&sup3;").replace(u"\xb5", u"&micro;")
430 # s = replace(s, "", "&Aring;") 431 # s = replace(s, "", "&szlig;")
432 - def element(self, tag, data="", cod=""):
433 self.start(tag) 434 self.data(data, cod) 435 self.stop(tag)
436
437 -def RelativeName(Name):
438 cur = [] 439 a = RootDir 440 while len(a) > 1: 441 a, b = os.path.split(a) 442 cur.append(b) 443 cur.reverse() 444 fil = [] 445 a = Name 446 while len(a) > 1: 447 a, b = os.path.split(a) 448 fil.append(b) 449 fil.reverse() 450 newfil = [] 451 for i in range(len(fil)): 452 # print i,newfil 453 if len(cur) < i + 1:newfil.append(fil[i]) 454 elif fil[i] == cur[i]:continue 455 return OP.join(*tuple(newfil))
456 457 458 459 460 461 ################################################################################################ 462 ############ Main program Start ################################################################ 463 ################################################################################################ 464 if __name__ == "__main__": 465 if len(sys.argv) > 1: 466 if OP.isdir(sys.argv[1]): 467 RootDir = sys.argv[1] 468 if sys.argv[0].lower().find("nommevideo") >= 0: 469 Action = "Rename" 470 elif sys.argv[0].lower().find("genhtml") >= 0: 471 Action = "GenHTML" 472 else: #sys.argv[0].lower().find("genhtml") >= 0: 473 Action = "DEBUG" 474 UpperDir = OP.split(RootDir)[0] 475 if Action == "Rename": 476 for filename in FindFile(RootDir): 477 #for filename in os.listdir("."): 478 # if OP.splitext(filename)[1].lower() in VideoExts: 479 vi = Video(filename) 480 vi.FindThumb() 481 vi.MkDir() 482 if not OP.isfile(vi.DestFile): 483 vi.PlayVideo() 484 print vi 485 vi.SetTitle() 486 vi.PBSRencode() 487 elif Action == "GenHTML": 488 videos = {} 489 for filename in FindFile(RootDir): 490 vi = Video(filename) 491 if not videos.has_key(vi.DateTime.date().isoformat()): 492 videos[vi.DateTime.date().isoformat()] = [vi] 493 else: 494 videos[vi.DateTime.date().isoformat()].append(vi) 495 date = videos.keys() 496 date.sort() 497 print date 498 html = HTML("Videos", enc=webEncoding) 499 html.start("body") 500 html.element("a name='begin'") 501 502 for i in date: 503 html.element("b", videos[i][0].DateTime.date().strftime("%A, %d %B %Y").capitalize().decode(local)) 504 html.start("table", {"cellspacing":10}) 505 for j in videos[i]: 506 j.GenThumb() 507 html.start("tr") 508 html.start("td", {"width":200}) 509 print RelativeName(j.FullPath) 510 html.start("a", {"href":RelativeName(j.FullPath)}) 511 thumb = RelativeName(j.ThumbName) 512 html.start("img", {"src":thumb, "alt":thumb}) 513 html.stop("img") 514 html.stop("a") 515 html.stop("td") 516 html.start("td") 517 html.data(j.DateTime.time().strftime("%Hh%Mm%Ss").decode(local)) 518 html.start("br") 519 # print j.Duration 520 html.data(u"Dur\xe9e %is" % j.Duration.seconds) 521 html.stop("td") 522 html.element("td", j.title) 523 html.stop("tr") 524 html.stop("table") 525 html.start("hr/") 526 html.element("a name='end'") 527 html.stop("body") 528 html.write("index.html") 529 for j in videos[i]: 530 print j.DateTime 531 532 else: 533 videos = {} 534 for filename in FindFile(RootDir): 535 vi = Video(filename) 536 if not videos.has_key(vi.DateTime.date().isoformat()): 537 videos[vi.DateTime.date().isoformat()] = [vi] 538 else: 539 videos[vi.DateTime.date().isoformat()].append(vi) 540 date = videos.keys() 541 date.sort() 542 print date 543 for i in date: 544 for j in videos[i]: 545 try: 546 print j 547 except: 548 print "error" 549 sys.stdout.write(j.__repr__()) 550 print "#" * 50 551