Surgically remove Automation 3.
Going to break UNIX build and Windows buildbot for now. Originally committed to SVN as r3196.
This commit is contained in:
parent
352df194aa
commit
be26ba4652
95 changed files with 4 additions and 24175 deletions
|
@ -1,158 +0,0 @@
|
|||
--[[
|
||||
Copyright (c) 2005, Niels Martin Hansen
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the Aegisub Group nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
]]
|
||||
|
||||
-- Aegisub Automation factory-brewed script
|
||||
-- "Line-per-syllable effects"
|
||||
|
||||
-- Use karaskel.lua for skeleton code
|
||||
include("karaskel-adv.lua")
|
||||
|
||||
-- Define the name of the script
|
||||
name = "Line-per-syllable effects"
|
||||
-- Define a description of the script
|
||||
description = "Makes line-per-syllable effects, that is, each syllable in the script gets its own line. This allows for more advanced effects, such as syllables moving about separately, or overlapping each other."
|
||||
-- Define the script variables that can be configured graphically
|
||||
-- This is the primary point of the script, being able to configure it graphically
|
||||
configuration = {
|
||||
-- First a label to descript what special variables can be used
|
||||
[1] = {
|
||||
name = "label1";
|
||||
kind = "label";
|
||||
label = [[Variable-names are prefixed with $,
|
||||
expressions are enclosed in % pairs.
|
||||
Variables:
|
||||
$START = Start-time of syllable (ms)
|
||||
$END = End-time of syllable (ms)
|
||||
$MID = Time midways through the syllable (ms)
|
||||
$DUR = Duration of syllable (cs)
|
||||
$X = X-position of syllable (center)
|
||||
$WIDTH = width of syllable
|
||||
$HEIGHT = height of syllable
|
||||
(There is no $Y)
|
||||
Calculation example:
|
||||
\t($start,%$start+10,\fscx110\fscy110)
|
||||
\move($x,40,%$x-$width+10%,40)
|
||||
Remember you should always have a \pos or \move in your effect.]];
|
||||
hint = ""
|
||||
-- No "default", since a label doesn't have a value
|
||||
},
|
||||
-- Then a text field to input the string to replace \k's with
|
||||
-- Make the default a "NOP" string
|
||||
[2] = {
|
||||
name = "k_repstr";
|
||||
kind = "text";
|
||||
label = "Effect";
|
||||
hint = "The string to place at the start of every syllable line.";
|
||||
default = "{\\an5\\pos($X,40)\\t($START,$END,\\fry360)}"
|
||||
},
|
||||
-- Allow the user to specify whether to strip tags or not
|
||||
[3] = {
|
||||
name = "striptags";
|
||||
kind = "bool";
|
||||
label = "Strip all tags";
|
||||
hint = "Strip all formatting tags apart from the processed karaoke tags?";
|
||||
default = false
|
||||
},
|
||||
[4] = {
|
||||
name = "workstyle";
|
||||
kind = "style";
|
||||
label = "Line style";
|
||||
hint = "Only apply the effect to lines with this style. Empty means apply to all lines.";
|
||||
default = ""
|
||||
}
|
||||
}
|
||||
-- Mandatory values
|
||||
version, kind= 3, 'basic_ass'
|
||||
|
||||
function do_syllable(meta, styles, config, line, syl)
|
||||
-- text is the replacement text for the syllable
|
||||
-- ktext is the karaoke effect string
|
||||
local text, ktext
|
||||
|
||||
-- Prepare the stripped or unstripped main text
|
||||
if config.striptags then
|
||||
text = syl.text_stripped
|
||||
else
|
||||
text = syl.text
|
||||
end
|
||||
|
||||
-- Don't bother with empty syllables
|
||||
if syl.text == "" or syl.n == 0 then
|
||||
return { n=0 }
|
||||
end
|
||||
|
||||
-- Add the variable names to the syllable data
|
||||
syl["dur"] = syl.duration
|
||||
syl["start"] = syl.start_time
|
||||
syl["end"] = syl.end_time
|
||||
syl["mid"] = syl.start_time + syl.duration*5
|
||||
syl["x"] = syl.center + line.centerleft
|
||||
|
||||
-- Prepare the karaoke effect string
|
||||
ktext = config.k_repstr
|
||||
|
||||
-- Function for replacing the variables
|
||||
local function var_replacer(varname)
|
||||
varname = string.lower(varname)
|
||||
if syl[varname] ~= nil then
|
||||
return syl[varname]
|
||||
else
|
||||
aegisub.output_debug(string.format("Unknown variable name: %s", varname))
|
||||
return "$" .. varname
|
||||
end
|
||||
end
|
||||
-- Replace the variables in the ktext
|
||||
ktext = string.gsub(ktext, "$(%a+)", var_replacer)
|
||||
|
||||
-- Function for evaluating expressions
|
||||
local function expression_evaluator(expression)
|
||||
chunk, err = loadstring(string.format("return (%s)", expression))
|
||||
if (err) ~= nil then
|
||||
aegisub.output_debug(string.format("Error parsing expression:\n%s", expression, err))
|
||||
return "%" .. expression .. "%"
|
||||
else
|
||||
return chunk()
|
||||
end
|
||||
end
|
||||
-- Find and evaluate expressions
|
||||
ktext = string.gsub(ktext, "%%([^%%]*)%%", expression_evaluator)
|
||||
|
||||
local newline = copy_line(line)
|
||||
newline.text = ktext .. text
|
||||
|
||||
return { n=1, [1]=newline }
|
||||
end
|
||||
|
||||
function do_line(meta, styles, config, line)
|
||||
if config.workstyle == "" or config.workstyle == line.style then
|
||||
return karaskel.do_line(meta, styles, config, line)
|
||||
else
|
||||
return { n=1, [1]=line }
|
||||
end
|
||||
end
|
|
@ -1,171 +0,0 @@
|
|||
--[[
|
||||
Copyright (c) 2005, Niels Martin Hansen
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the Aegisub Group nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
]]
|
||||
|
||||
-- Aegisub Automation factory-brewed script
|
||||
-- "Template-based multiple-lines-per-syllable karaoke effects"
|
||||
|
||||
-- Use karaskel.lua for skeleton code
|
||||
include("karaskel-adv.lua")
|
||||
|
||||
-- Define the name of the script
|
||||
name = "Template-based effects"
|
||||
-- Define a description of the script
|
||||
description = "Makes advanced effects using templates embedded into the subtitle script. Please see the help for information on how to use this script."
|
||||
-- Only one config option here.
|
||||
-- Everything else is defined in the subtitle script
|
||||
configuration = {
|
||||
-- Allow the user to specify whether to strip tags or not
|
||||
[1] = {
|
||||
name = "striptags";
|
||||
kind = "bool";
|
||||
label = "Strip all tags";
|
||||
hint = "Strip all formatting tags apart from the processed karaoke tags?";
|
||||
default = false
|
||||
},
|
||||
[2] = {
|
||||
name = "skipunknown";
|
||||
kind = "bool";
|
||||
label = "Remove unknown lines";
|
||||
hint = "Removes all lines without a defined template";
|
||||
default = false
|
||||
}
|
||||
}
|
||||
-- Mandatory values
|
||||
version, kind= 3, 'basic_ass'
|
||||
|
||||
function do_syllable(meta, styles, config, line, syl)
|
||||
-- text is the replacement text for the syllable
|
||||
-- ktext is the karaoke effect string
|
||||
local text, ktext
|
||||
|
||||
-- Prepare the stripped or unstripped main text
|
||||
if config.striptags then
|
||||
text = syl.text_stripped
|
||||
else
|
||||
text = syl.text
|
||||
end
|
||||
|
||||
local result = { n=0 }
|
||||
|
||||
-- Don't bother with empty syllables
|
||||
if syl.text == "" or syl.n == 0 then
|
||||
return result
|
||||
end
|
||||
|
||||
-- Add the variable names to the syllable data
|
||||
syl["dur"] = syl.duration
|
||||
syl["start"] = syl.start_time
|
||||
syl["end"] = syl.end_time
|
||||
syl["mid"] = syl.start_time + syl.duration*5
|
||||
syl["x"] = syl.center + line.centerleft
|
||||
|
||||
-- Prepare the karaoke effect string
|
||||
for templateid, template in template_data[line.style] do
|
||||
local ktext = template.text
|
||||
|
||||
-- do_repeat is global on purpose
|
||||
_G.do_repeat = false
|
||||
|
||||
repeat
|
||||
-- Function for replacing the variables
|
||||
local function var_replacer(varname)
|
||||
varname = string.lower(varname)
|
||||
if syl[varname] ~= nil then
|
||||
return syl[varname]
|
||||
else
|
||||
aegisub.output_debug(string.format("Unknown variable name: %s", varname))
|
||||
return "$" .. varname
|
||||
end
|
||||
end
|
||||
-- Replace the variables in the ktext
|
||||
ktext = string.gsub(ktext, "$(%a+)", var_replacer)
|
||||
|
||||
local skipline = false
|
||||
local newline = copy_line(line)
|
||||
newline.layer = template.layer
|
||||
A = { meta = meta, styles = styles, line = line, syl = syl, newline = newline }
|
||||
|
||||
-- Function for evaluating expressions
|
||||
local function expression_evaluator(expression)
|
||||
if string.find(expression, "return") then
|
||||
chunk, err = loadstring(expression)
|
||||
else
|
||||
chunk, err = loadstring(string.format("return (%s)", expression))
|
||||
end
|
||||
if (err) ~= nil then
|
||||
aegisub.output_debug(string.format("Error parsing expression:\n%s", expression, err))
|
||||
return "%" .. expression .. "%"
|
||||
else
|
||||
local result = chunk(meta, styles, line, syl, newline)
|
||||
if result then
|
||||
return result
|
||||
else
|
||||
skipline = true
|
||||
return ""
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Find and evaluate expressions
|
||||
ktext = string.gsub(ktext, "%%([^%%]*)%%", expression_evaluator)
|
||||
|
||||
newline.text = ktext .. text
|
||||
if not (kline == "" or skipline) then
|
||||
table.insert(result, newline)
|
||||
end
|
||||
until not do_repeat
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function do_line(meta, styles, config, line)
|
||||
if line.kind == "comment" and line.name == "template" then
|
||||
if not template_data[line.style] then
|
||||
template_data[line.style] = {}
|
||||
end
|
||||
table.insert(template_data[line.style], line)
|
||||
return { n=0 }
|
||||
elseif line.kind == "dialogue" and template_data[line.style] then
|
||||
return karaskel.do_line(meta, styles, config, line)
|
||||
elseif not config.skipunknown then
|
||||
return { n=1, [1]=line }
|
||||
else
|
||||
return { n=0 }
|
||||
end
|
||||
if config.workstyle == "" or config.workstyle == line.style then
|
||||
return adv_do_line(meta, styles, config, line)
|
||||
else
|
||||
return { n=1, [1]=line }
|
||||
end
|
||||
end
|
||||
|
||||
function process_lines(meta, styles, lines, config)
|
||||
template_data = {}
|
||||
return karaskel.process_lines(meta, styles, lines, config)
|
||||
end
|
|
@ -1,147 +0,0 @@
|
|||
--[[
|
||||
Copyright (c) 2005, Niels Martin Hansen
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the Aegisub Group nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
]]
|
||||
|
||||
-- Aegisub Automation factory-brewed script
|
||||
-- "Basic \k replacer"
|
||||
|
||||
-- Use karaskel.lua for skeleton code
|
||||
include("karaskel.lua")
|
||||
|
||||
-- Define the name of the script
|
||||
name = "Basic \\k replacer"
|
||||
-- Define a description of the script
|
||||
description = "Makes basic karaoke effects. Replace all \\k tags (and variations) with a custom string, where some variables can be substituted in."
|
||||
-- Define the script variables that can be configured graphically
|
||||
-- This is the primary point of the script, being able to configure it graphically
|
||||
configuration = {
|
||||
-- First a label to descript what special variables can be used
|
||||
[1] = {
|
||||
name = "label1";
|
||||
kind = "label";
|
||||
label = [[Variable-names are prefixed with $,
|
||||
expressions are enclosed in % pairs.
|
||||
Variables:
|
||||
$START = Start-time of syllable (ms)
|
||||
$END = End-time of syllable (ms)
|
||||
$MID = Time midways through the syllable (ms)
|
||||
$DUR = Duration of syllable (cs)
|
||||
Calculation example:
|
||||
\t($start,%$start+$dur*2%,\fscx110)
|
||||
\t(%$start+$dur*2%,$end,\fscx90)]];
|
||||
hint = ""
|
||||
-- No "default", since a label doesn't have a value
|
||||
},
|
||||
-- Then a text field to input the string to replace \k's with
|
||||
-- Make the default a "NOP" string
|
||||
[2] = {
|
||||
name = "k_repstr";
|
||||
kind = "text";
|
||||
label = "\\k replacement";
|
||||
hint = "The string to replace \\k tags with. Should start and end with { } characters.";
|
||||
default = "{\\k$DUR}"
|
||||
},
|
||||
-- Allow the user to specify whether to strip tags or not
|
||||
[3] = {
|
||||
name = "striptags";
|
||||
kind = "bool";
|
||||
label = "Strip all tags";
|
||||
hint = "Strip all formatting tags apart from the processed karaoke tags?";
|
||||
default = false
|
||||
},
|
||||
[4] = {
|
||||
name = "workstyle";
|
||||
kind = "style";
|
||||
label = "Line style";
|
||||
hint = "Only apply the effect to lines with this style. Empty means apply to all lines.";
|
||||
default = ""
|
||||
}
|
||||
}
|
||||
-- Mandatory values
|
||||
version, kind= 3, 'basic_ass'
|
||||
|
||||
function do_syllable(meta, styles, config, line, syl)
|
||||
-- text is the replacement text for the syllable
|
||||
-- ktext is the karaoke effect string
|
||||
local text, ktext
|
||||
|
||||
-- Prepare the stripped or unstripped main text
|
||||
if config.striptags then
|
||||
text = syl.text_stripped
|
||||
else
|
||||
text = syl.text
|
||||
end
|
||||
|
||||
if syl.n == 0 then
|
||||
return text
|
||||
end
|
||||
|
||||
-- Add the variable names to the syllable data
|
||||
syl["dur"] = syl.duration
|
||||
syl["start"] = syl.start_time
|
||||
syl["end"] = syl.end_time
|
||||
syl["mid"] = syl.start_time + syl.duration*5
|
||||
|
||||
ktext = config.k_repstr
|
||||
|
||||
-- Function for replacing the variables
|
||||
local function var_replacer(varname)
|
||||
varname = string.lower(varname)
|
||||
if syl[varname] ~= nil then
|
||||
return syl[varname]
|
||||
else
|
||||
aegisub.output_debug(string.format("Unknown variable name: %s", varname))
|
||||
return "$" .. varname
|
||||
end
|
||||
end
|
||||
-- Replace the variables in the ktext
|
||||
ktext = string.gsub(ktext, "$(%a+)", var_replacer)
|
||||
|
||||
-- Function for evaluating expressions
|
||||
local function expression_evaluator(expression)
|
||||
chunk, err = loadstring(string.format("return (%s)", expression))
|
||||
if (err) ~= nil then
|
||||
aegisub.output_debug(string.format("Error parsing expression:\n%s", expression, err))
|
||||
return "%" .. expression .. "%"
|
||||
else
|
||||
return chunk()
|
||||
end
|
||||
end
|
||||
-- Find and evaluate expressions
|
||||
ktext = string.gsub(ktext, "%%([^%%]*)%%", expression_evaluator)
|
||||
|
||||
return ktext .. text
|
||||
end
|
||||
|
||||
function do_line(meta, styles, config, line)
|
||||
if config.workstyle == "" or config.workstyle == line.style then
|
||||
return karaskel.do_line(meta, styles, config, line)
|
||||
else
|
||||
return { n=1, [1]=line }
|
||||
end
|
||||
end
|
|
@ -1,548 +0,0 @@
|
|||
Aegisub Automation documentation
|
||||
Version 3
|
||||
Copyright 2005 Niels Martin Hansen.
|
||||
|
||||
---
|
||||
|
||||
This document describes version 3 of the automation system used in Aegisub.
|
||||
The automation system uses the Lua language for scripting engine.
|
||||
See <http://www.lua.org/> for more information.
|
||||
|
||||
---
|
||||
|
||||
What is Automation?
|
||||
|
||||
Aegisub Automation is a scripting system designed to automate many processing
|
||||
tasks of ASS subtitles, instead of using tedious, error-prone manual
|
||||
processing. The primary purpose is creating karaoke effects for anime fansubs.
|
||||
|
||||
The Automation script is given the complete subtitle data from a subtitle
|
||||
file, in a format suited for creating special effects.
|
||||
The script will return a complete substiture for the original subtitle
|
||||
data, allowing full freedom of processing.
|
||||
|
||||
A number of helper functions are provided, to aid in finding errors in
|
||||
scripts, as well as retrieve further data about the subtitles, needed to
|
||||
created advanced effects.
|
||||
|
||||
---
|
||||
|
||||
Scripts, files, functions:
|
||||
|
||||
A script is a file containing Lua code. One file can define just one script,
|
||||
but several scripts can share code by the help of including other files.
|
||||
|
||||
All scripts are run in a separate interpreter, and as such don't have any way
|
||||
of interacting with other loaded scripts.
|
||||
|
||||
All strings in a script should be in UTF-8 encoding, without byte-order mark.
|
||||
All strings input to a script are encoded as UTF-8.
|
||||
Script files may start with an UTF-8 BOM (byte-order mark) or not, but this
|
||||
is currently not well tested.
|
||||
|
||||
A script must define certain global variables:
|
||||
|
||||
version
|
||||
Number. Version of the scripting interface used.
|
||||
The version described in this file is 3.
|
||||
To comply with version 3, version must be: 3 <= version < 4
|
||||
kind
|
||||
String. Not used, but mandatory. Set it to "basic_ass" for now.
|
||||
name
|
||||
String. Displayed name of the script.
|
||||
description
|
||||
String. Optional. Long description of the script.
|
||||
process_lines
|
||||
Function. The main script function.
|
||||
configuration
|
||||
Table. Optional. Configuration options for the script.
|
||||
|
||||
The functions are described in detail in the following.
|
||||
|
||||
The script may define further global variables, but they do not have any
|
||||
special meaning. Be aware, however, that later versions of the scripting
|
||||
system might define further global variables with special meanings, so be
|
||||
careful choosing names for private use globals.
|
||||
It's recommended to prefix private global variables with "p_"; the scripting
|
||||
system will never assign special meanings to global variables with that
|
||||
prefix.
|
||||
|
||||
The scripting system defines a global variable with name "aegisub", which
|
||||
contains important values. You should not hide the "aegisub" variable.
|
||||
|
||||
---
|
||||
|
||||
The processing function:
|
||||
|
||||
The processing function is the heart of the script.
|
||||
|
||||
It takes as input some meta-information about the subtitles, the styles
|
||||
used in the subtitles, as well as the actual subtitle data to process.
|
||||
|
||||
The output is a set of subtitle data in the same format as the input.
|
||||
The output subtitle data will be used as a complete replacement of the
|
||||
input data.
|
||||
Future versions might allow modifying style data and meta data as well.
|
||||
|
||||
|
||||
The processing function is defined as follows:
|
||||
|
||||
function process_lines(meta, styles, lines, config)
|
||||
|
||||
The arguments are:
|
||||
|
||||
@meta
|
||||
Table. Meta information about the script. (Script Info section.)
|
||||
@styles
|
||||
Table. Style definitions. (V4+ Styles section.)
|
||||
@lines
|
||||
Table. Subtitle events. (Events section.)
|
||||
@config
|
||||
Table. Values set for the configuration options provided. If no
|
||||
configuration options were provided, this will be an empty table.
|
||||
|
||||
Returns: One value.
|
||||
This value must be a table, using the same format as @lines.
|
||||
Note that the indexes in the return value may be either zero-based or
|
||||
one-based, to allow for greater compatibility. You are encouraged to
|
||||
use one-based indexes.
|
||||
|
||||
|
||||
Description of @meta:
|
||||
|
||||
This is a table with the following keys:
|
||||
|
||||
res_x
|
||||
Horizontal resolution of the script.
|
||||
res_y
|
||||
Vertical resolution of the script.
|
||||
|
||||
|
||||
Description of @styles:
|
||||
|
||||
This is a table with the following keys:
|
||||
|
||||
-1
|
||||
Number. The amount of styles defined, called "n".
|
||||
0 -> n-1
|
||||
Table. The actual style definitions.
|
||||
<string "name">
|
||||
Table. The style definition with the specified name.
|
||||
|
||||
The key -1 is used for count rather than "n", since one might have a style
|
||||
definition with the name "n".
|
||||
|
||||
A style definition is a table with the following keys:
|
||||
|
||||
name
|
||||
String. Name of the style.
|
||||
fontname
|
||||
String. Name of the font used.
|
||||
fontsize
|
||||
Number. Size of the font used.
|
||||
color1
|
||||
String. Primary color.
|
||||
All color fields use raw hexadecimal format, that is, no special characters
|
||||
before or after the hex string.
|
||||
color2
|
||||
String. Secondary color.
|
||||
color3
|
||||
String. Outline color.
|
||||
color4
|
||||
String. Shadow color.
|
||||
bold
|
||||
Boolean. Bold text or not.
|
||||
italic
|
||||
Boolean. Italic text or not.
|
||||
underline
|
||||
Boolean. Underlined text or not.
|
||||
strikeout
|
||||
Boolean. Striked-out text or not.
|
||||
scale_x
|
||||
Number. Horizontal scale.
|
||||
scale_y
|
||||
Number. Vertical scale.
|
||||
spacing
|
||||
Number. Spacing between characters.
|
||||
angle
|
||||
Number. Rotation angle in degrees.
|
||||
borderstyle
|
||||
Number. 1=Outline + drop shadow, 3=Opaque box (not really used???)
|
||||
outline
|
||||
Number. Thickness of outline.
|
||||
shadow
|
||||
Number. Distance of shadow from text.
|
||||
align
|
||||
Number. Numpad style alignment.
|
||||
margin_l
|
||||
Number. Left margin in pixels.
|
||||
margin_r
|
||||
Number. Right margin in pixels.
|
||||
margin_v
|
||||
Number. Vertical margin in pixels.
|
||||
encoding
|
||||
Number. Font encoding used.
|
||||
|
||||
|
||||
Description of @lines:
|
||||
|
||||
This is a table with the following keys:
|
||||
|
||||
n
|
||||
Number. The amount of lines.
|
||||
0 -> n-1
|
||||
Table. The actual lines.
|
||||
|
||||
A line is a table with the following key:
|
||||
|
||||
kind
|
||||
String. Can be "blank", "scomment", "comment" or "dialogue".
|
||||
|
||||
The keys otherwise defined depends on the kind of the line.
|
||||
|
||||
If the kind if "blank", no further fields are defined.
|
||||
|
||||
If the kind is "scomment", the line is a "semicolon comment", and the
|
||||
following key is defined:
|
||||
|
||||
text
|
||||
String. Text following the semicolon until end of line. EOL not included.
|
||||
|
||||
If the kind is "comment" or "dialogue", the line is either a Comment: or
|
||||
a Dialogue: line. In both cases, the following keys are defined:
|
||||
|
||||
layer
|
||||
Number.
|
||||
start_time
|
||||
Number. Start time of line in centiseconds.
|
||||
(Might change to userdata later.)
|
||||
end_time
|
||||
Number. End time of line in centiseconds.
|
||||
(Might change to userdata later.)
|
||||
style
|
||||
String. Style used for this line.
|
||||
name
|
||||
String. Character name speaking this line.
|
||||
margin_l
|
||||
Number. Left margin override, in pixels. (0=no override)
|
||||
margin_r
|
||||
Number. Right margin override, in pixels. (0=no override)
|
||||
margin_v
|
||||
Number. Right margin override, in pixels. (0=no override)
|
||||
effect
|
||||
String. Effect to apply to the line. (No error checking done.)
|
||||
text
|
||||
String. Text to display.
|
||||
text_stripped
|
||||
String. Same as text, but stripped for all tags, and newline/hardspace
|
||||
tags are converted to real newlines/spaces. Non-hard spaces at the start/
|
||||
end of lines are stripped.
|
||||
karaoke
|
||||
Table. Line split into karaoke syllables. See below for more information.
|
||||
|
||||
Note about output:
|
||||
Neither text_stripped nor karaoke are used when the results are parsed, they
|
||||
are only passed to simplify processing. You should set text to the final text
|
||||
of the line, you want in the output.
|
||||
It is encouraged to entirely leave text_stripped and karaoke out of the
|
||||
tables in the result.
|
||||
|
||||
|
||||
Karaoke tables:
|
||||
|
||||
A karaoke table has a number of values indexed by numbers. Each value
|
||||
represents a karaoke syllable.
|
||||
Key "n" holds the number of syllables. The syllables can be accessed from
|
||||
index 0 and up. The syllables are indexed chronologically.
|
||||
A karaoke table always has at least one syllable. The first syllable (index
|
||||
0) contains all data before the first timed syllable.
|
||||
Each syllable is a table containing the following keys:
|
||||
|
||||
duration
|
||||
Number. Duration of the syllable in centiseconds. Always 0 for first
|
||||
syllable.
|
||||
kind
|
||||
String. "Kind" of the karaoke, the name of the tag. For a \k type syllable,
|
||||
kind is "k", for a \kf syllable kind is "kf". Freeform tags can be used, as
|
||||
long as they start with the letter "k" or "K".
|
||||
Always the empty string ("") for the first syllable.
|
||||
text
|
||||
String. Text of the syllable. This includes formatting tags.
|
||||
For the first syllable, this contains everything before the first karaoke
|
||||
timing tag.
|
||||
text_stripped
|
||||
String. Same as text, but with all formatting tags stripped.
|
||||
|
||||
|
||||
Description of @config:
|
||||
|
||||
This is a table. The keys are the names for the options defined in the global
|
||||
"configuration" table. The values are the values provided by the user.
|
||||
|
||||
---
|
||||
|
||||
Script configuration:
|
||||
|
||||
An automation script can provide a configuration set, allowing the user to
|
||||
set certain options before the script is called.
|
||||
|
||||
This is performed through the "configuration" value.
|
||||
|
||||
Scripts can define configuration options of the following types:
|
||||
|
||||
label
|
||||
A static, non-editable text displayed to the user. (Useful for adding
|
||||
additional explanations for some options.)
|
||||
text
|
||||
Freeform text entry.
|
||||
int
|
||||
Integer numbers. A range of valid values can be specified.
|
||||
float
|
||||
Any kind of number. A range of valid values can be specified.
|
||||
bool
|
||||
A boolean on/off value.
|
||||
colour
|
||||
An RGB colour value.
|
||||
style
|
||||
The name of a style defined in the subtitles.
|
||||
|
||||
|
||||
The "configuration" table:
|
||||
|
||||
The "configuration" table contains a number of values indexed by numbers.
|
||||
Each value defines a configuration option.
|
||||
The configuration options must be in keys numbered from 1 to n, where n
|
||||
is the number of options. No "n" key is required.
|
||||
The configuration options will be presented to the user in the order defined.
|
||||
Each configuration option is a table containing the following keys:
|
||||
|
||||
name
|
||||
String. The internal name used to refer to the configuration option.
|
||||
Must not contain the colon or pipe characters. (ASCII 58 and 124.)
|
||||
kind
|
||||
String. One of "label", "text", "int", "float", "bool", "colour" and
|
||||
"style". Defines what kind of option this is.
|
||||
label
|
||||
String. Name of the option, presented to the user. Should be very short.
|
||||
hint
|
||||
String. Longer description of the option, presented to the user as a
|
||||
tooltip. Ignored for "label" kind options.
|
||||
min
|
||||
Number. Optional. Lowest value allowed. Only used for "int" and "float" kinds.
|
||||
max
|
||||
Number. Optional. Highest value allowed. Only used for "int" and "float" kinds.
|
||||
default.
|
||||
Type depends on "kind". The value given to this configuration option before
|
||||
the user has entered another value. Ignored for "label" kind options.
|
||||
|
||||
Data types for the different kinds:
|
||||
|
||||
label
|
||||
None. A label doesn't have a value, and won't be present in the @config
|
||||
table in the process_lines function.
|
||||
text
|
||||
String. You might want to do some kind of extra validation on text input, as
|
||||
it might be anything.
|
||||
int
|
||||
Number. Guaranteed to always be integer.
|
||||
float
|
||||
Number. Can be integer or not.
|
||||
bool
|
||||
Boolean.
|
||||
colour
|
||||
String. An ASS hex colourcode in "&HBBGGRR&" format.
|
||||
style
|
||||
String. The name of the style. The style can't be guaranteed to exist, as
|
||||
another export filter in Aegisub might have removed it before your script
|
||||
gets to run.
|
||||
|
||||
---
|
||||
|
||||
Script environment and registration:
|
||||
|
||||
A script is assigned to a subtitle file by adding it to the
|
||||
"Automation Scripts" extra header in the [Script Info] section. This header
|
||||
contains a list of script filenames, separated by pipe characters. Example:
|
||||
|
||||
Automation Scripts: test1.lua|test2.lua
|
||||
|
||||
All scripts run in their own separate interpreter. This means there is no
|
||||
risk of name collisions, though also that scripts can't easily share code.
|
||||
|
||||
If you need to share code between several scripts, you should create a
|
||||
subdirectory to the script directory, and place include files there.
|
||||
|
||||
|
||||
The settings for the configuration options for a script are stored in the ASS
|
||||
file in the following way:
|
||||
|
||||
Each script gets one line for configuration, named "Automation Settings" plus
|
||||
a space plus the filename of the script. The filename used is stripped of all
|
||||
path specifiers. (Use unique filenames for your scripts!)
|
||||
|
||||
The value of the line is a pipe-separated list of "name:value" pairs. The name
|
||||
is the internal name given by the "name" key. It is not mangled in any way.
|
||||
|
||||
The way the value is stored depends on the kind of the option.
|
||||
|
||||
label
|
||||
Not stored.
|
||||
text
|
||||
The string is stored in an URL-encoding like manner. Some unsafe characters
|
||||
are replaced with escape-sequences of the form #xx, where xx is a two-digit
|
||||
hexadecimal number for the ASCII code of the escaped character. Only ASCII-
|
||||
characters can be escaped this way, Unicode characters aren't supported.
|
||||
int
|
||||
Stored in ASCII base 10 without any group separators.
|
||||
float
|
||||
Stored in exponential notation, using ASCII base 10. (As the %e sprintf()
|
||||
argument.)
|
||||
bool
|
||||
True is stored as "1", false as "0".
|
||||
colour
|
||||
Stored as in ASS hex format without any mangling.
|
||||
style
|
||||
Stored in the same manner as "text" kind options.
|
||||
|
||||
---
|
||||
|
||||
Helper functions:
|
||||
|
||||
There is a gloabl variable names "aegisub". This is a table containing
|
||||
various helper functions.
|
||||
|
||||
The following helper functions are defined:
|
||||
|
||||
|
||||
function aegisub.set_status(text)
|
||||
|
||||
Sets the current status-message. (Used for progress-reporting.)
|
||||
|
||||
@text
|
||||
String. The status message.
|
||||
|
||||
Returns: nothing.
|
||||
|
||||
|
||||
function aegisub.output_debug(text)
|
||||
|
||||
Output text to a debug console.
|
||||
|
||||
@text
|
||||
String. The text to output.
|
||||
|
||||
Returns: nothing.
|
||||
|
||||
|
||||
function aegisub.colorstring_to_rgb(colorstring)
|
||||
|
||||
Convert an ASS color-string to a set of RGB values.
|
||||
|
||||
@colorstring
|
||||
String. The color-string to convert.
|
||||
|
||||
Returns: Four values, all numbers, being the color components in this
|
||||
order: Red, Green, Blue, Alpha-channel
|
||||
|
||||
|
||||
function aegisub.report_progress(percent)
|
||||
|
||||
Report the progress of the processing.
|
||||
|
||||
@percent
|
||||
Number. How much of the data have been processed so far. (Percent)
|
||||
|
||||
Returns: nothing.
|
||||
|
||||
|
||||
function aegisub.text_extents(style, text)
|
||||
|
||||
Calculate the on-screen pixel size of the given text using the given style.
|
||||
|
||||
@style
|
||||
Table. A single style definition like those passed to process_lines.
|
||||
@text
|
||||
String. The text to calculate the extents for. This should not contain
|
||||
formatting codes, as they will be treated as part of the text.
|
||||
|
||||
Returns 4 values:
|
||||
1: Number. Width of the text, in pixels.
|
||||
2: Number. Height of the text, in pixels.
|
||||
3: Number. Descent of the text, in pixels.
|
||||
4: Number. External leading for the text, in pixels.
|
||||
|
||||
Short description of the values returned:
|
||||
Width: The X advance of the text, how much the "cursor" moves forward when
|
||||
this text is rendered.
|
||||
Height: The total height of the text, including internal leading.
|
||||
Descent: How far below the baseline a character can extend. The ascent of
|
||||
the text can be calculated as (height - descent).
|
||||
External leading: How much vertical spacing will be added between the lines
|
||||
of text rendered with this font. The total height of a line is
|
||||
(height + external_leading).
|
||||
|
||||
|
||||
function aegisub.frame_from_ms(ms)
|
||||
|
||||
Return the video frame-number for the given time.
|
||||
|
||||
@ms
|
||||
Number. Time in miliseconds to get the frame number for.
|
||||
|
||||
Returns: A number, the frame numer. If there is no framerate data, returns
|
||||
nil.
|
||||
|
||||
|
||||
function aegisub.ms_from_frame(frame)
|
||||
|
||||
Returns the start-time for the given video frame-number.
|
||||
|
||||
@frame
|
||||
Number. Frame-number to get start-time from.
|
||||
|
||||
Returns: A number, the start-time of the frame. If there is no framerate
|
||||
data, returns nil.
|
||||
|
||||
|
||||
function include(filename)
|
||||
|
||||
Include the named script. The script search-path defined in Aegisub will be
|
||||
used, searching for the script.
|
||||
If the filename is relative, the regular search path will not be used, but
|
||||
instead the filename will be taken as relative to the directory the current
|
||||
script is located in.
|
||||
Note that if you use include() inside an included script, relative paths
|
||||
will still be taken relative to the original script, and not relative to the
|
||||
current included script. This is a design limitation.
|
||||
The included script is loaded as an anonymous function, which is executed in
|
||||
the current environment. This has two implications: You can include files
|
||||
based on conditional statements, and even in loops, and included files can
|
||||
return values using the "return" statement.
|
||||
|
||||
@filename
|
||||
String. Name of the file to include.
|
||||
|
||||
Returns: Depends on the script included.
|
||||
|
||||
Note that if the file couldn't be found, the script will be terminated
|
||||
(or fail to load.)
|
||||
|
||||
---
|
||||
|
||||
Versions of the scripting interface:
|
||||
|
||||
Here's a quick history of the scripting interface:
|
||||
|
||||
Version 1
|
||||
Using Lua as engine.
|
||||
The scripts used in the Karaoke Effector application, avaible at:
|
||||
<http://www.jiifurusu.dk/files/programming/effector/>
|
||||
|
||||
Version 2
|
||||
Using Python as engine.
|
||||
The first draft for an Aegisub automation engine.
|
||||
Never implemented.
|
||||
|
||||
Version 3
|
||||
Using Lua as engine.
|
||||
The current version.
|
|
@ -1,33 +0,0 @@
|
|||
-- Aegisub Automation demonstration script
|
||||
-- Original written by Niels Martin Hansen
|
||||
-- Given into the public domain
|
||||
|
||||
-- Comment lines (like this line) start with two hyphens, these are ignored when the script is interpreted.
|
||||
-- This script does not do anything useful, it merely displays a message. Think of it as a kind of "hello world" script.
|
||||
|
||||
-- The following lines define some values identifying the script
|
||||
-- This script is written for Automation version 3
|
||||
version = 3
|
||||
-- And it's a "basic ass" processing script. There are no other kinds of scripts though... but this is still required.
|
||||
kind = "basic_ass"
|
||||
-- This is the name of the script that shows up in Aegisub
|
||||
name = "Minimal demonstration"
|
||||
-- This is a longer description of the script
|
||||
description = "A very minimal demonstration of the strucrure of an Automation script."
|
||||
-- This defines any configuration that can be done of the script. This is demonstrated in demo 5.
|
||||
-- The empty braces denote an empty table (associative array)
|
||||
configuration = {}
|
||||
|
||||
-- This is the main function of the script.
|
||||
-- This function is run whenever the script is run
|
||||
function process_lines(meta, styles, lines, config)
|
||||
-- The function aegisub-report_progress changes the position of the progress bar shown while the script is running
|
||||
-- The value given is in percent.
|
||||
aegisub.report_progress(50)
|
||||
-- The aegisub,.output_debug function shows some text
|
||||
aegisub.output_debug("Test script 1 running")
|
||||
aegisub.report_progress(100)
|
||||
-- It is very important that the process_lines function returns an array of lines, otherwise an error will occur
|
||||
-- If an empty array is returned, the entire file is cleared!
|
||||
return lines
|
||||
end
|
|
@ -1,23 +0,0 @@
|
|||
[Script Info]
|
||||
; Demonstration script for Aegisub Automation 3 demo script '10-furigana.lua'
|
||||
; http://www.aegisub.net
|
||||
Title: Furigana demonstration
|
||||
ScriptType: v4.00+
|
||||
PlayResX: 640
|
||||
PlayResY: 480
|
||||
Automation Scripts: 10-furigana.lua
|
||||
Export Encoding: UTF-8
|
||||
Export filters: Automation: Furigana demo
|
||||
WrapStyle: 0
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
||||
Style: Default,MS Gothic,36,&H00FFFFFF,&H0000FFFF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,2,2,10,10,30,0
|
||||
|
||||
[Events]
|
||||
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
Dialogue: 0,0:00:00.00,0:00:10.00,Default,,0000,0000,0000,,{\k20}意|い{\k5}味|み{\k7}の{\k14}な{\k6}い{\k30}test|テスト{\k2}を{\k14}魂|た{\k12}#|ま{\k4}#|し{\k8}#|い{\k10}に{\k4}頂|ちょ{\k5}#|う{\k18}戴|だ{\k14}#|い
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
-- Aegisub Automation demonstration script
|
||||
-- Original written by Niels Martin Hansen
|
||||
-- Given into the public domain
|
||||
|
||||
-- Furigana is handled by the advanced karaskel
|
||||
include("karaskel-adv.lua")
|
||||
-- But it requires some additional functionality to be enabled as well. Do that here
|
||||
karaskel.engage_furigana = true
|
||||
-- Enabling trace isn't really required, but it's nice for debugging
|
||||
karaskel.engage_trace = true
|
||||
|
||||
version = 3
|
||||
kind = "basic_ass"
|
||||
name = "Furigana demo"
|
||||
description = "Demonstrates how to use the Furigana feature in karaskel-adv"
|
||||
|
||||
function do_syllable(meta, styles, config, line, syl)
|
||||
-- First prepare a table to add the resulting lines of this syllable to
|
||||
local result = {n=0}
|
||||
-- Actually, make a function that does some stuff for us
|
||||
-- Calling result.add will create another copy of the current line, add it to the result table, and return a reference to the new line
|
||||
-- The result from this function can just be modified, and the line in the result table changes along (since it's just a reference)
|
||||
function result.add()
|
||||
local l = copy_line(line)
|
||||
result.n = result.n + 1
|
||||
result[result.n] = l
|
||||
return l
|
||||
end
|
||||
-- Place the main text
|
||||
-- So far no magic, just a regular line placed
|
||||
local l = result.add()
|
||||
l.text = string.format("{\\an8\\pos(%d,%d)\\k%d\\kf%d}%s", line.centerleft+syl.center, line.height*1.5, syl.start_time/10, syl.duration, syl.text_stripped)
|
||||
l.layer = 5
|
||||
-- Now for some "magic" stuff, loop over the highlights array to add possibly multiple highlights to each syllable
|
||||
-- For example, kanji spanning multiple syllables can "flash" multiple times this way
|
||||
for i = 0, syl.highlights.n-1 do
|
||||
local hl = syl.highlights[i]
|
||||
l = result.add()
|
||||
l.start_time = l.start_time + hl.start_time/10
|
||||
l.end_time = l.start_time + 25
|
||||
l.text = string.format("{\\an8\\k10000\\k0\\move(%d,%d,%d,%d)\\t(\\1a&HFF&\\2a&HFF&\\3a&HFF&\\4a&HFF&)}%s", line.centerleft+syl.center, line.height*1.5, line.centerleft+syl.center, line.height*3, syl.text_stripped)
|
||||
-- Put each highlight in a layer for itself, because they might overlap. This creates a possibly slightly nicer effect
|
||||
l.layer = 10+i
|
||||
end
|
||||
-- Now for the real magic, ,loop over the furigana array
|
||||
-- This contains a lot of pre-calculated info about how each furigana syllable should be placed relatively to the beginning of the line
|
||||
-- With this info, it's really not much different from making a "main" effect. You just have to be aware that you're working with much smaller font sizes
|
||||
for i = 0, syl.furigana.n-1 do
|
||||
local furi = syl.furigana[i]
|
||||
l = result.add()
|
||||
-- Be sure to include the \fscx%f\fs%f tags here! Otherwise the text will be incorrectly scaled.
|
||||
-- The \fscx is also important, because long stretches of furigana might be squished together so it all fits over the main text
|
||||
l.text = string.format("{\\an2\\k%d\\k%d\\bord2\\fscx%.1f\\fs%.1f\\t(%d,%d,\\bord0)\\pos(%d,%d)}%s", furi.start_time/10, furi.duration, syl.furigana.scale, syl.furigana.fontsize, furi.start_time, furi.end_time, line.centerleft+furi.center, line.height*1.5, furi.text)
|
||||
l.layer = 3
|
||||
end
|
||||
-- The additional 'add' function in the result is ignored when it's read back by the caller
|
||||
return result
|
||||
end
|
||||
|
||||
-- Trick: The script includes itself on apply, meaning it's automatically reloaded
|
||||
function process_lines(meta, styles, lines, config)
|
||||
include("10-furigana.lua")
|
||||
-- Make sure to call the karaskel.process_lines function to do the work
|
||||
return karaskel.process_lines(meta, styles, lines, config)
|
||||
end
|
|
@ -1,63 +0,0 @@
|
|||
-- Aegisub Automation demonstration script
|
||||
-- Original written by Niels Martin Hansen
|
||||
-- Given into the public domain
|
||||
|
||||
-- For an explanation of these, see the documentation, or demo 1
|
||||
version = 3
|
||||
kind = "basic_ass"
|
||||
name = "Reading data demonstration"
|
||||
description = "This is a demonstration of how to access the various data passed to an Automation script. It loops over the data structures provided, and dumps them to the debug console."
|
||||
configuration = {}
|
||||
|
||||
include "karaskel-base.auto3"
|
||||
|
||||
function process_lines(meta, styles, lines, config)
|
||||
karaskel.parse_syllable_data(meta, styles, lines)
|
||||
|
||||
-- This makes an alias for the aegisub.output_debug function. Remember that functions are first-class values in Lua.
|
||||
-- The 'local' keyword makes the 'out' variable local to this function
|
||||
local out = aegisub.output_debug
|
||||
|
||||
-- Use the string.format function to form a string showing some metadata about the subtitles and output it
|
||||
out(string.format("Metadata: res_x=%d res_s=%d", meta.res_x, meta.res_y))
|
||||
|
||||
-- The number of styles is stored in index -1, because there might be a style named "n"
|
||||
local numstyles = styles[-1]
|
||||
out("Number of styles: " .. numstyles)
|
||||
-- Loop over the styles with a for loop, printing some info about each style
|
||||
for i = 0, numstyles-1 do
|
||||
out(string.format("Style %d: name='%s' fontname='%s'", i, styles[i].name, styles[i].fontname))
|
||||
end
|
||||
|
||||
-- Do the same, but for the actual subtitle lines
|
||||
out("Number of subtitle lines: " .. lines.n)
|
||||
for i = 0, lines.n-1 do
|
||||
-- Use the report_progress function to show the progress of the loop
|
||||
aegisub.report_progress(i/lines.n*100)
|
||||
-- Check if the line is a dialogue line, otherwise it won't have much interesting data
|
||||
-- Also, the script will crash if you try to access a field that doesn't exist
|
||||
if lines[i].kind == "dialogue" then
|
||||
-- Again, output some info about the line
|
||||
out(string.format("Line %d: dialogue start=%d end=%d style=%s", i, lines[i].start_time, lines[i].end_time, lines[i].style))
|
||||
out(" Text: " .. lines[i].text)
|
||||
out(" Stripped text: " .. lines[i].text_stripped)
|
||||
out(" Number of karaoke syllables: " .. lines[i].karaoke.n)
|
||||
-- Also loop over the karaoke syllables, if any, in the line.
|
||||
-- Note that there will actually always be at least one syllable, number zero, which is everything before the first \k tag
|
||||
for j = 0, lines[i].karaoke.n-1 do
|
||||
syl = lines[i].karaoke[j]
|
||||
-- Use the aegisub.text_extents function to calculate the rendered size of the syllable text
|
||||
-- Note that the styles[lines[i].style] construct can be dangerous, in case the line refers to a non-existant style
|
||||
extx, exty, extd, extl = aegisub.text_extents(styles[lines[i].style], syl.text_stripped)
|
||||
out(string.format(" Syllable %d: dur=%d kind=%s text='%s' text_stripped='%s' extx=%d exty=%d extd=%d extl=%d", j, syl.duration, syl.kind, syl.text, syl.text_stripped, extx, exty, extd, extl))
|
||||
end
|
||||
else
|
||||
-- For non-dialogue lines, output a lot less info
|
||||
out(string.format("Line %d: %s", i, lines[i].kind))
|
||||
end
|
||||
end
|
||||
out("Finished dumping")
|
||||
|
||||
-- In the end, no modifications were done, so just return the original subtitle data
|
||||
return lines
|
||||
end
|
|
@ -1,25 +0,0 @@
|
|||
-- Aegisub Automation demonstration script
|
||||
-- Original written by Niels Martin Hansen
|
||||
-- Given into the public domain
|
||||
|
||||
-- This script demonstrated using include scripts in Automation.
|
||||
-- You include a file simply by calling the include function with a filename.
|
||||
-- Depending on whether the filename contains a path or not, it is interpreted in slightly different ways,
|
||||
-- see the documentation for more information.
|
||||
include("utils.lua")
|
||||
|
||||
-- The usual info
|
||||
name = "Include demo"
|
||||
description = "Simple demonstration of the include function."
|
||||
-- Here several values are set in one line
|
||||
version, kind, configuration = 3, 'basic_ass', {}
|
||||
|
||||
function process_lines(meta, styles, lines, config)
|
||||
-- Copy the first line (line 0) and store it as as a new last line
|
||||
-- The last line has index lines.n-1, so lines.n is one past the last line
|
||||
lines[lines.n] = copy_line(lines[0])
|
||||
-- Make sure to increment 'n', so the correct number of lines are read out
|
||||
lines.n = lines.n + 1
|
||||
-- Then return the modified lines table
|
||||
return lines
|
||||
end
|
|
@ -1,56 +0,0 @@
|
|||
-- Aegisub Automation demonstration script
|
||||
-- Original written by Niels Martin Hansen
|
||||
-- Given into the public domain
|
||||
|
||||
include("utils.lua")
|
||||
|
||||
name = "Text placement demo"
|
||||
description = "Demonstration of the text_extents function, to do per-syllable placement of text."
|
||||
version, kind, configuration = 3, 'basic_ass', {}
|
||||
|
||||
function process_lines(meta, styles, lines, config)
|
||||
-- Prepare local variables
|
||||
local output = { n=0 }
|
||||
-- Loop through every line
|
||||
for i = 0, lines.n-1 do
|
||||
aegisub.report_progress(i/lines.n*100)
|
||||
-- Only process dialogue lines
|
||||
if lines[i].kind ~= "dialogue" then
|
||||
output.n = output.n + 1
|
||||
output[output.n] = lines[i]
|
||||
else
|
||||
-- This is just for making the code a bit easier to read
|
||||
local line = lines[i]
|
||||
-- Get the rendered size of the entire line. (Won't work if there's line breaks in it.)
|
||||
local totalx, totaly = aegisub.text_extents(styles[line.style], line.text_stripped)
|
||||
-- Calculate where the first syllable should be positioned, if the line is to appear centered on screen
|
||||
local curx, cury = (meta.res_x - totalx) / 2, meta.res_y / 2
|
||||
-- And more preparations for per-syllable placement
|
||||
local startx = curx
|
||||
local tstart, tend = 0, 0
|
||||
-- Now process each stllable
|
||||
for j = 1, line.karaoke.n-1 do
|
||||
-- A shortcut variable, and, most important: a copy of the original line
|
||||
local syl, syllin = line.karaoke[j], copy_line(line)
|
||||
-- Calculate the ending time of this syllable
|
||||
tend = tstart + syl.duration*10
|
||||
-- Get the rendered size of this syllable
|
||||
local extx, exty, extd, extl = aegisub.text_extents(styles[line.style], syl.text_stripped)
|
||||
-- Some debug stuff...
|
||||
aegisub.output_debug(string.format("text_extents returned: %d, %d, %d, %d", extx, exty, extd, extl));
|
||||
-- Replace the text of the copy of the line with this syllable, moving around
|
||||
syllin.text = string.format("{\\an4\\move(%d,%d,%d,%d,%d,%d)\\kf%d\\kf%d}%s", curx, cury, curx, cury-exty, tstart, tend, tstart/10, syl.duration, syl.text)
|
||||
-- Add the line to the output
|
||||
output.n = output.n + 1
|
||||
output[output.n] = syllin
|
||||
-- And prepare for next iteration
|
||||
curx = curx + extx
|
||||
tstart = tend
|
||||
end
|
||||
-- More debug stuff
|
||||
aegisub.output_debug(string.format("after syllable loop: totalx=%d curx-startx=%d", totalx, curx-startx))
|
||||
end
|
||||
end
|
||||
-- And remember to return something :)
|
||||
return output
|
||||
end
|
|
@ -1,96 +0,0 @@
|
|||
-- Aegisub Automation demonstration script
|
||||
-- Original written by Niels Martin Hansen
|
||||
-- Given into the public domain
|
||||
|
||||
name = "Configuration demo"
|
||||
description = "This script allows the user to input some data in the Aegisub Export window. Some of these data are used during the processing, to change the subtitles. (The strings is prepended every dialogue line.)"
|
||||
version, kind = 3, 'basic_ass'
|
||||
-- The configuration table defines a number of controls to show in the config window
|
||||
-- The controls must be numbered from 1 and up with no "holes", the number of controls is automatically detected
|
||||
configuration = {
|
||||
[1] = {
|
||||
-- There are some mandatory fields for evry control defined
|
||||
-- 'name' is the internal name of the control, it's used to refer to the value the user entered later on
|
||||
name = "thelabel";
|
||||
-- 'kind' is the class of control, this is a label which only displays text and can't be edited
|
||||
kind = "label";
|
||||
-- 'label' is a short description of the control, displayed ot the left of it.
|
||||
-- In the case of a label control, it's the entire text displayed
|
||||
label = "This is a label control. Just for shows.";
|
||||
-- 'hint' is a tooltip for the control. It doesn't actually work for label controls though
|
||||
hint = "Tooltip for label?!?";
|
||||
};
|
||||
[2] = {
|
||||
name = "thestring";
|
||||
-- the "text" class is a regular text input field
|
||||
kind = "text";
|
||||
label = "String:";
|
||||
hint = "The string to insert at the beginning of each line";
|
||||
-- The 'default' is required for everything but 'label' controls, it simply specifies the default value
|
||||
default = "foobar "
|
||||
};
|
||||
[3] = {
|
||||
name = "theint";
|
||||
-- 'int' is a text control that only allows inputting whole numbers (integers)
|
||||
kind = "int";
|
||||
label = "Integer:";
|
||||
hint = "An integer number to display in debug output";
|
||||
default = 50;
|
||||
-- If the 'min' and 'max' fields are specified, the control will get a "spin control" attached,
|
||||
-- which can be used to change the value with the mouse
|
||||
min = 0;
|
||||
max = 100;
|
||||
};
|
||||
[4] = {
|
||||
name = "thefloat";
|
||||
-- 'float' is like int, except you can also put decimal numbers in it
|
||||
kind = "float";
|
||||
label = "Float number:";
|
||||
hint = "Just a random float number";
|
||||
default = 3.1415927;
|
||||
-- There are no working spin controls for floats, unfortunately
|
||||
};
|
||||
[5] = {
|
||||
name = "thebool";
|
||||
-- 'bool' makes a checkbox, which can either be checked or unchecked
|
||||
kind = "bool";
|
||||
label = "I accept";
|
||||
hint = "Check if you accept the terms of the license agreement";
|
||||
-- false means unchecked, true means checked
|
||||
default = false;
|
||||
};
|
||||
[6] = {
|
||||
name = "thecolour";
|
||||
-- 'colour' is currently just a text edit box which allows you to input an ASS format color
|
||||
-- The idea was to have some kind of graphical control, but that probably won't happen in auto3
|
||||
kind = "colour";
|
||||
label = "Favourite color:";
|
||||
hint = "What color do you want your pantsu?";
|
||||
default = "&H8080FF";
|
||||
};
|
||||
[7] = {
|
||||
name = "thestyle";
|
||||
-- 'style' produces a drop down list, where the user can select one of the styles in the file, or no style at all
|
||||
kind = "style";
|
||||
label = "Style:";
|
||||
hint = "Pick a style the effects will apply to, or none to apply to everything";
|
||||
-- An empty string means that nothing is selected
|
||||
-- Be careful about assuming any style names that might be available in the subtitle file
|
||||
default = "";
|
||||
}
|
||||
}
|
||||
|
||||
function process_lines(meta, styles, lines, config)
|
||||
-- All the values selected by the user are stored in the 'config' variable
|
||||
-- For example, control 2 in this example has name "thestring", so you can access the value input by config.thestring
|
||||
aegisub.output_debug("The string entered is: " .. config.thestring)
|
||||
for i = 0, lines.n-1 do
|
||||
aegisub.report_progress(i/lines.n*100)
|
||||
if lines[i].kind == "dialogue" then
|
||||
-- So loop over all dialogue lines and append thestring to them all
|
||||
lines[i].text = config.thestring .. lines[i].text
|
||||
end
|
||||
end
|
||||
return lines
|
||||
end
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
-- Aegisub Automation demonstration script
|
||||
-- Original written by Niels Martin Hansen
|
||||
-- Given into the public domain
|
||||
|
||||
-- Define some required constants
|
||||
-- version and kind are required to have the given values for the script to work.
|
||||
-- configuration is not needed in this script, so it's just left as an empty table
|
||||
version, kind, configuration = 3, "basic_ass", {}
|
||||
|
||||
-- Define the displayed name of the script
|
||||
name = "Simple karaoke effect"
|
||||
-- A longer description of the script
|
||||
description = "A simple karaoke effect, with the source code heavily commented. Provided as a starting point for a useful effect."
|
||||
|
||||
-- The actual script function
|
||||
function process_lines(meta, styles, lines, config)
|
||||
-- Create a local variable to store the output subtitles in
|
||||
local output = { n=0 }
|
||||
|
||||
-- Start to loop over the lines, one by one
|
||||
-- The lines are numbered 0..n-1
|
||||
for i = 0, lines.n-1 do
|
||||
-- Show the user how far the script has got
|
||||
aegisub.report_progress(i/lines.n*100)
|
||||
-- First check if the line is even a dialogue line. If it's not, no need to process it.
|
||||
if lines[i].kind ~= "dialogue" then
|
||||
output.n = output.n + 1
|
||||
output[output.n] = lines[i]
|
||||
else
|
||||
-- This is a dialogue line, so process is
|
||||
-- Make a nicer name for the line we're processing
|
||||
newline = lines[i]
|
||||
-- Also show the line to the user
|
||||
aegisub.set_status(newline.text_stripped)
|
||||
|
||||
-- The text of the new line will be build little by little
|
||||
-- Each line has 700 ms fadein, 300 ms fadeout,
|
||||
-- is positioned at the center of the screen (\an8)
|
||||
-- and the highlighting should be delayed by 1000 ms (100 cs)
|
||||
newline.text = string.format("{\\fad(700,300)\\pos(%d,30)\\k100}", meta.res_x/2)
|
||||
-- Make the line start 1000 ms (100 cs) earlier than original
|
||||
newline.start_time = newline.start_time - 100
|
||||
|
||||
-- Now it's time to loop through the syllables one by one, processing them
|
||||
-- The first syllable is usually a "null" syllable, not containing real data, so that one should be skipped.
|
||||
-- This variable is used to keep track of when the last syllable ended
|
||||
-- It's initialised to 1000, since the start of the line was pushed 1000 ms back
|
||||
local cursylpos = 1000
|
||||
for j = 1, lines[i].karaoke.n-1 do
|
||||
local syl = lines[i].karaoke[j]
|
||||
-- Call another function to process the syllable
|
||||
newline.text = newline.text .. doSyllable(syl.text, cursylpos, cursylpos+syl.duration*10, syl.duration, syl.kind)
|
||||
-- Calculate the start time of the next syllable
|
||||
cursylpos = cursylpos + syl.duration*10
|
||||
end
|
||||
|
||||
-- The entire line has been calculated
|
||||
-- Add it to the output
|
||||
output.n = output.n + 1
|
||||
output[output.n] = newline
|
||||
end
|
||||
end
|
||||
|
||||
-- All lines processed, and output filled
|
||||
-- Just return it
|
||||
-- (This is important! If you don't return anything, the output file will be empty!)
|
||||
return output
|
||||
end
|
||||
|
||||
-- This effect was originally written in the "Effector" program, which can be considered the first version of Automation.
|
||||
-- This following function is almost verbatimly copied from that original script.
|
||||
-- This is done in order to show how you can make sub-functions to make your script more readable.
|
||||
-- The contents of this function could also just be pasted into the middle of the main loop in process_lines,
|
||||
-- but that generally makes scripts harder to read.
|
||||
function doSyllable(text, t_start, t_end, t_dur, ktype)
|
||||
-- Declare two local variables needed here
|
||||
-- (If they're not declared local, they will be global.)
|
||||
local a, b
|
||||
-- If it's a "long" syllable, let the effect be different
|
||||
if t_dur > 75 then
|
||||
a = t_start + 500
|
||||
b = t_end
|
||||
else
|
||||
a = t_start + 100
|
||||
b = t_start + 500
|
||||
end
|
||||
-- Return the replacement for the syllable, including some ASS tags for format it
|
||||
return string.format("{\\r\\t(%d,%d,\\1c&H808080&\\2c&H808080&)\\kf%d}%s", a, b, t_dur, text)
|
||||
end
|
|
@ -1,201 +0,0 @@
|
|||
-- Aegisub Automation demonstration script
|
||||
-- Original written by Niels Martin Hansen
|
||||
-- Given into the public domain
|
||||
-- But still, please don't use the effect generated by this script
|
||||
-- (unchanged) for your own works.
|
||||
|
||||
-- Note that many of the techniques used in this script are heavily deprecated, much of the processing done
|
||||
-- is also done by the karaskel scripts.
|
||||
-- In fact, this can almost be viewed as an example of how *not* to do things...
|
||||
|
||||
-- Since this script assumes some rather specific things about the ASS input, it might not be very useful at first.
|
||||
-- The original ASS file this was written for is available upon request.
|
||||
|
||||
include("utils.lua")
|
||||
|
||||
name = "Advanced karaoke effect"
|
||||
description = "An advanced karaoke effect, making heavy use of both line-copying and per-syllable text placement. Also demonstrates how to treat lines differently, based on their style, and syllables differently based on the timing tag used."
|
||||
version, kind, configuration = 3, 'basic_ass', {}
|
||||
|
||||
function process_lines(meta, styles, lines, config)
|
||||
local output = { n=0 }
|
||||
math.randomseed(5922) -- just to make sure it's initialised the same every time
|
||||
for curline = 0, lines.n-1 do
|
||||
aegisub.report_progress(curline/lines.n*100)
|
||||
local lin = lines[curline]
|
||||
if lin.kind == "dialogue" and lin.style == "op romaji" then
|
||||
doromaji(lin, output, styles["op romaji"], 30)
|
||||
elseif lin.kind == "dialogue" and lin.style == "op kanji" then
|
||||
-- Just one of these lines should be uncommented.
|
||||
-- This script was written before configuration worked, otherwise it would use configuration
|
||||
-- to select which of the two effects to use for "op kanji" style lines.
|
||||
--doromaji(lin, output, styles["op kanji"], 20)
|
||||
dokanji(lin, output, styles["op kanji"])
|
||||
else
|
||||
-- Unknown lines are copied verbatim
|
||||
output.n = output.n + 1
|
||||
output[output.n] = lin
|
||||
end
|
||||
end
|
||||
return output
|
||||
end
|
||||
|
||||
function doromaji(lin, output, sty, linetop)
|
||||
aegisub.set_status(lin.text_stripped)
|
||||
|
||||
--local linetop = 50
|
||||
|
||||
-- prepare syllable data
|
||||
local linewidth = 0
|
||||
local syltime = 0
|
||||
local syls = {n=0}
|
||||
for i = 1, lin.karaoke.n-1 do
|
||||
local syl = lin.karaoke[i]
|
||||
syl.width, syl.height, syl.descent, syl.extlead = aegisub.text_extents(sty, syl.text_stripped)
|
||||
syl.left = linewidth
|
||||
syl.start_time = syltime
|
||||
syl.end_time = syltime + syl.duration
|
||||
syltime = syltime + syl.duration
|
||||
if syl.kind == "kf" and (syl.text == " " or syl.text == " ") then
|
||||
-- The font this effect was made to work with has too wide spaces, so make those half width
|
||||
syl.width = math.floor(syl.width / 2)
|
||||
syl.kind = "space"
|
||||
elseif syl.kind == "kf" then
|
||||
syl.kind = "deco"
|
||||
elseif syl.kind == "k" then
|
||||
syl.kind = "reg"
|
||||
elseif syl.kind == "ko" then
|
||||
syl.kind = "dance"
|
||||
else
|
||||
syl.kind = "ignore"
|
||||
end
|
||||
if syl.text == "#" then
|
||||
syls[syls.n-1].duration = syls[syls.n-1].duration + syl.duration
|
||||
syls[syls.n-1].end_time = syls[syls.n-1].end_time + syl.duration
|
||||
else
|
||||
linewidth = linewidth + syl.width
|
||||
syls[syls.n] = syl
|
||||
syls.n = syls.n + 1
|
||||
end
|
||||
end
|
||||
local lineofs = math.floor((640 - linewidth) / 2)
|
||||
|
||||
for i = 0, syls.n-1 do
|
||||
local syl = syls[i], copy_line(lin)
|
||||
if syl.kind == "space" then
|
||||
-- Spaces are skipped. Since the width of them is already incorporated in the position calculations
|
||||
-- for the following syllables, they can safely be stripped from output, without losing the spaces.
|
||||
elseif syl.kind == "ignore" then
|
||||
-- These are actually syllable kinds we don't know what to do about. They are not included in the output.
|
||||
else
|
||||
local startx, starty, shakex, shakey, enterangle
|
||||
-- angle to enter from
|
||||
enterangle = math.rad((180 / lin.karaoke.n) * i - 90)
|
||||
-- position to enter from (350 pixels from (320, 50))
|
||||
startx = math.sin(enterangle)*350 + 320
|
||||
starty = linetop - math.cos(enterangle)*350
|
||||
if syl.kind == "reg" then
|
||||
shakex = (syl.left+lineofs) + math.random(-5, 5)
|
||||
shakey = linetop + math.random(-5, 5)
|
||||
elseif syl.kind == "deco" then
|
||||
shakex, shakey = syl.left+lineofs, linetop
|
||||
elseif syl.kind == "dance" then
|
||||
shakex = (syl.left+lineofs) + math.random(-5, 5)
|
||||
shakey = linetop + math.random(-5, 5)
|
||||
end
|
||||
-- origin for rotation
|
||||
local orgx = syl.left + lineofs + syl.width/2
|
||||
local orgy = linetop + syl.height/2
|
||||
-- entry effect
|
||||
local enterlin = copy_line(lin)
|
||||
enterlin.start_time = lin.start_time - 40
|
||||
enterlin.end_time = lin.start_time
|
||||
enterlin.text = string.format("{\\move(%d,%d,%d,%d)\\fr%d\\t(\\fr0)\\an7}%s", startx, starty, shakex, shakey, -math.deg(enterangle), syl.text)
|
||||
output.n = output.n + 1
|
||||
output[output.n] = enterlin
|
||||
-- main highlight effect
|
||||
local newlin = copy_line(lin)
|
||||
local hilistart, hilimid, hiliend = syl.start_time*10, (syl.start_time+syl.duration/2)*10, (syl.start_time+syl.duration)*10
|
||||
newlin.text = string.format("\\move(%d,%d,%d,%d,%d,%d)\\an7}%s", shakex, shakey, syl.left+lineofs, linetop, hilistart, hiliend, syl.text)
|
||||
newlin.layer = 1
|
||||
if syl.kind == "dance" then
|
||||
local fx = string.format("\\org(%d,%d)\\t(%d,%d,\\fr30)\\t(%d,%d,\\fr-30)\\t(%d,%d,\\3c&H0000ff&)\\t(%d,%d,\\3c&H000080&)\\t(%d,%d,\\fr0)", orgx, orgy, hilistart, hilistart+20, hilistart+20, hiliend, hilistart, hilimid, hilimid, hiliend, hiliend, hiliend+syl.duration*10)
|
||||
newlin.text = fx .. newlin.text
|
||||
else
|
||||
local fx = string.format("\\t(%d,%d,\\3c&H0000ff&)\\t(%d,%d,\\3c&H000080&)", hilistart, hilimid, hilimid, hiliend)
|
||||
newlin.text = fx .. newlin.text
|
||||
end
|
||||
local bord = copy_line(newlin)
|
||||
bord.layer = 0
|
||||
bord.text = "{" .. bord.text
|
||||
newlin.text = "{\\bord0" .. newlin.text
|
||||
output.n = output.n + 2
|
||||
output[output.n-1] = bord
|
||||