【Aegisub相关】卡拉OK模板执行环境和顺序
本頁描述了許多有關 卡拉OK模板執行器(kara-templater) 的工作方式,并且會解釋為什么許多東西起作用,而另一些不起作用。
大多數的細節你在卡拉OK模板執行器中是不需要用到的,但是如果你在某些腳本中看到了你不理解的行為,那么本頁面可能會解釋它。
注:Aegisub的代碼執行環境具體實現對應的源碼文件是kara-templater.lua,在這個文件中的第292行——function apply_templates(meta, styles, subs, templates)
function apply_templates(meta, styles, subs, templates)的具體代碼如下:
概念
有些術語和概念在本頁全篇中都有使用。這些名稱和腳本中使用的相似或者完全相同。(譯者注:在使用時需要保留英文,故翻譯內容保留重要英文)
tenv:template environment(模板環境)的縮寫, 或者 代碼執行環境。
varctx:variable context(內聯變量環境), 內聯變量存儲在的實際區域。
template:卡拉OK模板執行器(kara-templater)中最基本的 “執行單元(execution unit)” , 事實上一個模板就是一個迷你程序,這個程序由 卡拉OK模板執行器 編譯并執行。
code template:以Lua代碼塊方式行使功能的模板,但是一般情況下不會直接輸出字幕對象。(用 code 關鍵字聲明)
output template:會產生字幕行(字幕對象)的一類模板,一般以打好K值的行作為輸入。(用 template 關鍵字聲明)
code line:字幕文件中的一行,該行定義了一個code模板(code 模板)。
template line:字幕文件中的一行,該行定義了一個輸出模板(output template), 或者整個輸出模板中的一部分。 (一個 line 類輸出模板可以對應多個模板行)
class(類):一個類指的是一種類型的模板。有四種基本的模板類, once, line, syl and furi, 第一個類只對code模板有用。
modifier(修飾語):修飾語會影響模板作用的方式和作用的順序。
template text 或 text:模板的"文本" 部分,可以是code模板中的 Lua 代碼,或者是輸出模板中的模板代碼。 line 類輸出模板還有一個 pre-line text 。
啟動(Start-up)
卡拉OK模板執行器(后文均簡稱模板應用器)做的第一件事是使用 卡拉OK框架(karaskel) 來收集一些基礎的字幕文件信息。這個過程中總是會伴隨著傳遞 真(true)值給 generate_furigana (生成假名標注),它屬于karaskel.collect_head 函數,這意味著 假名標注(furigana) 的樣式會被生成,除非它們早就存在。
然后模板應用器會收集文件中的所有模板行(template line)信息。
收集,解析并編譯模板
文件中的每一行都會被檢查是否是一行模板,例如,被打上注釋并且特效欄(Effect field)填寫著 code 或者 template 的行會被作為模板行。
細節在這里并不重要。你要知道的是 特效欄關鍵字后的修飾語會作為一個參數起作用。
當遇到一個 line 類的模板行時,模板應用器首先會檢查是否有其他和這行具有一樣模板名稱的行。如果沒有,則會以該名稱新建一行,并按照給定的修飾語進行初始化。如果已經存在這樣的行, 該模板行中的文本會被加入到當前模板行中統一成一個新模板行 。最終應用的修飾語決定于后一個模板行的修飾語,而非當前行。應用模板的過程中,修飾語沒有辦法從模板中移除。特殊的是 pre-line 模板行的文本會被添加到 pre-line text (被置于所有代碼的最前面)。
不同類的模板會被分別放置到各自的 “bucket” 中,所以 line 和 syl 模板不會被一起保存。(應用模板后不會產生同類合并效果)
清除(Clean-up)
在所有模板信息都被收集后。所有不需要的行會被從字幕文件中刪除,最常見的情況是,第二次應用同一個模板時第一次生成的 fx(在Effect欄) 行會先被清除。
初始化 tenv
在開始實際應用模板之前的最后一項工作就是初始化運行環境。基本上,在所有的模板運行之前,都會被放置到 tenv。詳見 代碼執行環境 ("基本上"是指除了 line, orgline, syl 和 basesyl.)
運行 once 模板
所有的 once 類模板會被首先執行。這個過程中沒有什么激動人心的事情發生,發生的僅僅是一些額外的文件被添加到了 tenv。
循環訪問(Iterate through)卡拉OK行
字幕文件中的每個非模板行都會被瀏覽并且按順序應用上模板。
如果一行的注釋已經打勾,但是特效欄沒有寫著Karaoke,那么應用模板時這行會被跳過。
如果一行沒被打上注釋,并且特效欄寫著除了Karaoke或者空白以外的文本,它也會被跳過。
模板應用器會試圖匹配所有非模板行。
如果通過了以上幾點,剩下的每一行都會以三個步驟被應用上模板。
首先,所有的 line 類模板會試圖匹配非模板行然后再逐一在karaoke行上運行。下面會給出"模板匹配行的順序"的概念。
接下來,所有行內的音節會按順序被瀏覽,所有的 syl 類模板最終會被應用在每個音節上。
最后,會過一遍所有注音假名的音節,來嘗試將所有 furi 類模板匹配相應行,然后在注音假名上應用模板。
值得注意的是,音節和注音假名音節是會被解析并儲存的音節,而不是用multi時的虛擬音節,或是用char時的虛擬音節,并且不是一個組合。
Example 假設有三個 syl 類模板: A, B 和 C.A 是一個規則的模板,不帶有 multi 或者 char 修飾語。 B 模板含有 multi 修飾語,但是不含有 char 修飾語。 C 含有 char 和 multi 修飾語。 現在這三個模板會被應用到一行中,這行含有兩個音節(syllable)。以下是過程:音節1 被選出 模板A匹配到這行,音節1被匹配。 模板A被應用到音節1。 模板B匹配到這行,音節1被匹配。 音節1被分解為多音節標注的虛擬音節1.1 和 1.2 模板B被應用到虛擬音節1.1。 模板B被應用到虛擬音節1.2。 模板C匹配到這行。 音節1被分解為以字符為單位的虛擬音節1.a 和 1.b 音節 1.a 和 1.b 被進一步分解為 1.a1, 1.a2, 1.b1 和 1.b2。 模板C被應用到虛擬音節 1.a1。 模板C被應用到虛擬音節 1.a2。 模板C被應用到虛擬音節 1.b1。 模板C被應用到虛擬音節 1.b2。 音節2 被選出 進行和上面相似的過程。 想知道更多有關 多音節標注 和 以字符為單位的虛擬音節的內容,請看下面。如果任何一個模板在以上三個步驟中匹配到了“打好K值的行”,執行過模板后這樣的行就會被打上注釋,并且特效欄會顯示 karaoke 。
模板匹配行
模板的匹配總是以行為單位,而不是音節或其他單位。
如果模板含有 fxgroup 修飾語,那么名字和 fxgroup 名相同的行會被無視。
如果模板含有 all 修飾語,它會匹配任何行。
如果模板和某行有一樣的樣式,它會匹配到這行。(這是最常見的情況)
其他情況下模板不會匹配到行。
應用 line 類模板
待編寫(原文如此)
應用 syl 和 furi 類模板
待編寫(原文如此)
過程描述
(這部分內容的具體代碼可以在Aegisub安裝目錄下的automation/autoload/kara-templater.lua中讀到)
卡拉OK模板執行器執行的主要過程: 1. 收集頭部信息1. 找到所有的頭部信息,基本有播放分辨率(X/Y)。2. 找到所有的樣式。3. 生成對應樣式的假名標注樣式。 2. 收集模板并刪除已存在的 "fx" 行lines。 3. 初始化 tenv1. 添加 "string", "math" 和 "_G" 標記2. 添加 "tenv"自引用3. 添加 "retime" 函數4. 添加空的 "fxgroup" 表 4. 運行每一個"code once" 模板 5. 對于字幕文件中每個待處理的對話行:a. 如果特效欄以 "code" 或 "template"開始:1. 跳過行b. 否則:1. 如果特效欄不是空的,也不是 "karaoke":a. 跳過行2. 如果特效欄是空的,并且該行被打上注釋:a. 跳過行3. 用karaskel(卡拉OK框架)預處理行4. 初始化 varctx(內聯變量環境)5. 重置 tenv1. 把 "orgline" 作為輸入2. 把 "line", "syl" 和 "basesyl" 置空6. 對于每個 "line" 模板:如果樣式匹配或者作用范圍是"all":循環過程("template.loops")多次:1. 置 "tenv.j" 為循環計數器2. a. 如果模板是 code 行:1. 置 "tenv.line" 為輸入行2. 運行 code 代碼b. 否則:1. 產生輸出行作為輸入行的副本2. 置 "tenv.line" t為輸出行3. 初始化 輸出行層(output line Layer)為模板層(template Layer)4. 初始化 輸出行文本為空5. 如果模板含有 pre-line:1. 運行 pre-line 模板2. 在輸出結果上附加文本6. a. 如果模板匹配到規則的行:對于輸入行中的每個音節:1. 置 "tenv.syl" 為音節2. 為音節更新 varctx 3. 運行 line 模板4. 在輸出結果上附加文本5. 如果未設置 "notext" :a. 如果設置 "keeptags" :1. 在輸出文本上附上 "syl.text" b. 否則:1. 在輸出文本上附上 "syl.text_stripped"(剝離原標簽的文本)b. 否則:a. 如果設置了 "keeptags" :1. 在輸出文本上附上 "syl.text" b. 否則1. 在輸出文本上附上 "syl.text_stripped"7. 把輸出行的特效欄填上 "fx"8. 把輸出行整合到字幕文件中7. 對于行中每個主要的音節:對于每個 "syl" 模板:如果樣式匹配或者作用范圍是"all":如果模板不是在一個無效的fxgroup中:1. 置 "tenv.syl" 為音節2. 為音節更新 varctx 3. 如果音節的inlinefx(內聯特效)沒有匹配到對應的模板:1. 跳過音節4. 如果模板設置了 "noblank" 并且這個音節是個空格:1. 跳過音節5. 如果模板有"char"修飾:1. 建立 "charsyl" 作為音節的副本2. 置 "tenv.basesyl"(基礎音節)為當前的"tenv.syl"3. 置 "tenv.syl" 為"charsyl"(字符音節)4. 對于音節中每個 Unicode 編碼的字符:1. 對"charsyl"計算虛擬音節數 2. 為"字符音節"更新 varctx 3. 對虛擬音節繼續進行音節的處理過程 (從 5.b.7.6.)6. 如果模板有"multi"修飾:1. 建立 "hlsyl"(音節) 作為音節的副本2. 除非 "tenv.basesyl" 早就存在,否則置為 "hlsyl"3. 置 "tenv.syl" 為 "hlsyl"4. 對于音節上每個標記:1. 對"hlsyl"計算虛擬音節數2. 為"標記音節"更新 varctx 3. 對虛擬音節繼續進行音節的處理過程 (從 5.b.7.7.)7. a. 如果模板是 code 行:1. 置 "tenv.line" 為輸入行2. 運行 code 代碼b. 否則:1. 置 "tenv.line" 為輸入行2. 運行 code 代碼循環過程("template.loops")多次:1. 置 "tenv.j" 為循環計數器2. 創建輸出行3. 置輸出行的樣式為虛擬音節樣式4. 置輸出行層為模板層5. 置 "tenv.line" 為輸出行6. 運行模板7. 置輸出行文本為結果8. a. 如果設置了 "keeptags" :1. 在輸出文本上附上 "syl.text"b. 如果未設置 "keeptags" :1. 在輸出行文本上附上 "syl.text_stripped"c. 其他情況下什么都不會發生9. 置輸出行的特效欄內容為"fx"10. 把輸出行整合到字幕文件中8. 對于行中的每個假名部分:和音節處理方式相同 (5.b.7.)9. 如果有非 code 模板應用到行:1. 把輸入行置為注釋2. 置輸入行的特效欄文本為 "karaoke"3. 存儲修飾過的輸入行到字幕文件運行 code 行: 1. 編譯行文本為 Lua 函數 2. 如果編譯失敗, 報告錯誤 3. 置已編譯的函數的環境到 tenv 4. 循環過程("template.loops")多次::1. 置 "tenv.j" 為循環計數器2. 運行已編譯的函數3. 如果發生錯誤,報告它運行一行單獨的模板: 1. 置結果文本為模板 2. 如果存在 varctx:對于結果文本中的每個屬于 "$([a-zA-Z_]+)" 的字符:1. 將捕獲到的文本轉化為小寫2. a. 如果捕獲到的名稱在 varctx中:1. 替換結果文本中的這部分為 varctx中的值b. 否則:1. 警告2. 保持原文本不變 3. 對于結果文本中匹配到 "!(.-)!" 的情況:1. 附加 "結果 " 到捕獲的代碼中2. 按照Lua函數的方式編譯 捕獲到的代碼3. 如果編譯失敗,報告錯誤4. 置已編譯的函數的環境到 tenv 中5. 運行已編譯的函數a. 如果已編譯的函數產生了錯誤:1. 報告錯誤2. 在結果文本中保留了匹配到的內容b. 否則:1. 用函數運行的結果替換掉匹配到的內容總結
以上是生活随笔為你收集整理的【Aegisub相关】卡拉OK模板执行环境和顺序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BitLocker 秘钥如何获取
- 下一篇: sql中return/break/con