forked from unanimated/luaegisub
-
Notifications
You must be signed in to change notification settings - Fork 24
/
ua.EncodeHardsub.lua
367 lines (321 loc) · 13.5 KB
/
ua.EncodeHardsub.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
--[[ Script for encoding / hardsubbing
Options:
- encode whole video / a clip
- hardsub 1 or 2 subtitle files or only encode
- use vsfilter or vsfiltermod for each subtitle track
- encode to mp4 or mkv
- mux with audio
Requirements:
- x264.exe
- vsfilter.dll / vsfiltermod.dll for hardsubbing
- avisynth (not required when encoding for mocha)
'Encode clip for mocha' does automatically the following (meaning you don't have to do those manually):
- disables 10bit
- enables trimming
- disables subtitles
- sets target to .mp4
- disables avisynth use
--]]
script_name="Encode - Hardsub"
script_description="Encode a clip with or without hardsubs"
script_author="unanimated"
script_version="1.2"
script_namespace="ua.EncodeHardsub"
local haveDepCtrl,DependencyControl,depRec=pcall(require,"l0.DependencyControl")
if haveDepCtrl then
script_version="1.2.0"
depRec=DependencyControl{feed="https://raw.githubusercontent.com/TypesettingTools/unanimated-Aegisub-Scripts/master/DependencyControl.json"}
end
function encode(subs,sel)
ADD=aegisub.dialog.display
ADP=aegisub.decode_path
ADO=aegisub.dialog.open
ak=aegisub.cancel
enconfig=ADP("?user").."\\encode_hardsub.conf"
defsett="--crf 18 --ref 10 --bframes 10 --merange 32 --me umh --subme 10 --trellis 2 --direct auto --b-adapt 2 --partitions all"
defmsett="--profile baseline --level 1.0 --crf 16 --fps 24000/1001"
scriptpath=ADP("?script").."\\"
scriptname=aegisub.file_name()
vpath=ADP("?video").."\\"
ms2fr=aegisub.frame_from_ms
fr2ms=aegisub.ms_from_frame
sframe=999999
eframe=0
videoname=nil
file=io.open(enconfig)
if file~=nil then
konf=file:read("*all")
io.close(file)
xpath=konf:match("xpath:(.-)\n")
xpath10=konf:match("xpath10:(.-)\n")
sett=konf:match("settings:(.-)\n")
vsfpath=konf:match("vsfpath:(.-)\n")
vsfmpath=konf:match("vsfmpath:(.-)\n")
mmgpath=konf:match("mmgpath:(.-)\n") or ""
vtype=konf:match("vtype:(.-)\n")
vsf1=konf:match("filter1:(.-)\n")
vsf2=konf:match("filter2:(.-)\n")
targ=konf:match("targ:(.-)\n")
target=konf:match("target:(.-)\n")
msett=konf:match("mocha:(.-)\n")
settlist=konf:match("(settings1:.*\n)$") or ""
else
xpath=""
xpath10=""
vsfpath=""
vsfmpath=""
mmgpath=""
vtype=".mkv"
vsf1="vsfilter"
vsf2="vsfilter"
sett=defsett
msett=defmsett
settlist=""
targ="Same as source"
target=""
end
for i=1,#subs do
if subs[i].class=="info" then
if subs[i].key=="Video File" then videoname=subs[i].value break end
end
if subs[i].class~="info" then break end
end
if videoname==nil then videoname=aegisub.project_properties().video_file:gsub("^.*\\","") end
if videoname==nil or videoname=="" or aegisub.frame_from_ms(10)==nil then t_error("No video detected.",1) end
vid2=videoname:gsub("%.[^%.]+","") :gsub("_?premux","") :gsub("_?workraw","")
vid2=vid2.."_hardsub"
for z,i in ipairs(sel) do
line=subs[i]
start=line.start_time
endt=line.end_time
sfr=ms2fr(start)
efr=ms2fr(endt)
if sfr<sframe then sframe=sfr end
if efr>eframe then eframe=efr end
end
GUI={
{x=0,y=0,class="label",label="x264.exe 8-bit:"},
{x=1,y=0,width=6,class="edit",name="xpath",value=xpath or ""},
{x=7,y=0,class="label",label=" x264 10-bit:"},
{x=8,y=0,width=2,class="edit",name="xpath10",value=xpath10 or ""},
{x=0,y=1,class="label",label="vsfilter.dll:"},
{x=1,y=1,width=6,class="edit",name="vsf",value=vsfpath or ""},
{x=7,y=1,class="label",label=" vsfiltermod.dll:"},
{x=8,y=1,width=2,class="edit",name="vsfm",value=vsfmpath or "",hint="only needed if you're using it"},
{x=0,y=2,class="label",label="Source video:"},
{x=1,y=2,width=6,class="edit",name="vid",value=videoname},
{x=7,y=2,class="label",label=" mkvmerge.exe:"},
{x=8,y=2,width=2,class="edit",name="mmg",value=mmgpath or "",hint="only needed if you're muxing audio"},
{x=0,y=3,class="label",label="Target folder:"},
{x=1,y=3,width=2,class="dropdown",name="targ",value=targ,items={"Same as source","Custom:"}},
{x=3,y=3,width=7,class="edit",name="target",value=target},
{x=0,y=4,class="label",label="Encode name:"},
{x=1,y=4,width=2,class="dropdown",name="vtype",value=vtype,items={".mkv",".mp4"}},
{x=3,y=4,width=7,class="edit",name="vid2",value=vid2},
{x=0,y=5,class="label",label="Primary subs:"},
{x=1,y=5,width=2,class="dropdown",name="filter1",value=vsf1,items={"none","vsfilter","vsfiltermod"}},
{x=3,y=5,width=7,class="edit",name="first",value=scriptpath..scriptname},
{x=0,y=6,class="checkbox",name="sec",label="Secondary:"},
{x=1,y=6,width=2,class="dropdown",name="filter2",value=vsf2,items={"vsfilter","vsfiltermod"}},
{x=3,y=6,width=7,class="edit",name="second",value=secondary or ""},
{x=0,y=7,class="label",label="Encoder settings:"},
{x=1,y=7,width=9,class="edit",name="encset",value=sett},
{x=0,y=8,class="label",label="Settings 4 mocha:"},
{x=1,y=8,width=9,class="edit",name="encmocha",value=msett or defmsett},
{x=0,y=9,class="checkbox",name="trim",label="Trim from:",hint="Encodes only current selection"},
{x=1,y=9,width=3,class="intedit",name="sf",value=sframe},
{x=4,y=9,class="label",label="to: "},
{x=5,y=9,width=2,class="intedit",name="ef",value=eframe},
{x=7,y=9,width=2,class="label",label=" If checked, frames are added to Encode name "},
{x=9,y=9,width=1,class="checkbox",name="audio",label="Mux with audio",hint="whether you're trimming or not"},
{x=0,y=10,width=2,class="checkbox",name="mocha",label="Encode clip for mocha "},
{x=2,y=10,width=1,class="checkbox",name="tenbit",label="10 bit"},
{x=5,y=10,width=1,class="checkbox",name="delbat",label="Delete batch file",value=true},
{x=6,y=10,width=2,class="checkbox",name="delavs",label="Delete avisynth script",value=true},
{x=8,y=10,width=1,class="checkbox",name="delAV",label="Delete A/V after muxing",value=true,hint="Delete audio/video files only needed for muxing"},
{x=9,y=10,width=1,class="checkbox",name="pause",label="Keep cmd window open "},
}
repeat
if P=="Default enc. settings" then
gui("encset",defsett)
end
if P=="x264" then
x264_path=ADO("x264","",scriptpath,"*.exe",false,true)
gui("xpath",x264_path)
end
if P=="x264 10bit" then
x26410_path=ADO("x264 10-bit","",scriptpath,"*.exe",false,true)
gui("xpath10",x26410_path)
end
if P=="vsfilter" then
vsf_path=ADO("vsfilter","",scriptpath,"*.dll",false,true)
gui("vsf",vsf_path)
end
if P=="vsfiltermod" then
vsfm_path=ADO("vsfiltermod","",scriptpath,"*.dll",false,true)
gui("vsfm",vsfm_path)
end
if P=="Target" then
tgt_path=ADO("Target folder for encodes (Select any file in it)",".",scriptpath,"",false,false)
if tgt_path then tgt_path=tgt_path:gsub("(.*\\).-$","%1") end
gui("target",tgt_path)
end
if P=="Secondary" then
sec_path=ADO("Secondary subs","",scriptpath,"*.ass",false,true)
gui("second",sec_path)
end
if P=="Enc. set." then
enclist={defsett}
for set in settlist:gmatch("settings%d:(.-)\n") do
table.insert(enclist,set)
end
encodings={{class="dropdown",name="enko",items=enclist,value=defsett}}
press,rez=ADD(encodings,{"OK","Cancel"},{ok='OK',close='Cancel'})
for k,v in ipairs(GUI) do
if v.name=="encset" then v.value=rez.enko else v.value=res[v.name] end
end
end
if P=="Save" then
konf="xpath:"..res.xpath.."\nxpath10:"..res.xpath10.."\nvsfpath:"..res.vsf.."\nvsfmpath:"..res.vsfm.."\nmmgpath:"..res.mmg.."\nvtype:"..res.vtype.."\nfilter1:"..res.filter1.."\nfilter2:"..res.filter2.."\ntarg:"..res.targ.."\ntarget:"..res.target.."\nmocha:"..res.encmocha.."\nsettings:"..res.encset.."\n"
if res.encset~=sett then
settlist=settlist:gsub("settings9:.-\n","")
set1=esc(sett)
if not settlist:match(set1) then
for i=8,1,-1 do
settlist=settlist:gsub("(settings)"..i,"%1"..i+1)
end
settlist="settings1:"..sett.."\n"..settlist
end
end
konf=konf..settlist
file=io.open(enconfig,"w")
file:write(konf)
file:close()
for k,v in ipairs(GUI) do v.value=res[v.name] end
ADD({{class="label",label="Settings saved to:\n"..enconfig}},{"OK"},{close='OK'})
end
P,res=ADD(GUI,
{"Encode","x264","x264 10bit","vsfilter","vsfiltermod","Target","Secondary","Enc. set.","Save","Cancel"},{ok='Encode',close='Cancel'})
until P=="Encode" or P=="Cancel"
if P=="Cancel" then ak() end
----------------------------------------------------------------------------------------------------------------------------------------
videoname=res.vid
encname=res.vid2
mkvmerge=res.mmg
target=vpath
vfull=vpath..videoname
vsm=0
if res.targ=="Custom:" then target=res.target end
-- mocha
if res.mocha then
res.vtype=".mp4"
res.tenbit=false
res.trim=true
res.encset=res.encmocha.." --seek "..res.sf.." --frames "..res.ef-res.sf
res.delavs=false
encname=encname:gsub("_hardsub","")
source=quo(vfull)
end
if res.filter1=="none" then res.sec=false encname=encname:gsub("_hardsub","_encode") end
if res.trim then encname=encname.."_"..res.sf.."-"..res.ef encname=encname:gsub("_encode","") end
if res.tenbit then xpath=res.xpath10 else xpath=res.xpath end
file=io.open(xpath) if file==nil then t_error(xpath.."\nERROR: File does not exist (x264).",true) else file:close() end
file=io.open(vfull) if file==nil then t_error(vfull.."\nERROR: File does not exist (video source).",true) else file:close() end
-- avisynth
if res.mocha==false then
if res.filter1~="none" and res.first:match("%?script\\") then t_error("ERROR: It appears your subtitles are not saved.",true) end
if res.filter1=="vsfilter" then
plug1="loadplugin(\""..res.vsf.."\")\n" text1="textsub("..quo(res.first)..")\n" vsm=1
elseif res.filter1=="vsfiltermod" then
plug1="loadplugin(\""..res.vsfm.."\")\n" text1="textsubmod("..quo(res.first)..")\n" vsm=2
else
plug1="" text1=""
end
if res.filter2=="vsfilter" then filth2=res.vsf ts2="textsub" else filth2=res.vsfm ts2="textsubmod" end
if res.sec and res.filter1~=res.filter2 then plug2="loadplugin(\""..filth2.."\")\n" vsm=3 else plug2="" end
if res.sec then text2=ts2.."("..quo(res.second)..")\n" else text2="" end
if res.trim then trim="Trim("..res.sf..", "..res.ef-1 ..")" else trim="" end
avs=plug1..plug2.."ffvideosource("..quo(vfull)..")\n"..text1..text2..trim
-- vsfilter checks
if vsm==1 or vsm==3 then
file=io.open(res.vsf) if file==nil then t_error(res.vsf.."\nERROR: File does not exist (vsfilter).",true) else file:close() end
end
if vsm>1 then
file=io.open(res.vsfm) if file==nil then t_error(res.vsfm.."\nERROR: File does not exist (vsfiltermod).",true) else file:close() end
end
if scriptpath=="?script\\" then scriptpath=vpath end
local avsfile=io.open(scriptpath.."hardsub.avs","w")
avsfile:write(avs)
avsfile:close()
source=quo(scriptpath.."hardsub.avs")
end
-- mkvmerge audio
if res.audio then
if res.trim then
vstart=fr2ms(res.sf)
vend=fr2ms(res.ef)
timec1=time2string(vstart)
timec2=time2string(vend)
audiofile=target..encname..".mka"
audiosplit=quo(mkvmerge).." -o "..quo(audiofile).." -D -S -M --split parts:"..timec1.."-"..timec2.." "..quo(vfull)
merge=audiosplit.."\n"..quo(mkvmerge).." -o "..quo(target..encname.."_muxed.mkv").." "..quo(target..encname..res.vtype).." "..quo(audiofile)
else
merge=quo(mkvmerge).." -o "..quo(target..encname.."_muxed.mkv").." "..quo(target..encname..res.vtype).." -D -S -M "..quo(vfull)
end
end
-- batch script
encode=quo(xpath).." "..res.encset.." -o "..quo(target..encname..res.vtype).." "..source
if res.audio then encode=encode.."\n"..merge end
batch=scriptpath.."encode.bat"
if res.pause then encode=encode.."\npause" end
encode=encode.."\ndel "..quo(target..videoname..".ffindex")
if res.audio and res.delAV then encode=encode.."\ndel "..quo(target..encname..res.vtype)
if audiofile then encode=encode.."\ndel "..quo(audiofile) audiofile=nil end
end
if res.delavs then encode=encode.."\ndel "..quo(scriptpath.."hardsub.avs") end
if res.delbat then encode=encode.."\ndel "..quo(batch) end
local xfile=io.open(batch,"w")
xfile:write(encode)
xfile:close()
-- encode
if res.tenbit then ten="Yes" else ten="No" end
if res.trim then tr=res.sf..","..res.ef else tr="None" end
info="Encode name: "..encname..res.vtype.."\n10-bit: "..ten.."\nTrim: "..tr.."\n\nBatch file: "..batch.."\n\nYou can encode now or run this batch file later.\nIf encoding from Aegisub doesn't work,\njust run the batch file.\n\nEncode now?"
P=ADD({{class="label",label=info}},{"Yes","No"},{ok='Yes',close='No'})
if P=="Yes" then
aegisub.progress.title("Encoding...")
batch=batch:gsub("%=","^=")
os.execute(quo(batch))
end
end
function time2string(num)
timecode=math.floor(num/1000)
tc0=math.floor(timecode/3600)
tc1=math.floor(timecode/60)
tc2=timecode%60
numstr="00"..num
tc3=numstr:match("(%d%d)%d$")
if tc1==60 then tc1=0 tc0=tc0+1 end
if tc2==60 then tc2=0 tc1=tc1+1 end
if tc1<10 then tc1="0"..tc1 end
if tc2<10 then tc2="0"..tc2 end
tc0=tostring(tc0)
tc1=tostring(tc1)
tc2=tostring(tc2)
timestring=tc0..":"..tc1..":"..tc2.."."..tc3
return timestring
end
function gui(a,b)
for k,v in ipairs(GUI) do
if b==nil then b="" end
if v.name==a then v.value=b else v.value=res[v.name] end
end
end
function esc(str) str=str:gsub("[%%%(%)%[%]%.%-%+%*%?%^%$]","%%%1") return str end
function logg(m) m=m or "nil" aegisub.log("\n "..m) end
function quo(x) x="\""..x.."\"" return x end
function t_error(message,cancel)
ADD({{class="label",label=message}},{"OK"},{close='OK'})
if cancel then ak() end
end
if haveDepCtrl then depRec:registerMacro(encode) else aegisub.register_macro(script_name,script_description,encode) end