186 lines
6.8 KiB
Plaintext
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
|