From 275b74ab4f23e2ddf40c4d4bb411a00d116aee8c Mon Sep 17 00:00:00 2001 From: yuzu-eva Date: Fri, 23 Dec 2022 23:48:27 +0100 Subject: added mpv scripts --- .config/mpv/input.conf | 23 ++ .config/mpv/script-opts/crop.conf | 34 +++ .config/mpv/script-opts/encode_webm.conf | 39 +++ .config/mpv/scripts/crop.lua | 434 +++++++++++++++++++++++++++++++ .config/mpv/scripts/encode.lua | 315 ++++++++++++++++++++++ 5 files changed, 845 insertions(+) create mode 100644 .config/mpv/input.conf create mode 100644 .config/mpv/script-opts/crop.conf create mode 100644 .config/mpv/script-opts/encode_webm.conf create mode 100644 .config/mpv/scripts/crop.lua create mode 100644 .config/mpv/scripts/encode.lua (limited to '.config/mpv') diff --git a/.config/mpv/input.conf b/.config/mpv/input.conf new file mode 100644 index 0000000..396711e --- /dev/null +++ b/.config/mpv/input.conf @@ -0,0 +1,23 @@ +# crop.lua +# ========== +# start cropping +c script-message-to crop start-crop hard +alt+c script-message-to crop start-crop soft +# delogo mode can be used like so +l script-message-to crop start-crop delogo +# remove the crop +d vf del -1 + +# or use the ready-made "toggle" binding +C script-message-to crop toggle-crop hard + +# remove the soft zoom +0 set video-pan-x 0; set video-pan-y 0; set video-zoom 0 + +# encode.lua +# ============ +# use default profile (makes vp8 webms) +E script-message-to encode set-timestamp + +# use webm profile +e script-message-to encode set-timestamp encode_webm diff --git a/.config/mpv/script-opts/crop.conf b/.config/mpv/script-opts/crop.conf new file mode 100644 index 0000000..9f75cdf --- /dev/null +++ b/.config/mpv/script-opts/crop.conf @@ -0,0 +1,34 @@ +# default mode to be used if not specified in the script-message +# can be hard, soft or delogo +# in hard mode, a crop filter is applied to the video +# in soft mode, video-zoom, video-pan-x and video-pan-y are modified to simulate the cropping +# in delogo mode, the delogo filter is applied to the selected are +# hard mode interacts nicely with encode.lua, soft mode does not +mode=hard + +draw_crosshair=yes +draw_text=yes +draw_shade=yes +draw_frame=yes +frame_border_width=2 +frame_border_color=EEEEEE +# hexadecimal: 00 is opaque, FF is transparent +shade_opacity=77 +mouse_support=yes + +# movement is defined in pixels in the window +# which explains the mismatch with the text (in video space) +coarse_movement=30 +left_coarse=LEFT +right_coarse=RIGHT +up_coarse=UP +down_coarse=DOWN +fine_movement=1 +left_fine=ALT+LEFT +right_fine=ALT+RIGHT +up_fine=ALT+UP +down_fine=ALT+DOWN + +# these two options accept comma separated list of keys +accept=ENTER,MOUSE_BTN0 +cancel=ESC diff --git a/.config/mpv/script-opts/encode_webm.conf b/.config/mpv/script-opts/encode_webm.conf new file mode 100644 index 0000000..06cdc34 --- /dev/null +++ b/.config/mpv/script-opts/encode_webm.conf @@ -0,0 +1,39 @@ +# if yes, only encode the currently active tracks +# for example, mute the player / hide the subtitles if you don't want audio / subs to be part of the extract +only_active_tracks=no + +# whether to preserve some of the applied filters (crop, rotate, flip and mirror) into the extract +# this is pretty useful in combination with crop.lua +# note that you cannot copy video streams and apply filters at the same time +preserve_filters=yes + +# apply another filter after the ones from the previous option if any +# can be used to limit the resolution of the output, for example with +# append_filter=scale=2*trunc(iw/max(1\,sqrt((iw*ih)/(960*540)))/2):-2 +append_filter= + +# additional parameters passed to ffmpeg +codec=-c:a libvorbis -crf 1 -b:v 1M + +# format of the output filename +# Does basic interpolation on the following variables: $f, $x, $t, $s, $e, $d, $p, $n which respectively represent +# input filename, input extension, title, start timestamp, end timestamp, duration, profile name and an incrementing number in case of conflicts +# if the extension is not among the recognized ones, it will default to mkv +output_format=$f_$n.webm + +# the directory in which to create the extract +# empty means the same directory as the input file +# relative paths are relative to mpv's working directory, absolute ones work like you would expect +output_directory=~/vids/ + +# if yes, the ffmpeg process will run detached from mpv and we won't know if it succeeded or not +# if no, we know the result of calling ffmpeg, but we can only encode one extract at a time and mpv will block on exit +detached=yes + +# executable to run when encoding (or its full path if not in PATH) +# for example, this can be used with a wrapper script that calls ffmpeg and triggers a notification when finished +# note that the executable gets the ffmpeg arguments as-is, and is expected to call ffmpeg itself +ffmpeg_command=ffmpeg + +# if yes, print the ffmpeg call before executing it +print=yes diff --git a/.config/mpv/scripts/crop.lua b/.config/mpv/scripts/crop.lua new file mode 100644 index 0000000..adbfaa3 --- /dev/null +++ b/.config/mpv/scripts/crop.lua @@ -0,0 +1,434 @@ +local opts = { + mode = "hard", -- can be "hard" or "soft". If hard, apply a crop filter, if soft zoom + pan. Or a bonus "delogo" mode + draw_shade = true, + shade_opacity = "77", + draw_frame = false, + frame_border_width = 2, + frame_border_color = "EEEEEE", + draw_crosshair = true, + draw_text = true, + mouse_support = true, + coarse_movement = 30, + left_coarse = "LEFT", + right_coarse = "RIGHT", + up_coarse = "UP", + down_coarse = "DOWN", + fine_movement = 1, + left_fine = "ALT+LEFT", + right_fine = "ALT+RIGHT", + up_fine = "ALT+UP", + down_fine = "ALT+DOWN", + accept = "ENTER,MOUSE_BTN0", + cancel = "ESC", +} +(require 'mp.options').read_options(opts) + +function split(input) + local ret = {} + for str in string.gmatch(input, "([^,]+)") do + ret[#ret + 1] = str + end + return ret +end +local msg = require 'mp.msg' + +opts.accept = split(opts.accept) +opts.cancel = split(opts.cancel) +function mode_ok(mode) + return mode == "soft" or mode == "hard" or mode == "delogo" +end +if not mode_ok(opts.mode) then + msg.error("Invalid mode value: " .. opts.mode) + return +end + +local assdraw = require 'mp.assdraw' +local active = false +local active_mode = "" -- same possible values as opts.mode +local rect_centered = false +local rect_keepaspect = false +local needs_drawing = false +local crop_first_corner = nil -- in normalized video space +local crop_cursor = { + x = 0, + y = 0 +} + +function redraw() + needs_drawing = true +end + +function rect_from_two_points(p1, p2, centered, ratio) + local c1 = {p1.x, p1.y} + local c2 = {p2.x, p2.y} + if ratio then + -- adjust position of p2, such + if math.abs(c2[1] - c1[1]) < ratio * math.abs(c2[2] - c1[2]) then + local is_left = c2[1] < c1[1] and -1 or 1 + c2[1] = c1[1] + is_left * math.abs(c2[2] - c1[2]) * ratio + else + local is_up = c2[2] < c1[2] and -1 or 1 + c2[2] = c1[2] + is_up * math.abs(c2[1] - c1[1]) / ratio + end + end + if centered then + -- p1 is center => convert it into corner + c1[1] = c1[1] - (c2[1] - c1[1]) + c1[2] = c1[2] - (c2[2] - c1[2]) + end + -- sort corners + if c1[1] > c2[1] then c1[1], c2[1] = c2[1], c1[1] end + if c1[2] > c2[2] then c1[2], c2[2] = c2[2], c1[2] end + return { x = c1[1], y = c1[2] }, { x = c2[1], y = c2[2] } +end + +function clamp(low, value, high) + if value <= low then + return low + elseif value >= high then + return high + else + return value + end +end + +function clamp_point(top_left, point, bottom_right) + return { + x = clamp(top_left.x, point.x, bottom_right.x), + y = clamp(top_left.y, point.y, bottom_right.y) + } +end + +function screen_to_video_norm(point, dim) + return { + x = (point.x - dim.ml) / (dim.w - dim.ml - dim.mr), + y = (point.y - dim.mt) / (dim.h - dim.mt - dim.mb) + } +end + +function video_norm_to_screen(point, dim) + return { + x = math.floor(point.x * (dim.w - dim.ml - dim.mr) + dim.ml + 0.5), + y = math.floor(point.y * (dim.h - dim.mt - dim.mb) + dim.mt + 0.5) + } +end + +function draw_shade(ass, unshaded, window) + ass:new_event() + ass:pos(0, 0) + ass:append("{\\an7}") + ass:append("{\\bord0}") + ass:append("{\\shad0}") + ass:append("{\\c&H000000&}") + ass:append("{\\1a&H" .. opts.shade_opacity .. "}") + ass:append("{\\2a&HFF}") + ass:append("{\\3a&HFF}") + ass:append("{\\4a&HFF}") + local c1, c2 = unshaded.top_left, unshaded.bottom_right + local v = window + -- c1.x c2.x + -- +-----+------------+ + -- | | ur | + -- c1.y| ul +-------+----+ + -- | | | | + -- c2.y+-----+-------+ lr | + -- | ll | | + -- +-------------+----+ + ass:draw_start() + ass:rect_cw(v.top_left.x, v.top_left.y, c1.x, c2.y) -- ul + ass:rect_cw(c1.x, v.top_left.y, v.bottom_right.x, c1.y) -- ur + ass:rect_cw(v.top_left.x, c2.y, c2.x, v.bottom_right.y) -- ll + ass:rect_cw(c2.x, c1.y, v.bottom_right.x, v.bottom_right.y) -- lr + ass:draw_stop() + -- also possible to draw a rect over the whole video + -- and \iclip it in the middle, but seemingy slower +end + +function draw_frame(ass, frame) + ass:new_event() + ass:pos(0, 0) + ass:append("{\\an7}") + ass:append("{\\bord0}") + ass:append("{\\shad0}") + ass:append("{\\c&H" .. opts.frame_border_color .. "&}") + ass:append("{\\1a&H00&}") + ass:append("{\\2a&HFF&}") + ass:append("{\\3a&HFF&}") + ass:append("{\\4a&HFF&}") + local c1, c2 = frame.top_left, frame.bottom_right + local b = opts.frame_border_width + ass:draw_start() + ass:rect_cw(c1.x, c1.y - b, c2.x + b, c1.y) + ass:rect_cw(c2.x, c1.y, c2.x + b, c2.y + b) + ass:rect_cw(c1.x - b, c2.y, c2.x, c2.y + b) + ass:rect_cw(c1.x - b, c1.y - b, c1.x, c2.y) + ass:draw_stop() +end + +function draw_crosshair(ass, center, window_size) + ass:new_event() + ass:pos(0, 0) + ass:append("{\\an7}") + ass:append("{\\bord0}") + ass:append("{\\shad0}") + ass:append("{\\c&HBBBBBB&}") + ass:append("{\\1a&H00&}") + ass:append("{\\2a&HFF&}") + ass:append("{\\3a&HFF&}") + ass:append("{\\4a&HFF&}") + ass:draw_start() + ass:rect_cw(center.x - 0.5, 0, center.x + 0.5, window_size.h) + ass:rect_cw(0, center.y - 0.5, window_size.w, center.y + 0.5) + ass:draw_stop() +end + +function draw_position_text(ass, text, position, window_size, offset) + ass:new_event() + local align = 1 + local ofx = 1 + local ofy = -1 + if position.x > window_size.w / 2 then + align = align + 2 + ofx = -1 + end + if position.y < window_size.h / 2 then + align = align + 6 + ofy = 1 + end + ass:append("{\\an"..align.."}") + ass:append("{\\fs26}") + ass:append("{\\bord1.5}") + ass:pos(ofx*offset + position.x, ofy*offset + position.y) + ass:append(text) +end + +function draw_crop_zone() + if needs_drawing then + local dim = mp.get_property_native("osd-dimensions") + if not dim then + cancel_crop() + return + end + + local cursor = { + x = crop_cursor.x, + y = crop_cursor.y, + } + local ass = assdraw.ass_new() + + if crop_first_corner and (opts.draw_shade or opts.draw_frame) then + local frame = {} + frame.top_left, frame.bottom_right = rect_from_two_points( + video_norm_to_screen(crop_first_corner, dim), + cursor, + rect_centered, + rect_keepaspect and dim.w/dim.h) + -- don't draw shade over non-visible video parts + if opts.draw_shade then + local window = { + top_left = { x = 0, y = 0 }, + bottom_right = { x = dim.w, y = dim.h }, + } + draw_shade(ass, frame, window) + end + if opts.draw_frame then + draw_frame(ass, frame) + end + end + + + if opts.draw_crosshair then + draw_crosshair(ass, cursor, { w = dim.w, h = dim.h }) + end + + if opts.draw_text then + local vop = mp.get_property_native("video-out-params") + if vop then + local cursor_norm = screen_to_video_norm(cursor, dim) + local text = string.format("%d, %d", cursor_norm.x * vop.w, cursor_norm.y * vop.h) + if crop_first_corner then + text = string.format("%s (%dx%d)", text, + math.abs((cursor_norm.x - crop_first_corner.x) * vop.w ), + math.abs((cursor_norm.y - crop_first_corner.y) * vop.h ) + ) + end + draw_position_text(ass, text, cursor, { w = dim.w, h = dim.h }, 6) + end + end + + mp.set_osd_ass(dim.w, dim.h, ass.text) + needs_drawing = false + end +end + +function crop_video(x1, y1, x2, y2) + if active_mode == "soft" then + local w = x2 - x1 + local h = y2 - y1 + local dim = mp.get_property_native("osd-dimensions") + if not dim then return end + + local zoom = mp.get_property_number("video-zoom") + local newZoom1 = math.log(dim.h * (2 ^ zoom) / (dim.h - dim.mt - dim.mb) / h) / math.log(2) + local newZoom2 = math.log(dim.w * (2 ^ zoom) / (dim.w - dim.ml - dim.mr) / w) / math.log(2) + mp.set_property("video-zoom", math.min(newZoom1, newZoom2)) + mp.set_property("video-pan-x", 0.5 - (x1 + w / 2)) + mp.set_property("video-pan-y", 0.5 - (y1 + h / 2)) + elseif active_mode == "hard" or active_mode == "delogo" then + x1 = clamp(0, x1, 1) + y1 = clamp(0, y1, 1) + x2 = clamp(0, x2, 1) + y2 = clamp(0, y2, 1) + local vop = mp.get_property_native("video-out-params") + local vf_table = mp.get_property_native("vf") + local x = math.floor(x1 * vop.w + 0.5) + local y = math.floor(y1 * vop.h + 0.5) + local w = math.floor((x2 - x1) * vop.w + 0.5) + local h = math.floor((y2 - y1) * vop.h + 0.5) + if active_mode == "delogo" then + -- delogo is a little special and needs some padding to function + w = math.min(vop.w - 1, w) + h = math.min(vop.h - 1, h) + x = math.max(1, x) + y = math.max(1, y) + if x + w == vop.w then w = w - 1 end + if y + h == vop.h then h = h - 1 end + end + vf_table[#vf_table + 1] = { + name=(active_mode == "hard") and "crop" or "delogo", + params= { x = tostring(x), y = tostring(y), w = tostring(w), h = tostring(h) } + } + mp.set_property_native("vf", vf_table) + end +end + +function update_crop_zone_state() + local dim = mp.get_property_native("osd-dimensions") + if not dim then + cancel_crop() + return + end + local corner = crop_cursor + if crop_first_corner == nil then + crop_first_corner = screen_to_video_norm(crop_cursor, dim) + redraw() + else + local c1, c2 = rect_from_two_points( + video_norm_to_screen(crop_first_corner, dim), + crop_cursor, + rect_centered, + rect_keepaspect and dim.w/dim.h) + local c1norm = screen_to_video_norm(c1, dim) + local c2norm = screen_to_video_norm(c2, dim) + crop_video(c1norm.x, c1norm.y, c2norm.x, c2norm.y) + cancel_crop() + end +end + +local bindings = {} +local bindings_repeat = {} + +function cancel_crop() + crop_first_corner = nil + for key, _ in pairs(bindings) do + mp.remove_key_binding("crop-"..key) + end + for key, _ in pairs(bindings_repeat) do + mp.remove_key_binding("crop-"..key) + end + mp.unobserve_property(redraw) + mp.unregister_idle(draw_crop_zone) + mp.set_osd_ass(1280, 720, '') + active = false +end + +function start_crop(mode) + if active then return end + if not mp.get_property_native("osd-dimensions") then return end + if mode and not mode_ok(mode) then + msg.error("Invalid mode value: " .. mode) + return + end + local mode_maybe = mode or opts.mode + if mode_maybe ~= 'soft' then + local hwdec = mp.get_property("hwdec-current") + if hwdec and hwdec ~= "no" and not string.find(hwdec, "-copy$") then + msg.error("Cannot crop with hardware decoding active (see manual)") + return + end + end + active = true + active_mode = mode_maybe + + if opts.mouse_support then + crop_cursor.x, crop_cursor.y = mp.get_mouse_pos() + end + redraw() + for key, func in pairs(bindings) do + mp.add_forced_key_binding(key, "crop-"..key, func) + end + for key, func in pairs(bindings_repeat) do + mp.add_forced_key_binding(key, "crop-"..key, func, { repeatable = true }) + end + mp.register_idle(draw_crop_zone) + mp.observe_property("osd-dimensions", nil, redraw) +end + +function toggle_crop(mode) + if mode and not mode_ok(mode) then + msg.error("Invalid mode value: " .. mode) + end + local toggle_mode = mode or opts.mode + if toggle_mode == "soft" then return end -- can't toggle soft mode + + local remove_filter = function() + local to_remove = (toggle_mode == "hard") and "crop" or "delogo" + local vf_table = mp.get_property_native("vf") + if #vf_table > 0 then + for i = #vf_table, 1, -1 do + if vf_table[i].name == to_remove then + for j = i, #vf_table-1 do + vf_table[j] = vf_table[j+1] + end + vf_table[#vf_table] = nil + mp.set_property_native("vf", vf_table) + return true + end + end + end + return false + end + if not remove_filter() then + start_crop(mode) + end +end + +-- bindings +if opts.mouse_support then + bindings["MOUSE_MOVE"] = function() crop_cursor.x, crop_cursor.y = mp.get_mouse_pos(); redraw() end +end +for _, key in ipairs(opts.accept) do + bindings[key] = update_crop_zone_state +end +for _, key in ipairs(opts.cancel) do + bindings[key] = cancel_crop +end +function movement_func(move_x, move_y) + return function() + crop_cursor.x = crop_cursor.x + move_x + crop_cursor.y = crop_cursor.y + move_y + redraw() + end +end +bindings_repeat[opts.left_coarse] = movement_func(-opts.coarse_movement, 0) +bindings_repeat[opts.right_coarse] = movement_func(opts.coarse_movement, 0) +bindings_repeat[opts.up_coarse] = movement_func(0, -opts.coarse_movement) +bindings_repeat[opts.down_coarse] = movement_func(0, opts.coarse_movement) +bindings_repeat[opts.left_fine] = movement_func(-opts.fine_movement, 0) +bindings_repeat[opts.right_fine] = movement_func(opts.fine_movement, 0) +bindings_repeat[opts.up_fine] = movement_func(0, -opts.fine_movement) +bindings_repeat[opts.down_fine] = movement_func(0, opts.fine_movement) + + +mp.add_key_binding(nil, "start-crop", start_crop) +mp.add_key_binding(nil, "toggle-crop", toggle_crop) diff --git a/.config/mpv/scripts/encode.lua b/.config/mpv/scripts/encode.lua new file mode 100644 index 0000000..df518d8 --- /dev/null +++ b/.config/mpv/scripts/encode.lua @@ -0,0 +1,315 @@ +local utils = require "mp.utils" +local msg = require "mp.msg" +local options = require "mp.options" + +local ON_WINDOWS = (package.config:sub(1,1) ~= "/") + +local start_timestamp = nil +local profile_start = "" + +-- implementation detail of the osd message +local timer = nil +local timer_duration = 2 + +function append_table(lhs, rhs) + for i = 1,#rhs do + lhs[#lhs+1] = rhs[i] + end + return lhs +end + +function file_exists(name) + local f = io.open(name, "r") + if f ~= nil then + io.close(f) + return true + else + return false + end +end + +function get_extension(path) + local candidate = string.match(path, "%.([^.]+)$") + if candidate then + for _, ext in ipairs({ "mkv", "webm", "mp4", "avi" }) do + if candidate == ext then + return candidate + end + end + end + return "mkv" +end + +function get_output_string(dir, format, input, extension, title, from, to, profile) + local res = utils.readdir(dir) + if not res then + return nil + end + local files = {} + for _, f in ipairs(res) do + files[f] = true + end + local output = format + output = string.gsub(output, "$f", function() return input end) + output = string.gsub(output, "$t", function() return title end) + output = string.gsub(output, "$s", function() return seconds_to_time_string(from, true) end) + output = string.gsub(output, "$e", function() return seconds_to_time_string(to, true) end) + output = string.gsub(output, "$d", function() return seconds_to_time_string(to-from, true) end) + output = string.gsub(output, "$x", function() return extension end) + output = string.gsub(output, "$p", function() return profile end) + if ON_WINDOWS then + output = string.gsub(output, "[/\\|<>?:\"*]", "_") + end + if not string.find(output, "$n") then + return files[output] and nil or output + end + local i = 1 + while true do + local potential_name = string.gsub(output, "$n", tostring(i)) + if not files[potential_name] then + return potential_name + end + i = i + 1 + end +end + +function get_video_filters() + local filters = {} + for _, vf in ipairs(mp.get_property_native("vf")) do + local name = vf["name"] + name = string.gsub(name, '^lavfi%-', '') + local filter + if name == "crop" then + local p = vf["params"] + filter = string.format("crop=%d:%d:%d:%d", p.w, p.h, p.x, p.y) + elseif name == "mirror" then + filter = "hflip" + elseif name == "flip" then + filter = "vflip" + elseif name == "rotate" then + local rotation = vf["params"]["angle"] + -- rotate is NOT the filter we want here + if rotation == "90" then + filter = "transpose=clock" + elseif rotation == "180" then + filter = "transpose=clock,transpose=clock" + elseif rotation == "270" then + filter = "transpose=cclock" + end + end + filters[#filters + 1] = filter + end + return filters +end + +function get_input_info(default_path, only_active) + local accepted = { + video = true, + audio = not mp.get_property_bool("mute"), + sub = mp.get_property_bool("sub-visibility") + } + local ret = {} + for _, track in ipairs(mp.get_property_native("track-list")) do + local track_path = track["external-filename"] or default_path + if not only_active or (track["selected"] and accepted[track["type"]]) then + local tracks = ret[track_path] + if not tracks then + ret[track_path] = { track["ff-index"] } + else + tracks[#tracks + 1] = track["ff-index"] + end + end + end + return ret +end + +function seconds_to_time_string(seconds, full) + local ret = string.format("%02d:%02d.%03d" + , math.floor(seconds / 60) % 60 + , math.floor(seconds) % 60 + , seconds * 1000 % 1000 + ) + if full or seconds > 3600 then + ret = string.format("%d:%s", math.floor(seconds / 3600), ret) + end + return ret +end + +function start_encoding(from, to, settings) + local args = { + settings.ffmpeg_command, + "-loglevel", "panic", "-hide_banner", + } + local append_args = function(table) args = append_table(args, table) end + + local path = mp.get_property("path") + local is_stream = not file_exists(path) + if is_stream then + path = mp.get_property("stream-path") + end + + local track_args = {} + local start = seconds_to_time_string(from, false) + local input_index = 0 + for input_path, tracks in pairs(get_input_info(path, settings.only_active_tracks)) do + append_args({ + "-ss", start, + "-i", input_path, + }) + if settings.only_active_tracks then + for _, track_index in ipairs(tracks) do + track_args = append_table(track_args, { "-map", string.format("%d:%d", input_index, track_index)}) + end + else + track_args = append_table(track_args, { "-map", tostring(input_index)}) + end + input_index = input_index + 1 + end + + append_args({"-to", tostring(to-from)}) + append_args(track_args) + + -- apply some of the video filters currently in the chain + local filters = {} + if settings.preserve_filters then + filters = get_video_filters() + end + if settings.append_filter ~= "" then + filters[#filters + 1] = settings.append_filter + end + if #filters > 0 then + append_args({ "-filter:v", table.concat(filters, ",") }) + end + + -- split the user-passed settings on whitespace + for token in string.gmatch(settings.codec, "[^%s]+") do + args[#args + 1] = token + end + + -- path of the output + local output_directory = settings.output_directory + if output_directory == "" then + if is_stream then + output_directory = "." + else + output_directory, _ = utils.split_path(path) + end + else + output_directory = string.gsub(output_directory, "^~", os.getenv("HOME") or "~") + end + local input_name = mp.get_property("filename/no-ext") or "encode" + local title = mp.get_property("media-title") + local extension = get_extension(path) + local output_name = get_output_string(output_directory, settings.output_format, input_name, extension, title, from, to, settings.profile) + if not output_name then + mp.osd_message("Invalid path " .. output_directory) + return + end + args[#args + 1] = utils.join_path(output_directory, output_name) + + if settings.print then + local o = "" + -- fuck this is ugly + for i = 1, #args do + local fmt = "" + if i == 1 then + fmt = "%s%s" + elseif i >= 2 and i <= 4 then + fmt = "%s" + elseif args[i-1] == "-i" or i == #args or args[i-1] == "-filter:v" then + fmt = "%s '%s'" + else + fmt = "%s %s" + end + o = string.format(fmt, o, args[i]) + end + print(o) + end + if settings.detached then + utils.subprocess_detached({ args = args }) + else + local res = utils.subprocess({ args = args, max_size = 0, cancellable = false }) + if res.status == 0 then + mp.osd_message("Finished encoding succesfully") + else + mp.osd_message("Failed to encode, check the log") + end + end +end + +function clear_timestamp() + timer:kill() + start_timestamp = nil + profile_start = "" + mp.remove_key_binding("encode-ESC") + mp.remove_key_binding("encode-ENTER") + mp.osd_message("", 0) +end + +function set_timestamp(profile) + if not mp.get_property("path") then + mp.osd_message("No file currently playing") + return + end + if not mp.get_property_bool("seekable") then + mp.osd_message("Cannot encode non-seekable media") + return + end + + if not start_timestamp or profile ~= profile_start then + profile_start = profile + start_timestamp = mp.get_property_number("time-pos") + local msg = function() + mp.osd_message( + string.format("encode [%s]: waiting for end timestamp", profile or "default"), + timer_duration + ) + end + msg() + timer = mp.add_periodic_timer(timer_duration, msg) + mp.add_forced_key_binding("ESC", "encode-ESC", clear_timestamp) + mp.add_forced_key_binding("ENTER", "encode-ENTER", function() set_timestamp(profile) end) + else + local from = start_timestamp + local to = mp.get_property_number("time-pos") + if to <= from then + mp.osd_message("Second timestamp cannot be before the first", timer_duration) + timer:kill() + timer:resume() + return + end + clear_timestamp() + mp.osd_message(string.format("Encoding from %s to %s" + , seconds_to_time_string(from, false) + , seconds_to_time_string(to, false) + ), timer_duration) + -- include the current frame into the extract + local fps = mp.get_property_number("container-fps") or 30 + to = to + 1 / fps / 2 + local settings = { + detached = true, + container = "", + only_active_tracks = false, + preserve_filters = true, + append_filter = "", + codec = "-an -sn -c:v libvpx -crf 10 -b:v 1000k", + output_format = "$f_$n.webm", + output_directory = "", + ffmpeg_command = "ffmpeg", + print = true, + } + if profile then + options.read_options(settings, profile) + if settings.container ~= "" then + msg.warn("The 'container' setting is deprecated, use 'output_format' now") + settings.output_format = settings.output_format .. "." .. settings.container + end + settings.profile = profile + else + settings.profile = "default" + end + start_encoding(from, to, settings) + end +end + +mp.add_key_binding(nil, "set-timestamp", set_timestamp) -- cgit v1.2.3 From e1737dbd191446d53d4687426eae682d31270b62 Mon Sep 17 00:00:00 2001 From: yuzu-eva Date: Mon, 20 Mar 2023 13:50:42 +0100 Subject: update i guess --- .config/mpv/script-opts/encode_webm.conf | 2 +- .config/neofetch/config.conf | 4 +-- .config/nvim/lua/user/plugins/lspconfig.lua | 12 +++++++-- .config/nvim/plugin/packer_compiled.lua | 40 ++++++++++++++--------------- .config/picom/picom.conf | 4 +-- .config/shell/profile | 6 ++--- .config/sxiv/exec/key-handler | 2 +- .config/yt-dlp/config | 2 +- .config/zsh/.zshrc | 10 +++----- 9 files changed, 43 insertions(+), 39 deletions(-) (limited to '.config/mpv') diff --git a/.config/mpv/script-opts/encode_webm.conf b/.config/mpv/script-opts/encode_webm.conf index 06cdc34..93dbb74 100644 --- a/.config/mpv/script-opts/encode_webm.conf +++ b/.config/mpv/script-opts/encode_webm.conf @@ -13,7 +13,7 @@ preserve_filters=yes append_filter= # additional parameters passed to ffmpeg -codec=-c:a libvorbis -crf 1 -b:v 1M +codec=-c:v libvpx-vp9 -b:v 800k -c:a libvorbis # format of the output filename # Does basic interpolation on the following variables: $f, $x, $t, $s, $e, $d, $p, $n which respectively represent diff --git a/.config/neofetch/config.conf b/.config/neofetch/config.conf index 86feaa4..149ab2e 100644 --- a/.config/neofetch/config.conf +++ b/.config/neofetch/config.conf @@ -364,7 +364,7 @@ gtk3="off" # disk_show=('/'): # 'Disk (/): 74G / 118G (66%)' # -disk_show=('/' '/home' '/dev/sda2') +disk_show=('/' '/home' '/dev/sda2' '/dev/sdb1') # Disk subtitle. # What to append to the Disk subtitle. @@ -745,7 +745,7 @@ ascii_distro="auto" # Example: # ascii_colors=(distro) - Ascii is colored based on Distro colors. # ascii_colors=(4 6 1 8 8 6) - Ascii is colored using these colors. -ascii_colors=(15 88 88 88 88 88) +ascii_colors=(88 88 88 88 88 88) # Bold ascii logo # Whether or not to bold the ascii logo. diff --git a/.config/nvim/lua/user/plugins/lspconfig.lua b/.config/nvim/lua/user/plugins/lspconfig.lua index 92a728b..1351959 100644 --- a/.config/nvim/lua/user/plugins/lspconfig.lua +++ b/.config/nvim/lua/user/plugins/lspconfig.lua @@ -56,13 +56,13 @@ require 'lspconfig'.emmet_ls.setup { flags = { debounce_text_changes = 150, }, - filetypes = { 'html', 'javascript', 'typescript', 'javascriptreact', 'typescriptreact' } + filetypes = { 'html', 'javascript', 'typescript', 'javascriptreact', 'typescriptreact', 'eruby' } } local runtime_path = vim.split(package.path, ';') table.insert(runtime_path, "lua/?.lua") table.insert(runtime_path, "lua/?/init.lua") -require 'lspconfig'.sumneko_lua.setup { +require 'lspconfig'.lua_ls.setup { on_attach = on_attach, capabilities = capabilities, flags = { @@ -118,6 +118,14 @@ require 'lspconfig'.clangd.setup { cmd = { "/usr/bin/clangd-13" }; } +require 'lspconfig'.solargraph.setup { + on_attach = on_attach, + capabilities = capabilities, + flags = { + debounce_text_changes = 150, + } +} + -- suppress error messages from lang servers vim.notify = function(msg, log_level, _) if msg:match 'exit code' then diff --git a/.config/nvim/plugin/packer_compiled.lua b/.config/nvim/plugin/packer_compiled.lua index 6a3d510..6275daa 100644 --- a/.config/nvim/plugin/packer_compiled.lua +++ b/.config/nvim/plugin/packer_compiled.lua @@ -242,46 +242,46 @@ _G.packer_plugins = { } time([[Defining packer_plugins]], false) +-- Config for: dracula +time([[Config for dracula]], true) +try_loadstring("\27LJ\2\n4\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\25user.plugins.dracula\frequire\0", "config", "dracula") +time([[Config for dracula]], false) +-- Config for: nvim-autopairs +time([[Config for nvim-autopairs]], true) +try_loadstring("\27LJ\2\n<\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\19nvim-autopairs\frequire\0", "config", "nvim-autopairs") +time([[Config for nvim-autopairs]], false) -- Config for: nvim-ts-autotag time([[Config for nvim-ts-autotag]], true) try_loadstring("\27LJ\2\n=\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\20nvim-ts-autotag\frequire\0", "config", "nvim-ts-autotag") time([[Config for nvim-ts-autotag]], false) --- Config for: nvim-cmp -time([[Config for nvim-cmp]], true) -try_loadstring("\27LJ\2\n0\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\21user.plugins.cmp\frequire\0", "config", "nvim-cmp") -time([[Config for nvim-cmp]], false) -- Config for: nvim-lspconfig time([[Config for nvim-lspconfig]], true) try_loadstring("\27LJ\2\n6\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\27user.plugins.lspconfig\frequire\0", "config", "nvim-lspconfig") time([[Config for nvim-lspconfig]], false) --- Config for: dracula -time([[Config for dracula]], true) -try_loadstring("\27LJ\2\n4\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\25user.plugins.dracula\frequire\0", "config", "dracula") -time([[Config for dracula]], false) +-- Config for: telescope.nvim +time([[Config for telescope.nvim]], true) +try_loadstring("\27LJ\2\n6\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\27user.plugins.telescope\frequire\0", "config", "telescope.nvim") +time([[Config for telescope.nvim]], false) -- Config for: lualine.nvim time([[Config for lualine.nvim]], true) try_loadstring("\27LJ\2\n4\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\25user.plugins.lualine\frequire\0", "config", "lualine.nvim") time([[Config for lualine.nvim]], false) --- Config for: nvim-autopairs -time([[Config for nvim-autopairs]], true) -try_loadstring("\27LJ\2\n<\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\19nvim-autopairs\frequire\0", "config", "nvim-autopairs") -time([[Config for nvim-autopairs]], false) --- Config for: nvim-tree.lua -time([[Config for nvim-tree.lua]], true) -try_loadstring("\27LJ\2\n6\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\27user.plugins.nvim-tree\frequire\0", "config", "nvim-tree.lua") -time([[Config for nvim-tree.lua]], false) -- Config for: nvim-treesitter time([[Config for nvim-treesitter]], true) try_loadstring("\27LJ\2\n]\0\0\3\0\4\0\t6\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\0016\0\0\0'\2\3\0B\0\2\1K\0\1\0\28user.plugins.treesitter\nsetup\16spellsitter\frequire\0", "config", "nvim-treesitter") time([[Config for nvim-treesitter]], false) +-- Config for: nvim-tree.lua +time([[Config for nvim-tree.lua]], true) +try_loadstring("\27LJ\2\n6\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\27user.plugins.nvim-tree\frequire\0", "config", "nvim-tree.lua") +time([[Config for nvim-tree.lua]], false) +-- Config for: nvim-cmp +time([[Config for nvim-cmp]], true) +try_loadstring("\27LJ\2\n0\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\21user.plugins.cmp\frequire\0", "config", "nvim-cmp") +time([[Config for nvim-cmp]], false) -- Config for: LuaSnip time([[Config for LuaSnip]], true) try_loadstring("\27LJ\2\n4\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\25user.plugins.luasnip\frequire\0", "config", "LuaSnip") time([[Config for LuaSnip]], false) --- Config for: telescope.nvim -time([[Config for telescope.nvim]], true) -try_loadstring("\27LJ\2\n6\0\0\3\0\2\0\0046\0\0\0'\2\1\0B\0\2\1K\0\1\0\27user.plugins.telescope\frequire\0", "config", "telescope.nvim") -time([[Config for telescope.nvim]], false) _G._packer.inside_compile = false if _G._packer.needs_bufread == true then diff --git a/.config/picom/picom.conf b/.config/picom/picom.conf index 6d3640c..f3eb671 100644 --- a/.config/picom/picom.conf +++ b/.config/picom/picom.conf @@ -2,8 +2,8 @@ # empty file, just so transparency works on st opacity-rule = [ - "90:class_g = 'discord' && focused", - "90:class_g = 'discord' && !focused" + "90:class_g = 'SchildiChat' && focused", + "90:class_g = 'SchildiChat' && !focused" ] # corner-radius = 6 diff --git a/.config/shell/profile b/.config/shell/profile index 6cca5f1..0093eed 100644 --- a/.config/shell/profile +++ b/.config/shell/profile @@ -24,9 +24,7 @@ export XDG_SESSION_TYPE='x11' export NVM_DIR="$HOME/.config/nvm" -export PATH="$PATH:$HOME/.local/bin:$HOME/.fzf/bin:$HOME/.cargo/bin:/sbin:/usr/sbin" +export PATH="$PATH:$HOME/.local/bin:$HOME/.fzf/bin:$HOME/.cargo/bin:/sbin:/usr/sbin:$HOME/.rvm/bin" + -# if [ -z "${DISPLAY}" ] && [ "${XDG_VTNR}" -eq 1 ]; then -# exec startx -# fi diff --git a/.config/sxiv/exec/key-handler b/.config/sxiv/exec/key-handler index dcbc60b..981eb8e 100755 --- a/.config/sxiv/exec/key-handler +++ b/.config/sxiv/exec/key-handler @@ -1,6 +1,6 @@ #!/usr/bin/env bash -while read file +while read -r file do case "$1" in "C-d") rm "$file" ;; diff --git a/.config/yt-dlp/config b/.config/yt-dlp/config index e2b5628..aeb3bda 100755 --- a/.config/yt-dlp/config +++ b/.config/yt-dlp/config @@ -1 +1 @@ ---verbose -ciw -f bestvideo[ext=mp4][vcodec!*=av01]+bestaudio[ext=m4a]/best[ext=mp4]/best --add-metadata --merge-output-format mkv +--verbose -ciw -f bestvideo[ext=mp4][vcodec!*=av01]+bestaudio[ext=m4a]/best[ext=mp4]/best --merge-output-format mkv diff --git a/.config/zsh/.zshrc b/.config/zsh/.zshrc index 016a729..e94a036 100644 --- a/.config/zsh/.zshrc +++ b/.config/zsh/.zshrc @@ -70,12 +70,6 @@ setopt hist_ignore_all_dups setopt hist_find_no_dups setopt hist_save_no_dups -DIRSTACKFILE="${XDG_CACHE_HOME/.cache}/zsh/dirs" -if [[ -f "$DIRSTACKFILE" ]] && (( ${#dirstack} == 0 )); then - dirstack=("${(@f)"$(< "$DIRSTACKFILE")"}") - [[ -d "${dirstack[1]}" ]] && cd -- "${dirstack[1]}" -fi - DIRSTACKSIZE='20' setopt auto_pushd @@ -111,6 +105,10 @@ fi neofetch +# Add RVM to PATH for scripting. Make sure this is the last PATH variable change. +[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function* + if [ -f $XDG_DATA_HOME/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]; then . $XDG_DATA_HOME/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh fi + -- cgit v1.2.3