aboutsummaryrefslogtreecommitdiffstats
path: root/macros
diff options
context:
space:
mode:
Diffstat (limited to 'macros')
-rw-r--r--macros/a-b.lua34
-rw-r--r--macros/append-comment.lua35
-rw-r--r--macros/audio-clipper.lua131
-rw-r--r--macros/become-fansubber.lua54
-rw-r--r--macros/chapters.lua80
-rw-r--r--macros/dupe-and-comment.lua33
-rw-r--r--macros/em-dash.lua27
-rw-r--r--macros/karaoke2alpha.lua68
-rw-r--r--macros/scenebleed.lua35
-rw-r--r--macros/select-comments.lua18
10 files changed, 515 insertions, 0 deletions
diff --git a/macros/a-b.lua b/macros/a-b.lua
new file mode 100644
index 0000000..994361f
--- /dev/null
+++ b/macros/a-b.lua
@@ -0,0 +1,34 @@
+script_name = "A-B"
+script_description = "makes checking pre-timing possible."
+script_author = "garret"
+script_version = "2021-07-10"
+
+function switch_number(i)
+ if i == "a" then
+ return "b"
+ elseif i == "b" then
+ return "a"
+ end
+end
+
+function main(sub, sel)
+ local i = "a"
+ for si,li in ipairs(sel) do
+ line = sub[li]
+ if line.actor == "" then
+ indicator = i
+ else
+ indicator = line.actor.." "..i
+ end
+ if line.text == "" then
+ line.text = indicator
+ elseif line.text:gsub("{[^}]-}","") == "" then
+ line.text = indicator.." "..line.text
+ end
+ sub[li] = line
+ i = switch_number(i)
+ end
+ aegisub.set_undo_point(script_name)
+end
+
+aegisub.register_macro(script_name, script_description, main)
diff --git a/macros/append-comment.lua b/macros/append-comment.lua
new file mode 100644
index 0000000..47d3feb
--- /dev/null
+++ b/macros/append-comment.lua
@@ -0,0 +1,35 @@
+script_name = "Append Comment"
+script_description = "{ts do all the work pls kthxbye}"
+script_author = "garret"
+script_version = "1.1.2"
+
+function main(sub, sel)
+ dialog_config=
+ {
+ {
+ class="label",
+ x=0,y=0,width=1,height=1,
+ label="Comment:"
+ },
+ {
+ class="edit",name="msg",
+ x=0,y=1,width=1,height=2,
+ value=""
+ }
+ }
+ if #sel == 1 then
+ table.insert(dialog_config, {class="label",x=0,y=3,width=1,height=1,label="if you're not using this for multiple lines \nyou may as well just type it out yourself"})
+ end
+ button, results = aegisub.dialog.display(dialog_config)
+ if button ~= false then
+ for _, i in ipairs(sel) do
+ local line = sub[i]
+ line.text = line.text.." {"..results.msg.."}"
+ sub[i] = line
+ end
+ else
+ aegisub.cancel()
+ end
+end
+
+aegisub.register_macro(script_name, script_description, main)
diff --git a/macros/audio-clipper.lua b/macros/audio-clipper.lua
new file mode 100644
index 0000000..99f2b9f
--- /dev/null
+++ b/macros/audio-clipper.lua
@@ -0,0 +1,131 @@
+script_name = "Audio Clipper"
+script_description = "Extracts audio from the selected line(s).\nNeeds ffmpeg."
+script_author = "garret"
+script_version = "1.1.2"
+
+aegi = aegisub
+
+function err(msg)
+ aegi.dialog.display({{class = "label", label = msg}}, {"OK"}, {close = "OK"})
+ aegi.cancel()
+end
+
+function get_vid_dir()
+ local aud_dir = aegi.decode_path("?audio")
+ local vid_dir = aegi.decode_path("?video")
+ if aud_dir ~= "?audio" then
+ return aud_dir
+ elseif vid_dir ~= "?video" then -- if there is not, in fact, a video
+ return vid_dir
+ else
+ return nil
+ end
+end
+
+function get_vid()
+ local aud = aegi.project_properties().audio_file -- try get the audio first, if it's loaded separately
+ local vid = aegi.project_properties().video_file
+ if aud ~= "" then
+ return aud
+ elseif vid ~= "" then
+ return vid
+ else
+ return nil
+ end
+end
+
+function get_format(copy, format, custom)
+ if copy == true then -- if we do want to copy
+ if format == "" then -- format is the thing from the dropdown
+ err("Need a format!")
+ elseif format == "AAC" then -- these are the most common audio formats i've seen
+ return "m4a"
+ elseif format == "Opus" then
+ return "opus"
+ elseif format == "FLAC" then
+ return "flac" elseif format == "Custom" then -- but I am not all-knowing, so you can put your own
+ return custom
+ end
+ else -- if we don't want to copy (i.e. we've pressed "Just make it FLAC")
+ return "flac"
+ end
+end
+
+function make_out_path(out_path)
+ local lfs = require "aegisub.lfs"
+ if out_path == "" then
+ err("Need an output path!")
+ end
+ lfs.mkdir(out_path)
+ return out_path
+end
+
+function extract_audio(in_path, start_time, end_time, out_path, name, extension, copy)
+ if copy == true then
+ os.execute('ffmpeg -i "'..in_path..'" -codec copy -vn -ss '..start_time..'ms -to '..end_time..'ms "'..out_path..name..'.'..extension..'" -y')
+ -- takes the video as input, copies the streams, but doesn't include video. sets it to start at the start of the selection, and end at the end of it. outputs to our chosen out path with our chosen name and extension. overwrites anything with the same name.
+ elseif copy == false then
+ os.execute('ffmpeg -i "'..in_path..'" -vn -ss '..start_time..'ms -to '..end_time..'ms "'..out_path..name..'.'..extension..'" -y')
+ -- same as above, but doesn't copy the stream (transcodes to flac)
+ end
+end
+
+function loop(subs, sel, in_path, out_path, extension, copy, delay)
+ aegi.progress.title("Extracting Audio")
+ local progress = 0
+ local progress_increment = 100 / #sel -- increment by this for every line, and the bar will eventually reach 100
+ for x, i in ipairs(sel) do -- x is the position of the line in our selection, i is the position in the whole sub file
+ if aegi.progress.is_cancelled() then -- if you press the cancel button
+ aegi.cancel() -- it stops (mind-blowing, i know)
+ end
+ aegi.progress.set(progress)
+ local line = subs[i]
+ local start_time = line.start_time + delay
+ local end_time = line.end_time + delay
+ aegi.progress.task("Extracting line "..x)
+ extract_audio(in_path, start_time, end_time, out_path, x, extension, copy)
+ progress = progress + progress_increment
+ end
+ aegi.progress.set(100) -- in case it didn't reach 100 on its own
+end
+
+
+function gui(subs, sel)
+ local in_path = get_vid()
+ local out_path = get_vid_dir()
+ if in_path == nil or out_path == nil then -- if no video is loaded
+ in_path = "No audio/video loaded. Specify a path."
+ out_path = in_path -- both the same error message
+ else
+ out_path = out_path.."/audioclipper_output/" -- make the out path the one we actually want
+ end
+
+ local get_input={{class="label",x=0,y=0,label="Input's audio format:"},{class="dropdown",name="format",x=0,y=1,width=2,height=1,items={"AAC","Opus","FLAC","Custom"},value="Audio Format",hint="If you don't know, you should probably press \"Just make it FLAC\", or use mka."},{class="label",x=0,y=2,label="Custom Extension:"},{class="edit",name="custom",x=1,y=2,value="mka",hint="You'll probably be fine with mka, because matroska can contain pretty much anything"},{class="label",x=0,y=3,label="Delay (ms):"},{class="intedit",name="delay",x=1,y=3,value=0,hint="to prevent timing fuckery with weird raws"},{class="label",x=0,y=4,label="Input path:"},{class="edit",name="in_path",x=0,y=5,width=2,height=1,value=in_path,hint="where the audio comes from"},{class="label",x=0,y=6,label="Output path (will be created if it doesn't already exist):"},{class="edit",name="out_path",x=0,y=7,width=2,height=1,value=out_path,hint="where the audio goes"}}
+ local pressed, results = aegi.dialog.display(get_input, {"Cancel", "OK", "Just make it FLAC"})
+ -- there's probably something that can detect the format automatically, but I do not know what it is.
+ if pressed == "Cancel" then
+ aegi.cancel()
+ elseif pressed == "OK" then
+ do_copy = true
+ elseif pressed == "Just make it FLAC" then
+ do_copy = false
+ end
+ local extension = get_format(do_copy, results.format, results.custom) -- gets file extension
+ local delay = results.delay
+ in_path = results.in_path
+ out_path = make_out_path(results.out_path)
+ loop(subs, sel, in_path, out_path, extension, do_copy, delay)
+end
+
+function non_gui(subs, sel) -- no gui, so you can bind it to a hotkey
+ local vid = get_vid()
+ if vid == nil then
+ err("Need an input!\nSpecify a path in the GUI, or load one in aegisub.")
+ else
+ loop(subs, sel, get_vid(), make_out_path(get_vid_dir().."/audioclipper_output/"), 'flac', false, 0)
+ end
+ -- sets sane defaults (takes the audio from the video file, and outputs to /the/video/dir/audioclipper_output/. transcodes to flac. no delay)
+end
+
+aegi.register_macro(script_name, script_description, gui)
+aegi.register_macro(": Non-GUI macros :/"..script_name..": Just make it FLAC", script_description, non_gui) -- same section as unanimated's scripts
diff --git a/macros/become-fansubber.lua b/macros/become-fansubber.lua
new file mode 100644
index 0000000..1dfdb43
--- /dev/null
+++ b/macros/become-fansubber.lua
@@ -0,0 +1,54 @@
+script_name="Restyler"
+script_description="become a fansubber with a click of a button"
+script_author = "garret"
+script_version = "2.0.0"
+
+include("karaskel.lua")
+include("cleantags.lua")
+
+-- TODO: detect pre-existing inline tags
+ -- probably need some kind of ass parsing, or a hack with match()
+
+function add_tags(txt, italic, align) -- everything except txt is boolean. nil = don't change, !nil = change to this value
+
+--[[not quite happy with this, it overwrites the alignment - ie line is "{\an4} blah blah" and style is an8, it just changes it to an8
+realisticly this _probably_ won't be a problem, but still would like to try and stop it at some point to be safe
+italics is fine, it just does {\i1\i0}, which is jank and bad but works fine so i won't worry about it too much]]
+ if italic == true then
+ txt="{\\i1}"..txt
+ elseif italics == false then
+ txt="{\\i0}"..txt
+ end
+ if align ~= nil then
+ txt="{\\an"..align.."}"..txt
+ end
+ txt = cleantags(txt)
+ return txt
+end
+
+function get_new(old, new)
+ local i = nil
+ if old ~= new then
+ i = old
+ end
+ return i
+end
+
+function main(sub, sel)
+ local _, styles = karaskel.collect_head(sub, false)
+ local new_style_name = "Default" -- the one we'll be changing stuff to - TODO: configurable
+ local new_style = styles[new_style_name]
+ for h, i in ipairs(sel) do
+ -- TODO: automatically exclude styles (also configurable)
+ local line = sub[i]
+ local old_style = styles[line.style] -- reinventing the wheel a bit here, since karaskel can do this with preproc_line_size (line.styleref), but it also adds loads of other crap we don't care about for the same functionality in the end, so ¯\_(ツ)_/¯
+ local italic = get_new(old_style.italic, new_style.italic)
+ local align = get_new(old_style.align, new_style.align)
+ line.style = new_style_name
+ line.text = add_tags(line.text, italic, align)
+ sub[i] = line
+ end
+ aegisub.set_undo_point(script_name)
+end
+
+aegisub.register_macro(script_name, script_description, main)
diff --git a/macros/chapters.lua b/macros/chapters.lua
new file mode 100644
index 0000000..0dab8bd
--- /dev/null
+++ b/macros/chapters.lua
@@ -0,0 +1,80 @@
+script_name = "Chapter Generator"
+script_description = "Makes XML chapters for matroska."
+script_author = "garret"
+script_version = "2.0.0"
+
+language = "eng"
+language_ietf = "en"
+
+function ms_to_human(start) -- From Significance
+ local timecode=math.floor(start/1000)
+ local tc1=math.floor(timecode/60)
+ local tc2=timecode%60
+ local tc3=start%1000
+ local tc4="00"
+ if tc2==60 then tc2=0 tc1=tc1+1 end
+ if tc1>119 then tc1=tc1-120 tc4="02" end
+ if tc1>59 then tc1=tc1-60 tc4="01" end
+ if tc1<10 then tc1="0"..tc1 end
+ if tc2<10 then tc2="0"..tc2 end
+ if tc3<100 then tc3="0"..tc3 end
+ linetime=tc4..":"..tc1..":"..tc2.."."..tc3
+ if linetime=="00:00:00.00" then linetime="00:00:00.033" end
+ return linetime
+end
+
+function get_sane_path()
+ script_path = aegisub.decode_path("?script")
+ audio_path = aegisub.decode_path("?audio")
+ video_path = aegisub.decode_path("?video")
+ if script_path ~= "?script" then
+ return script_path
+ elseif video_path ~= "?video" then
+ return video_path
+ elseif audio_path ~= "?audio" then
+ return audio_path
+ else
+ return ""
+ end
+end
+
+function get_user_path(default_dir)
+ local path = aegisub.dialog.save("Save Chapter File", default_dir, "chapters.xml", "XML files|*.xml|All Files|*", false)
+ return path
+end
+
+function main(sub)
+ local times = {}
+ local names = {}
+ for i=1,#sub do
+ local line = sub[i]
+ if line.class == "dialogue" then
+ local fx = line.effect
+ if fx:match("[Cc]hapter") or fx:match("[Cc]hptr") or fx:match("[Cc]hap") then
+ line.comment = true
+ table.insert(times, line.start_time)
+ table.insert(names, line.text)
+ sub[i] = line
+ end
+ end
+ end
+ aegisub.set_undo_point(script_name)
+ local chapters = "<?xml version=\"1.0\"?>\n<!-- <!DOCTYPE Chapters SYSTEM \"matroskachapters.dtd\"> -->\n<Chapters>\n <EditionEntry>\n"
+ for j, k in ipairs(times) do
+ local humantime = ms_to_human(k)
+ local name = names[j]
+ chapters = chapters.." <ChapterAtom>\n <ChapterTimeStart>"..humantime.."</ChapterTimeStart>\n <ChapterDisplay>\n <ChapterString>"..name.."</ChapterString>\n <ChapLanguageIETF>"..language_ietf.."</ChapLanguageIETF>\n <ChapterLanguage>"..language.."</ChapterLanguage>\n </ChapterDisplay>\n </ChapterAtom>\n"
+ end
+ chapters = chapters.." </EditionEntry>\n</Chapters>"
+ sane_path = get_sane_path()
+ path = get_user_path(sane_path)
+ if path ~= nil then
+ local chapfile = io.open(path, "w")
+ chapfile:write(chapters)
+ chapfile:close()
+ else
+ aegisub.cancel()
+ end
+end
+
+aegisub.register_macro(script_name, script_description, main)
diff --git a/macros/dupe-and-comment.lua b/macros/dupe-and-comment.lua
new file mode 100644
index 0000000..97b71dd
--- /dev/null
+++ b/macros/dupe-and-comment.lua
@@ -0,0 +1,33 @@
+script_name="Dupe and Comment"
+script_description="Copies a line and comments out the original."
+script_author = "garret"
+script_version = "2021-04-11"
+include("utils.lua")
+-- i like seeing the original while editing, and being able to go back to it easily
+
+function comment(subs, sel)
+ for i=#sel,1,-1 do
+ local line=subs[sel[i]]
+ local dupe = util.copy(line)
+ line.comment = false -- going to edit it, so we probably want to see it on the video
+ dupe.comment = true -- this is the actual original one
+ subs.insert(sel[i]+1,dupe) -- putting it on the next line so i don't have to change line
+ end
+ aegisub.set_undo_point(script_name)
+end
+
+function undo(subs, sel)
+ for i=#sel,1,-1 do
+ local edit=subs[sel[i]]
+ local original=subs[sel[i]+1]
+ if edit.comment == false and original.comment == true then
+ original.comment = false
+ subs[sel[i]+1] = original
+ subs.delete(sel[i])
+ end
+ end
+ aegisub.set_undo_point("Undo "..script_name)
+end
+
+aegisub.register_macro(script_name.."/Do", script_description, comment)
+aegisub.register_macro(script_name.."/Undo", "Deletes selected line and restores the original", undo)
diff --git a/macros/em-dash.lua b/macros/em-dash.lua
new file mode 100644
index 0000000..99d22df
--- /dev/null
+++ b/macros/em-dash.lua
@@ -0,0 +1,27 @@
+script_name = "Em-dash"
+script_description = "I do not have an em-dash key on my keyboard"
+script_author = "garret"
+script_version = "2021-04-05"
+em = "—"
+function append(sub, sel)
+ for si, li in ipairs(sel) do
+ local line = sub[li]
+ line.text = line.text..em
+ sub[li] = line
+ end
+ aegisub.set_undo_point(script_name)
+end
+
+function replace(sub, sel)
+ for si, li in ipairs(sel) do
+ local line = sub[li]
+ local text = sub[li].text
+ text = text:gsub("%-%-",em)
+ line.text=text
+ sub[li] = line
+ end
+ aegisub.set_undo_point(script_name)
+end
+
+aegisub.register_macro(script_name.."/Append", "Appends an Em-dash to the selected line(s)", append)
+aegisub.register_macro(script_name.."/Replace", "Replaces -- with "..em, replace)
diff --git a/macros/karaoke2alpha.lua b/macros/karaoke2alpha.lua
new file mode 100644
index 0000000..1f34da0
--- /dev/null
+++ b/macros/karaoke2alpha.lua
@@ -0,0 +1,68 @@
+script_name="K-Timing -> Alpha Timing"
+script_description="makes doing alpha timing significantly easier by getting rid of the part where you do alpha timing."
+script_author = "garret"
+script_version = "1.0.1"
+include("utils.lua")
+
+-- logging stuff, for testing
+--[[inspect = require 'inspect' -- luarocks install inspect
+function log(level, msg)
+ if type(level) ~= "number" then -- if no actual level provided
+ msg = level -- set the non-level as the message
+ level = 4 -- set log level - i'm using this for debugging, so 4 is relatively sane imo
+ end
+ if type(msg) == "table" then
+ msg = inspect(msg) -- actually see what's in the table
+ end
+ aegisub.log(level, tostring(msg) .. "\n")
+end]]
+-- i should really put this stuff in a separate file or something but cba
+
+function get_visible(parsed_line, index)
+ local res = ""
+ for i=1,index do -- for every syl up to the current one
+ res = res..parsed_line[i].text -- add to the result
+ end
+ return res
+end
+
+function get_invisible(parsed_line, index)
+ local res = ""
+ for i=index+1,#parsed_line do -- for every syl from the next one to the end
+ res = res..parsed_line[i].text -- add to result
+ end
+ return res
+end
+
+function main(sub, sel)
+ for x=#sel,1,-1 do
+ local line=sub[sel[x]]
+ local parsed = aegisub.parse_karaoke_data(line) -- magic function that gets all the stuff about the karaoke
+ for i=1,#parsed do -- for every syl in the karaoke
+ visible = get_visible(parsed, i)
+ invisible = get_invisible(parsed, i)
+ if invisible ~= "" then -- if there's still invisible stuff left
+ text = visible.."{\\alpha&HFF&}"..invisible -- add an alpha tag and slap the invisible stuff on the end
+ else -- if it's all visible
+ text = visible -- don't need the alpha any more
+ end
+ local syl = parsed[i]
+ local new = util.copy(line)
+ new.text = text -- make a new line for this syl
+ -- set line start time
+ new.start_time = syl.start_time + line.start_time -- just the syl on its own returns the offset from the line
+ -- set line end time
+ if i ~= #parsed then -- if there's still invisible stuff left
+ new.end_time = syl.end_time + line.start_time -- end time is the syl's
+ else
+ new.end_time = line.end_time -- end time is the whole line's (i don't think this actually makes a difference but may as well)
+ end
+ sub.insert(sel[x] + i,new) -- add new lines (+1 line for first syl, +2 for 2nd syl, etc)
+ end
+ line.comment = true -- don't want to see the karaoke any more
+ sub[sel[x]]=line
+ end
+ aegisub.set_undo_point(script_name)
+end
+
+aegisub.register_macro(script_name, script_description, main)
diff --git a/macros/scenebleed.lua b/macros/scenebleed.lua
new file mode 100644
index 0000000..c0d3908
--- /dev/null
+++ b/macros/scenebleed.lua
@@ -0,0 +1,35 @@
+script_name="Scenebleed Detector"
+script_description="marks possible scenebleeds with an effect"
+script_author="garret"
+script_version="2021-07-14"
+
+function main(sub, sel)
+ local thresh = aegisub.frame_from_ms(500)
+ local bleedstring = "bleed"
+ -- tried to make config file work, failed, so shit's hardcoded
+
+ local keyframes = aegisub.keyframes()
+ local bleed_count = 0
+ for j,i in ipairs(sel) do
+ line = sub[i]
+ local start_frame = aegisub.frame_from_ms(line.start_time)
+ local end_frame = aegisub.frame_from_ms(line.end_time)
+ for index, frame in ipairs(keyframes) do
+ if end_frame > frame and end_frame < frame + thresh or start_frame < frame and start_frame >= frame - thresh then
+ -- off the kf, but not by more than the threshold
+ if line.effect == "" then
+ line.effect = bleedstring
+ else
+ line.effect = line.effect.."; "..bleedstring
+ end
+ bleed_count = bleed_count + 1
+ sub[i] = line
+ end
+ end
+ end
+ aegisub.log(bleed_count.." scenebleeds found.")
+ aegisub.set_undo_point(script_name)
+ return sel
+end
+
+aegisub.register_macro(script_name, script_description, main)
diff --git a/macros/select-comments.lua b/macros/select-comments.lua
new file mode 100644
index 0000000..c0c281d
--- /dev/null
+++ b/macros/select-comments.lua
@@ -0,0 +1,18 @@
+script_name = "Select Comments"
+script_description = "Selects all commented lines"
+script_author = "garret"
+script_version = "1.0.1"
+
+function main(sub, sel)
+ sel = {}
+ for i=1,#sub do
+ line=sub[i]
+ if line.comment == true then
+ table.insert(sel, i)
+ end
+ end
+ aegisub.set_undo_point(script_name)
+ return sel
+end
+
+aegisub.register_macro(script_name, script_description, main)