pyTivo
[pyTivo/krkeegan.git] / transcode.py
blobebf7cbeb7a250592788540bf418232ea5113ea3a
1 import subprocess, shutil, os, re
3 SCRIPTDIR = os.path.dirname(__file__)
5 def output_video(inFile, outFile):
6 if tivo_compatable(inFile):
7 f = file(inFile, 'rb')
8 shutil.copyfileobj(f, outFile)
9 f.close()
10 else:
11 transcode(inFile, outFile)
13 def transcode(inFile, outFile):
15 cmd = SCRIPTDIR + "\\ffmpeg_mp2.exe -i \"%s\" -vcodec mpeg2video -r 29.97 -b 4096 %s -ac 2 -ab 192 -f vob -" % (inFile, select_aspect(inFile))
16 ffmpeg = subprocess.Popen(cmd, stdout=subprocess.PIPE)
17 try:
18 shutil.copyfileobj(ffmpeg.stdout, outFile)
19 except:
20 win32kill(ffmpeg.pid)
22 def select_aspect(inFile):
23 type, height, width, fps = video_info(inFile)
25 d = gcd(height,width)
27 rheight, rwidth = height/d, width/d
29 if (rheight, rwidth) in [(4, 3), (10, 11), (15, 11), (59, 54), (59, 72), (59, 36), (59, 54)]:
30 return '-aspect 4:3 -s 720x480'
31 elif (rheight, rwidth) in [(16, 9), (20, 11), (40, 33), (118, 81), (59, 27)]:
32 return '-aspect 16:9 -s 720x480'
33 else:
34 settings = []
35 settings.append('-aspect 16:9')
37 endHeight = (720*width)/height
38 if endHeight % 2:
39 endHeight -= 1
41 settings.append('-s 720x' + str(endHeight))
43 topPadding = ((480 - endHeight)/2)
44 if topPadding % 2:
45 topPadding -= 1
47 settings.append('-padtop ' + str(topPadding))
48 bottomPadding = (480 - endHeight) - topPadding
49 settings.append('-padbottom ' + str(bottomPadding))
51 return ' '.join(settings)
53 def tivo_compatable(inFile):
54 suportedModes = [[720, 480], [704, 480], [544, 480], [480, 480], [352, 480]]
55 type, height, width, fps = video_info(inFile)
57 if not type == 'mpeg2video':
58 return False
60 if not fps == '29.97':
61 return False
63 for mode in suportedModes:
64 if (mode[0], mode[1]) == (height, width):
65 return True
66 return False
68 def video_info(inFile):
69 cmd = SCRIPTDIR + "\\ffmpeg_mp2.exe -i \"%s\"" % inFile
70 ffmpeg = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
71 output = ffmpeg.stderr.read()
73 rezre = re.compile(r'.*Video: (.+), (\d+)x(\d+), (.+) fps.*')
74 m = rezre.search(output)
75 if m:
76 return m.group(1), int(m.group(2)), int(m.group(3)), m.group(4)
77 else:
78 return None, None, None, None
80 def suported_format(inFile):
81 if video_info(inFile)[0]:
82 return True
83 else:
84 return False
86 def win32kill(pid):
87 import ctypes
88 handle = ctypes.windll.kernel32.OpenProcess(1, False, pid)
89 ctypes.windll.kernel32.TerminateProcess(handle, -1)
90 ctypes.windll.kernel32.CloseHandle(handle)
92 def gcd(a,b):
93 while b:
94 a, b = b, a % b
95 return a