OSDN Git Service

tunerec: include <unistd.h> for usleep
[rec10/rec10-git.git] / rec10 / tv2mp4.py
1 #!/usr/bin/python
2 # coding: UTF-8
3 # Rec10 TS Recording Tools
4 # Copyright (C) 2009-2011 Yukikaze
5 import commands
6 import shutil
7 import auto_process
8 import os
9 import re
10 import os.path
11 import string
12 import base64
13 import time
14 import subprocess
15 import traceback
16 import zip
17
18 import tv2avi
19 import recdblist
20 import configreader
21 import status
22 import tv2audio
23 path = str(os.path.dirname(os.path.abspath(__file__))) + "/"
24 tmppath = configreader.getConfPath("tmp")+"/"
25 if tmppath=="/":
26     tmppath=path
27 if not os.path.exists(tmppath):
28     os.mkdir(tmppath)
29 def ts2mp4(pin, pout, opt):
30     dir=os.path.split(pout)[0]
31     title=os.path.split(pout)[1]
32     title=os.path.splitext(title)[0]
33     tpraw=os.path.join(dir, title+".264")
34     tpmp4=os.path.join(dir, title+".mp4")
35     if os.path.isfile(pin) and os.path.getsize(pin)>10*1000:
36         tv2avi.ts2raw(pin, tpraw, opt)
37         time.sleep(10)
38         if os.path.isfile(tpraw) and os.path.getsize(tpraw)>10*1000:
39             raw2mp4(tpraw, tpmp4, opt)
40         time.sleep(10)
41         if os.path.exists(tpraw) and not re.search("B",opt):
42             os.remove(tpraw)
43     zip.addFile2FileZip(recdblist.getLogTitle(pin)+".command.log", recdblist.getLogTitle(pin)+".log.zip")
44     if os.path.exists(recdblist.getLogTitle(pin)+".command.log"):
45         os.remove(recdblist.getLogTitle(pin)+".command.log")
46 def raw2mp4(pin,pout,opt):
47     dir=os.path.split(pout)[0]
48     title=os.path.split(pout)[1]
49     title=os.path.splitext(title)[0]
50     duration="-fps 29.970030 "
51     if re.search("a",opt):
52         duration="-fps 23.976023 "
53     if re.search("I",opt):
54         duration="-fps 29.970030 "
55     exe = configreader.getConfPath("mp4box")+u" -tmp "+tmppath
56     txt=""
57     os.environ['LANG']="ja_JP.UTF-8"
58     pints=pin.replace(".264",".ts")
59     e1=exe +u" "+duration+" -add \""+pin+"\" -new \""+pout+"\""
60     execmp4box(pin, pout, e1)
61     addAudio(pints, pout, opt)
62     addCaption(pints, pout)
63     if status.getSettings_auto_del_tmp()==1:
64         if os.path.exists(pout):
65             if re.search("t",opt):
66                 auto_process.deleteTmpFile(dir, title, ".264")
67             elif re.search("k",opt):
68                 ""#削除しない
69             else:
70                 auto_process.deleteTmpFile(dir, title, ".mp4")
71 def mkv2mp4(pin,pout):
72     exeb = configreader.getConfPath(u"mkvextract")
73     exe = configreader.getConfPath(u"mp4Box")
74     #dtsedit=configreader.getConfPath("DtsEdit")
75     wineexe=configreader.getConfPath("wine")
76     dir=os.path.split(pin)[0]
77     title=os.path.split(pin)[1]
78     title=os.path.splitext(title)[0]
79     etitle=base64.b16encode(title.encode('utf-8'))
80     audiopath=os.path.join(dir,etitle+u"_audio.aac")
81     videopath=os.path.join(dir,etitle+u"_video.264")
82     timecodepath=os.path.join(dir,etitle+u"_1_timecode.txt")
83     tmpmp4=os.path.join(dir,etitle+u".tmp.mp4")
84     exe0=exeb+u" tracks \'"+pin+u"\' 1:\'"+videopath+u"\' 2:\'"+audiopath+u"\'"
85     exe1=exeb+u" timecodes_v2 \'"+pin+"\' 1:\'"+timecodepath+"\'"
86     exe2=exe+u" -fps 29.970030 -add \'"+videopath+u"\' -add \'"+audiopath+u"\' -new \'"+tmpmp4+u"\'"
87     exe3=wineexe+u" "+dtsedit+u" -tc \'Z:\\"+timecodepath+u"\' \'Z:\\"+tmpmp4+u"\' -o \'Z:\\"+pout+u"\'"
88     os.environ['LANG']="ja_JP.UTF-8"
89     txt=""
90     try:
91         txt=txt+execcomd(exe0)+"\n"
92         txt=txt+execcomd(exe1)+"\n"
93         txt=txt+execcomd(exe2)+"\n"
94         txt=txt+execcomd(exe3)+"\n"
95     except:
96         ""
97     recdblist.addLog(pin, txt, u"MKV2MP4-log")
98     txt = "\n####MKV2MP4-log####\n"+txt
99     time.sleep(10)
100     if status.getSettings_auto_del_tmp()==1:
101         if os.path.exists(pout):
102             auto_process.deleteTmpFile(dir, title, ".mp4")
103 def addCaption(pts,pmp4):##字幕の追加を試みる。
104     wineexe=configreader.getConfPath("wine")
105     pincap=pts.replace(".ts",".srt")
106     try:
107         cap2ass=configreader.getConfPath("caption2ass")
108     except:
109         cap2ass=""
110     if os.path.isfile(cap2ass):
111         e0=wineexe+u" "+cap2ass+u" -format srt \"Z:\\"+pts+"\" \"Z:\\"+pincap+"\""
112         recdblist.printutf8(e0)
113         p0=subprocess.Popen(e0,shell=True,stdout=subprocess.PIPE)
114         time.sleep(100)
115         if p0.poll==None:#実行中
116             #if os.path.getsize(pincap)<1000:#2mで1kb以下の場合自動で終了
117              #   os.kill(p0.pid,signal.SIGKILL)
118             #else:
119             os.waitpid(p0.pid, 0)
120             logt=unicode(p0.communicate()[0], "UTF-8")
121             recdblist.addLog(pts,e0, u"Captionログ-コマンド")
122             recdblist.addLog(pts,logt, u"Captionログ-詳細")
123             recdblist.addCommandLogZip(pts, "mp4box_caption", "mp4box_caption", e0, logt)
124         if os.path.exists(pincap):
125             if os.path.getsize(pincap)>1000:
126                 exe = configreader.getConfPath("mp4box")+u" -tmp "+tmppath
127                 e1s=exe +u" -add \""+pincap+"\" \""+pmp4+"\""
128                 addmp4(pincap,pmp4,e1s)
129 def addAudio(pts,pmp4,opts):#オプションに応じた音声の追加を行う
130     exe = configreader.getConfPath("mp4box")+u" -tmp "+tmppath
131     if re.search("d",opts) or re.search("5",opts):#二カ国語放送/5.1ch放送の場合
132         paac1=pts.replace(".ts","_1.aac")
133         paac2=pts.replace(".ts","_2.aac")
134         recdblist.printutf8(paac1)
135         e1a1=exe +u" -add \""+paac1+"\":mpeg4 \""+pmp4+"\""
136         e1a2=exe +u" -add \""+paac2+"\":mpeg4 \""+pmp4+"\""
137         if not os.path.exists(paac1):
138             paac1=pts.replace(".ts","_1.mp3")
139             e1a1=exe +u" -add \""+paac1+"\" \""+pmp4+"\""
140         if not os.path.exists(paac2):
141             paac2=pts.replace(".ts","_2.mp3")
142             e1a1=exe +u" -add \""+paac2+"\" \""+pmp4+"\""
143         if os.path.exists(paac1):
144             addmp4(paac1, pmp4, e1a1)
145         if os.path.exists(paac2):
146             addmp4(paac2, pmp4, e1a2)
147     elif re.search("b",opts):#BonTsDemuxを使って音声をスプリットした場合
148         paac=pts.replace(".ts",".aac")
149         e1a=exe +u" -add \""+pinaac+"\":mpeg4 \""+pmp4+"\""
150         if not os.path.exists(paac):
151             paac=pts.replace(".ts",".mp3")
152             e1a1=exe +u" -add \""+paac+"\" \""+pmp4+"\""
153         if os.path.exists(paac):
154             addmp4(paac, pmp4, e1a1)
155     else:
156         tv2audio.ts2single_audio(pts,opts)
157         pinaac=pts.replace(".ts",".aac")
158         e1a=exe +u" -add \""+pinaac+"\":mpeg4 \""+pmp4+"\""
159         if not os.path.exists(pinaac):
160             pinaac=pinaac.replace(".aac",".mp3")
161             e1a=exe +u" -add \""+pinaac+"\" \""+pmp4+"\""
162         if os.path.exists(pinaac):
163             addmp4(pinaac, pmp4, e1a)
164 def execmp4box(pin,pout,cmd):
165     title=os.path.splitext(os.path.split(pin)[1])[0]
166     nt=base64.b16encode(title.encode('utf-8'))
167     if len(nt)>200:
168         nt=nt[:180]
169     ptin=os.path.join(os.path.dirname(pin),nt+".264")
170     recdblist.printutf8(ptin)
171     shutil.move(pin,ptin)
172     time.sleep(10)
173     ptout=os.path.join(os.path.dirname(pout),nt+".mp4")
174     cmdn=string.replace(cmd,pin,ptin)
175     cmdn=string.replace(cmdn,pout,ptout)
176     recdblist.printutf8(cmdn)
177     recdblist.addCommandSelfLog(pin, cmdn)
178     txt=""
179     try:
180         txt=execcomd(cmdn)
181     except Exception, inst:
182         txt= "error occures in execmp4box\n"
183         txt=txt+ str(type(inst))+"\n"
184         txt=txt+str(inst)
185         recdblist.addCommonlogEX("Error", "excecmp4box(tv2mp4.py)", str(type(inst)), str(inst)+traceback.format_exc(),verbose_level=200,log_level=200)
186     recdblist.addLog(pin, cmdn, u"MP4Boxログ-コマンド")
187     recdblist.addLog(pin, txt, u"MP4Boxログ-詳細")
188     recdblist.addCommandLogZip(pin, "MP4Box", "mp4box", cmdn,txt)
189     time.sleep(5)
190     shutil.move(ptin,pin)
191     shutil.move(ptout,pout)
192     time.sleep(5)
193 def addmp4(padd,pout,cmd):#without video
194     title=os.path.splitext(os.path.split(padd)[1])[0]
195     ext=os.path.splitext(os.path.split(padd)[1])[1]
196     nt=base64.b16encode(title.encode('utf-8'))
197     if len(nt)>200:
198         nt=nt[:180]
199     ptadd=os.path.join(os.path.dirname(padd),nt+ext)
200     ptoutb=os.path.join(os.path.dirname(pout),nt+"_b.mp4")
201     ptout=os.path.join(os.path.dirname(pout),nt+".mp4")
202     shutil.move(padd,ptadd)
203     if os.path.isfile(pout):
204         shutil.move(pout,ptoutb)
205     time.sleep(5)
206     cmdn=string.replace(cmd,padd,ptadd)
207     cmdn=string.replace(cmdn,u"-out \""+pout,u"-add \""+ptoutb+"\" -new \""+ptout)
208     cmdn=string.replace(cmdn,u"\""+pout,u"-add \""+ptoutb+"\" -new \""+ptout)
209     cmdn=string.replace(cmdn,pout,ptout)
210     recdblist.printutf8(cmdn)
211     txt=""
212     try:
213         txt=execcomd(cmdn)
214     except Exception, inst:
215         txt= "error occures in addmp4\n"
216         txt=txt+ str(type(inst))+"\n"
217         txt=txt+str(inst)
218     recdblist.addLog(pout, cmdn, u"MP4Box追加ログ-コマンド")
219     recdblist.addLog(pout, txt, u"MP4Box追加ログ-詳細")
220     recdblist.addCommandLogZip(pout, "MP4Box_add", "mp4box_add", cmdn, txt)
221     time.sleep(5)
222     shutil.move(ptadd,padd)
223     if os.path.exists(ptout):
224         shutil.move(ptout,pout)
225         os.remove(ptoutb)
226     else:
227         txtt=padd+u"のインポートエラー"
228         recdblist.addLog(pout, txtt, u"MP4Box追加ログ-コマンド")
229         shutil.move(ptoutb,pout)
230     time.sleep(5)
231 def execcomd(cmd):
232     txt=""
233     try:
234         txt=u"Cmd : "+cmd+"\n"
235         txt2=commands.getoutput(cmd.encode('utf-8'))
236         txt=txt+unicode(txt2,"utf-8")+"\n"
237     except:
238         ""
239     return txt