dotfiles/.aegisub/automation/include/a-mo/TrimHandler.moon

186 lines
6.8 KiB
Plaintext

local log
version = '1.0.5'
haveDepCtrl, DependencyControl = pcall require, 'l0.DependencyControl'
if haveDepCtrl
version = DependencyControl {
name: 'TrimHandler'
:version
description: 'A class for encoding video clips.'
author: 'torque'
url: 'https://github.com/TypesettingTools/Aegisub-Motion'
moduleName: 'a-mo.TrimHandler'
feed: 'https://raw.githubusercontent.com/TypesettingTools/Aegisub-Motion/DepCtrl/DependencyControl.json'
{
{ 'a-mo.Log', version: '1.0.0' }
}
}
log = version\requireModules!
else
log = require 'a-mo.Log'
windows = jit.os == "Windows"
class TrimHandler
@version: version
@windows: windows
existingPresets: {
"x264", "ffmpeg"
}
-- Set up encoder presets.
defaults: {
x264: '"#{encbin}" --crf 16 --tune fastdecode -i 250 --fps 23.976 --sar 1:1 --index "#{prefix}/#{index}.index" --seek #{startf} --frames #{lenf} -o "#{prefix}/#{output}[#{startf}-#{endf}].mp4" "#{inpath}/#{input}"'
ffmpeg: '"#{encbin}" -ss #{startt} -an -sn -i "#{inpath}/#{input}" -q:v 1 -vsync passthrough -frames:v #{lenf} "#{prefix}/#{output}[#{startf}-#{endf}]-%05d.jpg"'
-- avs2pipe: 'echo FFVideoSource("#{inpath}#{input}",cachefile="#{prefix}#{index}.index").trim(#{startf},#{endf}).ConvertToRGB.ImageWriter("#{prefix}/#{output}-[#{startf}-#{endf}]\\",type="png").ConvertToYV12 > "#{temp}/a-mo.encode.avs"\nmkdir "#{prefix}#{output}-[#{startf}-#{endf}]"\n"#{encbin}" video "#{temp}/a-mo.encode.avs"\ndel "#{temp}/a-mo.encode.avs"'
-- vapoursynth:
}
-- Example trimConfig:
-- trimConfig = {
-- -- The prefix is the directory the output will be written to. It
-- -- is passed through aegisub.decode_path.
-- prefix: "?video"
-- -- The name of the built in encoding preset to use. Overridden by
-- -- command if that is neither nil nor an empty string.
-- preset: "x264"
-- -- The path of the executable used to actually do the encoding.
-- -- Full path is recommended as the shell environment may be
-- -- different than expected on non-windows systems.
-- encBin: "C:\x264.exe"
-- -- A custom encoding command that can be used to override the
-- -- built-in defaults. Usable token documentation to come.
-- -- Overrides preset if that is set.
-- command: nil
-- -- Script should attempt to create prefix directory.
-- makePfix: nil
-- -- Script should attempt to log output of the encoding command.
-- writeLog: true
-- }
new: ( trimConfig ) =>
@tokens = { }
if trimConfig.command != nil
trimConfig.command = trimConfig.command\gsub "[\t \r\n]*$", ""
if trimConfig.command != ""
@command = trimConfig.command
else
@command = @defaults[trimConfig.preset]
else
@command = @defaults[trimConfig.preset]
@makePrefix = trimConfig.makePfix
@writeLog = trimConfig.writeLog
with @tokens
.temp = aegisub.decode_path "?temp"
-- For some reason, aegisub appends / to the end of ?temp but not
-- other tokens.
finalTemp = .temp\sub -1, -1
if finalTemp == '\\' or finalTemp == '/'
.temp = .temp\sub 1, -2
.encbin = trimConfig.encBin
.prefix = aegisub.decode_path trimConfig.prefix
.inpath = aegisub.decode_path "?video"
.log = aegisub.decode_path "#{.temp}/a-mo.encode.log"
getVideoName @
getVideoName = =>
with @tokens
video = aegisub.project_properties!.video_file
if video\len! == 0
log.windowError "Aegisub thinks your video is 0 frames long.\nTheoretically it should be impossible to get this error."
if video\match "^?dummy"
log.windowError "I can't encode that dummy video for you."
.input = video\gsub( "^[A-Z]:\\", "", 1 )\gsub ".+[^\\/]-[\\/]", "", 1
.index = .input\match "(.+)%.[^%.]+$"
.output = .index
calculateTrimLength: ( lineCollection ) =>
with @tokens
.startt = lineCollection.startTime / 1000
.endt = lineCollection.endTime / 1000
.lent = .endt - .startt
.startf = lineCollection.startFrame
.endf = lineCollection.endFrame - 1
.lenf = lineCollection.totalFrames
performTrim: =>
with platform = ({
[true]: {
pre: @tokens.temp
ext: ".ps1"
-- This needs to be run from cmd or it will not work.
exec: 'powershell -c iex "$(gc "%s" -en UTF8)"'
preCom: (@makePrefix and "mkdir -Force \"#{@tokens.prefix}\"; & " or "& ")
postCom: (@writeLog and " 2>&1 | Out-File #{@tokens.log} -en UTF8; if($LASTEXITCODE -ne 0) {echo \"If there is no log before this, your encoder is not a working executable or your encoding command is invalid.\" | ac -en utf8 #{@tokens.log}; exit 1}" or "") .. "; exit 0"
execFunc: ( encodeScript ) ->
-- clear out old logfile because it doesn't get overwritten
-- when certain errors occur.
if @writeLog
logFile = io.open @tokens.log, 'wb'
logFile\close! if logFile
success = os.execute encodeScript
if @writeLog and not success
logFile = io.open @tokens.log, 'r'
unless logFile
log.windowError "Could not read log file #{@tokens.log}.\nSomething has gone horribly wrong."
encodeLog = logFile\read '*a'
logFile\close!
log.warn "\nEncoding error:"
log.warn encodeLog
log.windowError "Encoding failed. Log has been printed to progress window."
elseif not success
log.windowError "Encoding seems to have failed but you didn't write a log file."
}
[false]: {
pre: @tokens.temp
ext: ".sh"
exec: 'sh "%s"'
preCom: @makePrefix and "mkdir -p \"#{@tokens.prefix}\"\n" or ""
postCom: " 2>&1; if [[ $? -ne 0 ]]; then echo \"If there is no log before this, your encoder is not a working executable or your encoding command is invalid.\"; false; fi"
execFunc: ( encodeScript ) ->
logFile = io.popen encodeScript, 'r'
encodeLog = logFile\read '*a'
-- When closing a file handle created with io.popen,
-- file:close returns the same values returned by
-- os.execute.
success = logFile\close!
unless success
log.warn "\nEncoding error:"
log.warn encodeLog
log.windowError "Encoding failed. Log has been printed to progress window."
}
})[windows]
-- check encoder binary exists
encoder = io.open @tokens.encbin, "rb"
unless encoder
log.windowError "Encoding binary (#{@tokens.encbin}) does not appear to exist."
encoder\close!
encodeScript = aegisub.decode_path "#{.pre}/a-mo.encode#{.ext}"
encodeScriptFile = io.open encodeScript, "w+"
unless encodeScriptFile
log.windowError "Encoding script could not be written.\nSomething is wrong with your temp dir (#{.pre})."
encodeString = .preCom .. @command\gsub( "#{(.-)}", ( token ) -> @tokens[token] ) .. .postCom
if windows
encodeString = encodeString\gsub "`", "``"
log.debug encodeString
encodeScriptFile\write encodeString
encodeScriptFile\close!
.execFunc .exec\format encodeScript
if haveDepCtrl
return version\register TrimHandler
else
return TrimHandler