pyTivo
[pyTivo.git] / transcode.py
blob9e39087ae078d18bef2c05484f8c5ac4103af4bf
1 import subprocess, shutil, os, re
3 def output_video(inFile, outFile):
4 if tivo_compatable(inFile):
5 f = file(inFile, 'rb')
6 shutil.copyfileobj(f, outFile)
7 f.close()
8 else:
9 transcode(inFile, outFile)
11 def transcode(inFile, outFile):
13 cmd = "ffmpeg_mp2.exe -i \"%s\" -vcodec mpeg2video -r 29.97 -b 4096 %s -ac 2 -ab 192 -f vob -" % (inFile, select_aspect(inFile))
14 ffmpeg = subprocess.Popen(cmd, stdout=subprocess.PIPE)
15 try:
16 shutil.copyfileobj(ffmpeg.stdout, outFile)
17 except:
18 win32kill(ffmpeg.pid)
20 def select_aspect(inFile):
21 type, height, width, fps = video_info(inFile)
23 d = gcd(height,width)
25 rheight, rwidth = height/d, width/d
27 if (rheight, rwidth) in [(4, 3), (10, 11), (15, 11), (59, 54), (59, 72), (59, 36), (59, 54)]:
28 return '-aspect 4:3 -s 720x480'
29 elif (rheight, rwidth) in [(16, 9), (20, 11), (40, 33), (118, 81), (59, 27)]:
30 return '-aspect 16:9 -s 720x480'
31 else:
32 settings = []
33 settings.append('-aspect 16:9')
35 endHeight = (720*width)/height
36 if endHeight % 2:
37 endHeight -= 1
39 settings.append('-s 720x' + str(endHeight))
41 topPadding = ((480 - endHeight)/2)
42 if topPadding % 2:
43 topPadding -= 1
45 settings.append('-padtop ' + str(topPadding))
46 bottomPadding = (480 - endHeight) - topPadding
47 settings.append('-padbottom ' + str(bottomPadding))
49 return ' '.join(settings)
51 def tivo_compatable(inFile):
52 suportedModes = [[720, 480], [704, 480], [544, 480], [480, 480], [352, 480]]
53 type, height, width, fps = video_info(inFile)
55 if not type == 'mpeg2video':
56 return False
58 if not fps == '29.97':
59 return False
61 for mode in suportedModes:
62 if (mode[0], mode[1]) == (height, width):
63 return True
64 return False
66 def video_info(inFile):
67 cmd = "ffmpeg_mp2.exe -i \"%s\"" % inFile
68 print cmd
69 ffmpeg = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
70 output = ffmpeg.stderr.read()
71 print ffmpeg.stdout.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