2020-08-21 04:19:06 +00:00
|
|
|
|
local mpopt = require('mp.options')
|
2020-10-02 08:27:40 +00:00
|
|
|
|
local utils = require('mp.utils')
|
2020-08-21 04:19:06 +00:00
|
|
|
|
|
|
|
|
|
-- Options can be changed here or in a separate config file.
|
|
|
|
|
-- Config path: ~/.config/mpv/script-opts/videoclip.conf
|
|
|
|
|
local config = {
|
2020-08-27 07:12:30 +00:00
|
|
|
|
-- absolute paths
|
2020-09-19 23:47:10 +00:00
|
|
|
|
-- relative paths (e.g. ~ for home dir) do NOT work.
|
2020-10-02 07:32:25 +00:00
|
|
|
|
video_folder_path = string.format('%s/Videos/', os.getenv("HOME") or os.getenv('USERPROFILE')),
|
|
|
|
|
audio_folder_path = string.format('%s/Music/', os.getenv("HOME") or os.getenv('USERPROFILE')),
|
2020-08-21 04:47:46 +00:00
|
|
|
|
font_size = 24,
|
2020-08-21 04:19:06 +00:00
|
|
|
|
audio_bitrate = '32k',
|
|
|
|
|
-- The range of the CRF scale is 0–51, where 0 is lossless,
|
|
|
|
|
-- 23 is the default, and 51 is worst quality possible.
|
2020-09-20 00:43:41 +00:00
|
|
|
|
-- Insane values like 9999 still work but produce the worst quality.
|
2020-08-21 04:19:06 +00:00
|
|
|
|
video_quality = 23,
|
|
|
|
|
-- Use the slowest preset that you have patience for.
|
|
|
|
|
-- https://trac.ffmpeg.org/wiki/Encode/H.264
|
|
|
|
|
preset = 'faster',
|
|
|
|
|
video_width = -2,
|
|
|
|
|
video_height = 480,
|
2020-10-23 13:17:08 +00:00
|
|
|
|
video_format = 'mp4', -- webm or mp4
|
|
|
|
|
mute_audio = false,
|
2020-08-21 04:19:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mpopt.read_options(config, 'videoclip')
|
2020-08-26 04:29:22 +00:00
|
|
|
|
local menu
|
2020-10-23 13:33:10 +00:00
|
|
|
|
local pref_menu
|
2020-09-19 23:46:12 +00:00
|
|
|
|
local encoder
|
2020-08-26 04:29:22 +00:00
|
|
|
|
local OSD
|
|
|
|
|
local Timings
|
2020-08-21 04:19:06 +00:00
|
|
|
|
|
2020-09-24 18:16:14 +00:00
|
|
|
|
local allowed_presets = {
|
2020-09-20 00:44:35 +00:00
|
|
|
|
ultrafast = true,
|
|
|
|
|
superfast = true,
|
|
|
|
|
veryfast = true,
|
|
|
|
|
faster = true,
|
|
|
|
|
fast = true,
|
|
|
|
|
medium = true,
|
|
|
|
|
slow = true,
|
|
|
|
|
slower = true,
|
|
|
|
|
veryslow = true,
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-21 04:19:06 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- utility functions
|
|
|
|
|
|
2020-08-27 07:13:48 +00:00
|
|
|
|
function string:endswith(suffix)
|
2020-09-24 18:00:33 +00:00
|
|
|
|
return suffix == "" or self:sub(-#suffix) == suffix
|
2020-08-27 07:13:48 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-08-26 04:29:22 +00:00
|
|
|
|
local function remove_extension(filename)
|
2020-09-19 23:47:10 +00:00
|
|
|
|
return filename:gsub('%.%w+$', '')
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-08-26 04:29:22 +00:00
|
|
|
|
local function remove_text_in_brackets(str)
|
2020-09-19 23:47:10 +00:00
|
|
|
|
return str:gsub('%b[]', '')
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-08-26 04:29:22 +00:00
|
|
|
|
local function remove_special_characters(str)
|
2020-09-19 23:47:10 +00:00
|
|
|
|
return str:gsub('[%c%p%s]', '')
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-09-03 00:13:17 +00:00
|
|
|
|
local function human_readable_time(seconds)
|
|
|
|
|
if type(seconds) ~= 'number' or seconds < 0 then
|
2020-08-21 04:19:06 +00:00
|
|
|
|
return 'empty'
|
|
|
|
|
end
|
|
|
|
|
|
2020-09-03 00:13:17 +00:00
|
|
|
|
local parts = {}
|
2020-08-21 04:19:06 +00:00
|
|
|
|
|
2020-09-19 23:47:10 +00:00
|
|
|
|
parts.h = math.floor(seconds / 3600)
|
|
|
|
|
parts.m = math.floor(seconds / 60) % 60
|
|
|
|
|
parts.s = math.floor(seconds % 60)
|
2020-09-03 00:13:17 +00:00
|
|
|
|
parts.ms = math.floor((seconds * 1000) % 1000)
|
|
|
|
|
|
|
|
|
|
local ret = string.format("%02dm%02ds%03dms", parts.m, parts.s, parts.ms)
|
|
|
|
|
|
|
|
|
|
if parts.h > 0 then
|
|
|
|
|
ret = string.format('%dh%s', parts.h, ret)
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-09-03 00:13:17 +00:00
|
|
|
|
return ret
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-08-26 04:29:22 +00:00
|
|
|
|
local function construct_filename()
|
2020-08-21 04:19:06 +00:00
|
|
|
|
local filename = mp.get_property("filename") -- filename without path
|
|
|
|
|
|
|
|
|
|
filename = remove_extension(filename)
|
|
|
|
|
filename = remove_text_in_brackets(filename)
|
|
|
|
|
filename = remove_special_characters(filename)
|
|
|
|
|
|
|
|
|
|
filename = string.format(
|
2020-09-13 20:02:45 +00:00
|
|
|
|
'%s_(%s-%s)',
|
|
|
|
|
filename,
|
|
|
|
|
human_readable_time(menu.timings['start']),
|
|
|
|
|
human_readable_time(menu.timings['end'])
|
2020-08-21 04:19:06 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return filename
|
|
|
|
|
end
|
|
|
|
|
|
2020-09-19 23:46:12 +00:00
|
|
|
|
local function subprocess(args)
|
|
|
|
|
return mp.command_native {
|
2020-08-27 03:29:23 +00:00
|
|
|
|
name = "subprocess",
|
|
|
|
|
playback_only = false,
|
|
|
|
|
capture_stdout = true,
|
2020-09-19 23:46:12 +00:00
|
|
|
|
capture_stderr = true,
|
2020-08-27 03:29:23 +00:00
|
|
|
|
args = args
|
|
|
|
|
}
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:19:36 +00:00
|
|
|
|
local function force_resolution(width, height, clip_fn, ...)
|
|
|
|
|
local cached_prefs = {
|
|
|
|
|
video_width = config.video_width,
|
|
|
|
|
video_height = config.video_height,
|
|
|
|
|
}
|
|
|
|
|
config.video_width = width
|
|
|
|
|
config.video_height = height
|
|
|
|
|
clip_fn(...)
|
|
|
|
|
config.video_width = cached_prefs.video_width
|
|
|
|
|
config.video_height = cached_prefs.video_height
|
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:17:08 +00:00
|
|
|
|
local function set_video_settings()
|
|
|
|
|
if config.video_format == 'mp4' then
|
|
|
|
|
config.video_codec = 'libx264'
|
|
|
|
|
config.video_extension = '.mp4'
|
|
|
|
|
else
|
|
|
|
|
config.video_codec = 'libvpx-vp9'
|
|
|
|
|
config.video_extension = '.webm'
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2020-09-19 23:46:12 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- provides interface for creating audio/video clips
|
|
|
|
|
|
|
|
|
|
encoder = {}
|
|
|
|
|
|
2020-10-23 13:26:07 +00:00
|
|
|
|
encoder.create_videoclip = function(clip_filename)
|
2020-10-23 13:22:43 +00:00
|
|
|
|
local clip_path = utils.join_path(config.video_folder_path, clip_filename .. config.video_extension)
|
2020-09-19 23:46:12 +00:00
|
|
|
|
return subprocess {
|
|
|
|
|
'mpv',
|
|
|
|
|
mp.get_property('path'),
|
2020-09-26 22:35:36 +00:00
|
|
|
|
'--loop-file=no',
|
2020-09-19 23:46:12 +00:00
|
|
|
|
'--no-ocopy-metadata',
|
|
|
|
|
'--no-sub',
|
2020-09-26 22:33:32 +00:00
|
|
|
|
'--audio-channels=2',
|
2020-09-19 23:46:12 +00:00
|
|
|
|
'--oac=libopus',
|
|
|
|
|
'--oacopts-add=vbr=on',
|
|
|
|
|
'--oacopts-add=application=voip',
|
|
|
|
|
'--oacopts-add=compression_level=10',
|
|
|
|
|
table.concat { '--start=', menu.timings['start'] },
|
|
|
|
|
table.concat { '--end=', menu.timings['end'] },
|
2020-10-23 13:22:43 +00:00
|
|
|
|
table.concat { '--ovc=', config.video_codec },
|
2020-10-23 13:26:07 +00:00
|
|
|
|
table.concat { '--aid=', config.mute_audio and 'no' or mp.get_property("aid") }, -- track number
|
2020-10-16 01:42:55 +00:00
|
|
|
|
table.concat { '--volume=', mp.get_property('volume') },
|
2020-09-19 23:46:12 +00:00
|
|
|
|
table.concat { '--oacopts-add=b=', config.audio_bitrate },
|
|
|
|
|
table.concat { '--ovcopts-add=crf=', config.video_quality },
|
|
|
|
|
table.concat { '--ovcopts-add=preset=', config.preset },
|
|
|
|
|
table.concat { '--vf-add=scale=', config.video_width, ':', config.video_height },
|
|
|
|
|
table.concat { '-o=', clip_path }
|
2020-08-21 04:19:06 +00:00
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
2020-09-19 23:46:12 +00:00
|
|
|
|
encoder.create_audioclip = function(clip_filename)
|
2020-10-02 08:27:40 +00:00
|
|
|
|
local clip_path = utils.join_path(config.audio_folder_path, clip_filename .. '.ogg')
|
2020-09-19 23:46:12 +00:00
|
|
|
|
return subprocess {
|
|
|
|
|
'mpv',
|
|
|
|
|
mp.get_property('path'),
|
|
|
|
|
'--loop-file=no',
|
|
|
|
|
'--no-ocopy-metadata',
|
|
|
|
|
'--no-sub',
|
2020-09-26 22:33:32 +00:00
|
|
|
|
'--audio-channels=2',
|
2020-09-26 22:35:36 +00:00
|
|
|
|
'--video=no',
|
2020-09-19 23:46:12 +00:00
|
|
|
|
'--oac=libopus',
|
|
|
|
|
'--oacopts-add=vbr=on',
|
|
|
|
|
'--oacopts-add=application=voip',
|
|
|
|
|
'--oacopts-add=compression_level=10',
|
|
|
|
|
table.concat { '--start=', menu.timings['start'] },
|
|
|
|
|
table.concat { '--end=', menu.timings['end'] },
|
2020-10-16 01:42:55 +00:00
|
|
|
|
table.concat { '--volume=', mp.get_property('volume') },
|
2020-09-19 23:46:12 +00:00
|
|
|
|
table.concat { '--aid=', mp.get_property("aid") }, -- track number
|
|
|
|
|
table.concat { '--oacopts-add=b=', config.audio_bitrate },
|
|
|
|
|
table.concat { '-o=', clip_path }
|
2020-08-22 00:44:37 +00:00
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
2020-09-19 23:46:12 +00:00
|
|
|
|
encoder.create_clip = function(clip_type)
|
2020-10-23 13:32:33 +00:00
|
|
|
|
menu:close();
|
2020-09-19 23:46:12 +00:00
|
|
|
|
if clip_type == nil then
|
|
|
|
|
return
|
|
|
|
|
end
|
2020-08-22 00:44:37 +00:00
|
|
|
|
|
2020-08-26 04:29:22 +00:00
|
|
|
|
if not menu.timings:validate() then
|
2020-08-22 00:44:37 +00:00
|
|
|
|
mp.osd_message("Wrong timings. Aborting.", 2)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local clip_filename = construct_filename()
|
2020-08-27 03:29:23 +00:00
|
|
|
|
mp.osd_message("Please wait...", 9999)
|
|
|
|
|
|
|
|
|
|
local ret
|
2020-08-27 07:12:30 +00:00
|
|
|
|
local location
|
2020-08-27 03:29:23 +00:00
|
|
|
|
|
2020-10-23 13:26:07 +00:00
|
|
|
|
if clip_type == 'video' then
|
2020-08-27 07:12:30 +00:00
|
|
|
|
location = config.video_folder_path
|
2020-10-23 13:26:07 +00:00
|
|
|
|
ret = encoder.create_videoclip(clip_filename)
|
2020-10-23 07:26:32 +00:00
|
|
|
|
else
|
2020-08-27 07:12:30 +00:00
|
|
|
|
location = config.audio_folder_path
|
2020-09-19 23:46:12 +00:00
|
|
|
|
ret = encoder.create_audioclip(clip_filename)
|
2020-08-27 03:29:23 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-09-20 01:11:33 +00:00
|
|
|
|
if ret.status ~= 0 or string.match(ret.stdout, "could not open") then
|
|
|
|
|
mp.osd_message(string.format("Error: couldn't create the clip.\nDoes %s exist?", location), 5)
|
2020-09-20 00:21:39 +00:00
|
|
|
|
else
|
|
|
|
|
mp.osd_message(string.format("Clip saved to %s.", location), 2)
|
2020-08-22 00:44:37 +00:00
|
|
|
|
end
|
2020-09-28 10:40:07 +00:00
|
|
|
|
menu.timings:reset()
|
2020-08-22 00:44:37 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:10:29 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- Menu interface
|
|
|
|
|
|
|
|
|
|
local Menu = {}
|
|
|
|
|
Menu.__index = Menu
|
|
|
|
|
|
|
|
|
|
function Menu:new(parent)
|
|
|
|
|
local o = {
|
|
|
|
|
parent = parent,
|
|
|
|
|
overlay = parent and parent.overlay or mp.create_osd_overlay('ass-events'),
|
|
|
|
|
keybinds = { },
|
|
|
|
|
}
|
|
|
|
|
return setmetatable(o, self)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Menu:overlay_draw(text)
|
|
|
|
|
self.overlay.data = text
|
|
|
|
|
self.overlay:update()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Menu:open()
|
|
|
|
|
if self.parent then
|
|
|
|
|
self.parent:close()
|
|
|
|
|
end
|
|
|
|
|
for _, val in pairs(self.keybinds) do
|
|
|
|
|
mp.add_key_binding(val.key, val.key, val.fn)
|
|
|
|
|
end
|
|
|
|
|
self:update()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Menu:close()
|
|
|
|
|
for _, val in pairs(self.keybinds) do
|
|
|
|
|
mp.remove_key_binding(val.key)
|
|
|
|
|
end
|
|
|
|
|
if self.parent then
|
|
|
|
|
self.parent:open()
|
|
|
|
|
else
|
|
|
|
|
self.overlay:remove()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Menu:update()
|
|
|
|
|
local osd = OSD:new():size(config.font_size):align(4)
|
|
|
|
|
osd:append('Dummy menu.'):newline()
|
|
|
|
|
self:overlay_draw(osd:get_text())
|
|
|
|
|
end
|
|
|
|
|
|
2020-08-21 04:19:06 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- main menu
|
|
|
|
|
|
2020-10-23 13:32:33 +00:00
|
|
|
|
menu = Menu:new()
|
2020-09-20 00:01:38 +00:00
|
|
|
|
|
2020-08-21 04:19:06 +00:00
|
|
|
|
menu.keybinds = {
|
2020-10-23 13:32:33 +00:00
|
|
|
|
{ key = 's', fn = function() menu:set_time('start') end },
|
|
|
|
|
{ key = 'e', fn = function() menu:set_time('end') end },
|
|
|
|
|
{ key = 'S', fn = function() menu:set_time_sub('start') end },
|
|
|
|
|
{ key = 'E', fn = function() menu:set_time_sub('end') end },
|
|
|
|
|
{ key = 'r', fn = function() menu:reset_timings() end },
|
2020-09-28 10:40:07 +00:00
|
|
|
|
{ key = 'c', fn = function() encoder.create_clip('video') end },
|
2020-10-23 13:32:33 +00:00
|
|
|
|
{ key = 'C', fn = function() force_resolution(1920, -2, encoder.create_clip, 'video') end },
|
2020-09-28 10:40:07 +00:00
|
|
|
|
{ key = 'a', fn = function() encoder.create_clip('audio') end },
|
2020-10-23 13:32:33 +00:00
|
|
|
|
{ key = 'p', fn = function() pref_menu:open() end },
|
2020-08-21 04:19:06 +00:00
|
|
|
|
{ key = 'o', fn = function() mp.commandv('run', 'xdg-open', 'https://streamable.com/') end },
|
2020-10-23 13:32:33 +00:00
|
|
|
|
{ key = 'ESC', fn = function() menu:close() end },
|
2020-08-21 04:19:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-23 13:32:33 +00:00
|
|
|
|
function menu:set_time(property)
|
|
|
|
|
self.timings[property] = mp.get_property_number('time-pos')
|
|
|
|
|
self:update()
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:32:33 +00:00
|
|
|
|
function menu:set_time_sub(property)
|
2020-08-21 04:19:06 +00:00
|
|
|
|
local sub_delay = mp.get_property_native("sub-delay")
|
|
|
|
|
local time_pos = mp.get_property_number(string.format("sub-%s", property))
|
|
|
|
|
|
|
|
|
|
if time_pos == nil then
|
2020-09-06 16:01:32 +00:00
|
|
|
|
mp.osd_message("Warning: No subtitles visible.", 2)
|
2020-08-21 04:19:06 +00:00
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:32:33 +00:00
|
|
|
|
self.timings[property] = time_pos + sub_delay
|
|
|
|
|
self:update()
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:32:33 +00:00
|
|
|
|
function menu:reset_timings()
|
|
|
|
|
self.timings = Timings:new()
|
|
|
|
|
self:update()
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:32:33 +00:00
|
|
|
|
menu.open = function()
|
|
|
|
|
menu.timings = menu.timings or Timings:new()
|
|
|
|
|
Menu.open(menu)
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:32:33 +00:00
|
|
|
|
function menu:update()
|
|
|
|
|
local osd = OSD:new():size(config.font_size):align(4)
|
|
|
|
|
osd:bold('Clip creator'):newline()
|
|
|
|
|
osd:tab():bold('Start time: '):append(human_readable_time(self.timings['start'])):newline()
|
|
|
|
|
osd:tab():bold('End time: '):append(human_readable_time(self.timings['end'])):newline()
|
|
|
|
|
osd:bold('Timings: '):italics('(+shift use sub timings)'):newline()
|
|
|
|
|
osd:tab():bold('s: '):append('Set start'):newline()
|
|
|
|
|
osd:tab():bold('e: '):append('Set end'):newline()
|
|
|
|
|
osd:tab():bold('r: '):append('Reset'):newline()
|
|
|
|
|
osd:bold('Create clip: '):italics('(+shift to force fullHD preset)'):newline()
|
|
|
|
|
osd:tab():bold('c: '):append('video clip'):newline()
|
|
|
|
|
osd:tab():bold('a: '):append('audio clip'):newline()
|
|
|
|
|
osd:bold('Options: '):newline()
|
|
|
|
|
osd:tab():bold('p: '):append('Open preferences'):newline()
|
|
|
|
|
osd:tab():bold('o: '):append('Open streamable.com'):newline()
|
|
|
|
|
osd:tab():bold('ESC: '):append('Close'):newline()
|
|
|
|
|
|
|
|
|
|
self:overlay_draw(osd:get_text())
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:33:10 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- Preferences
|
|
|
|
|
|
|
|
|
|
pref_menu = Menu:new(main_menu)
|
|
|
|
|
|
|
|
|
|
pref_menu.keybinds = {
|
|
|
|
|
{ key = 'f', fn = function() pref_menu:toggle_video_format() end },
|
|
|
|
|
{ key = 'm', fn = function() pref_menu:toggle_mute_audio() end },
|
|
|
|
|
{ key = 'ESC', fn = function() pref_menu:close() end },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function pref_menu:update()
|
|
|
|
|
local osd = OSD:new():size(config.font_size):align(4)
|
|
|
|
|
osd:bold('Preferences'):newline()
|
|
|
|
|
osd:bold('Video format: '):append(config.video_format):newline()
|
|
|
|
|
osd:bold('Mute audio: '):append(config.mute_audio and 'yes' or 'no'):newline()
|
|
|
|
|
osd:newline()
|
|
|
|
|
osd:bold('Bindings:'):newline()
|
|
|
|
|
osd:tab():bold('f: '):append('Toggle video format'):newline()
|
|
|
|
|
osd:tab():bold('m: '):append('Toggle silent video clips'):newline()
|
|
|
|
|
|
|
|
|
|
self:overlay_draw(osd:get_text())
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function pref_menu:toggle_video_format()
|
|
|
|
|
config.video_format = config.video_format == 'mp4' and 'webm' or 'mp4'
|
|
|
|
|
set_video_settings()
|
|
|
|
|
self:update()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function pref_menu:toggle_mute_audio()
|
|
|
|
|
config.mute_audio = not config.mute_audio
|
|
|
|
|
self:update()
|
|
|
|
|
end
|
|
|
|
|
|
2020-08-21 04:19:06 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- Helper class for styling OSD messages
|
2020-09-06 15:51:52 +00:00
|
|
|
|
-- http://docs.aegisub.org/3.2/ASS_Tags/
|
2020-08-21 04:19:06 +00:00
|
|
|
|
|
|
|
|
|
OSD = {}
|
|
|
|
|
OSD.__index = OSD
|
|
|
|
|
|
|
|
|
|
function OSD:new()
|
2020-09-25 19:24:07 +00:00
|
|
|
|
return setmetatable({ text = {} }, self)
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function OSD:append(s)
|
2020-09-25 19:24:07 +00:00
|
|
|
|
table.insert(self.text, s)
|
2020-08-21 04:19:06 +00:00
|
|
|
|
return self
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function OSD:bold(s)
|
2020-09-20 00:02:51 +00:00
|
|
|
|
return self:append(string.format([[{\b1}%s{\b0}]], s))
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-09-27 23:54:17 +00:00
|
|
|
|
function OSD:italics(s)
|
|
|
|
|
return self:append('{\\i1}'):append(s):append('{\\i0}')
|
|
|
|
|
end
|
|
|
|
|
|
2020-08-21 04:19:06 +00:00
|
|
|
|
function OSD:newline()
|
2020-09-20 00:02:51 +00:00
|
|
|
|
return self:append([[\N]])
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function OSD:tab()
|
2020-09-20 00:02:51 +00:00
|
|
|
|
return self:append([[\h\h\h\h]])
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function OSD:size(size)
|
2020-09-20 00:02:51 +00:00
|
|
|
|
return self:append(string.format([[{\fs%s}]], size))
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-09-06 15:51:36 +00:00
|
|
|
|
function OSD:align(number)
|
2020-09-20 00:02:51 +00:00
|
|
|
|
return self:append(string.format([[{\an%s}]], number))
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-09-25 19:24:07 +00:00
|
|
|
|
function OSD:get_text()
|
|
|
|
|
return table.concat(self.text)
|
|
|
|
|
end
|
|
|
|
|
|
2020-08-21 04:19:06 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- Timings class
|
|
|
|
|
|
|
|
|
|
Timings = {
|
|
|
|
|
['start'] = -1,
|
|
|
|
|
['end'] = -1,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Timings:new(o)
|
|
|
|
|
o = o or {}
|
|
|
|
|
setmetatable(o, self)
|
|
|
|
|
self.__index = self
|
|
|
|
|
return o
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Timings:reset()
|
|
|
|
|
self['start'] = -1
|
2020-09-19 23:47:10 +00:00
|
|
|
|
self['end'] = -1
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Timings:validate()
|
2020-09-06 12:58:47 +00:00
|
|
|
|
return self['start'] >= 0 and self['start'] < self['end']
|
2020-08-21 04:19:06 +00:00
|
|
|
|
end
|
|
|
|
|
|
2020-08-27 07:13:48 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- Validate config
|
|
|
|
|
|
2020-09-20 00:23:19 +00:00
|
|
|
|
if not config.audio_bitrate:endswith('k') then
|
|
|
|
|
config.audio_bitrate = config.audio_bitrate .. 'k'
|
|
|
|
|
end
|
|
|
|
|
|
2020-09-24 18:16:14 +00:00
|
|
|
|
if not allowed_presets[config.preset] then
|
2020-09-20 00:44:35 +00:00
|
|
|
|
config.preset = 'faster'
|
|
|
|
|
end
|
|
|
|
|
|
2020-10-23 13:17:08 +00:00
|
|
|
|
set_video_settings()
|
|
|
|
|
|
2020-08-21 04:19:06 +00:00
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
-- Finally, set an 'entry point' in mpv
|
|
|
|
|
|
2020-08-31 19:45:35 +00:00
|
|
|
|
mp.add_key_binding('c', 'videoclip-menu-open', menu.open)
|