add cancel_cut binding, add bash utils with functions make_cuts and concat, remove make_cuts

binding
This commit is contained in:
familyfriendlymikey 2023-08-15 12:06:31 +09:00
parent 26ad54b42d
commit 6849b272a4
3 changed files with 88 additions and 95 deletions

131
README.md
View File

@ -50,6 +50,8 @@ That's all you have to do, next time you run mpv the script will be automaticall
The resulting cut will be placed in the same directory as the source file.
- You can press `C` to cancel a cut.
### Actions
You can press `a` to cycle between three default actions:
@ -80,9 +82,37 @@ the channel and `=` to increment the channel.
You can configure a name for each channel as shown below.
### Making Cuts
### Utils
If you want to make all the cuts stored in a cut list, simply press `0`.
This plugin includes a `utils` script that you can source in your shell's
startup file. In my `~/.zshrc` I have this line:
```
source ~/.config/mpv/scripts/mpv-cut/utils
```
Now when you open new terminals, you'll have access to the functions inside of
the `utils` script, which are explained in this section.
#### Making Cuts
The `make_cuts` function takes a `.list` file and ffmpeg output options except
for an output filename. To make cuts without reencoding:
```
make_cuts some_video.mp4.list -c copy
```
#### Concatenate, Merge, Join Cuts
The `concat` function takes a prefix and ffmpeg output options. Any file in the current directory
starting with the prefix will be included. For example, to concatenate all
files in the current directory whose filename starts with `CUT` without
reencoding:
```
concat CUT -c copy output.mp4
```
## Config
@ -94,29 +124,41 @@ You can include or omit any of the following:
```lua
-- Key config
KEY_CUT = "c"
KEY_CYCLE_ACTION = "a"
KEY_BOOKMARK_ADD = "i"
KEY_CHANNEL_INC = "="
KEY_CHANNEL_DEC = "-"
KEY_MAKE_CUTS = "0"
-- The list of channel names, you can choose whatever you want.
CHANNEL_NAMES[1] = "FUNNY"
CHANNEL_NAMES[2] = "COOL"
-- The default channel
CHANNEL = 1
-- The default action
ACTION = "ENCODE"
-- The action to use when making cuts from a cut list
MAKE_CUT = ACTIONS.COPY
ACTION = "COPY"
-- Delete a default action
ACTIONS.LIST = nil
```
-- Specify custom actions
### Custom Actions
In the config file you can also specify custom actions. Even if you don't know
Lua, it should be pretty straightforward to take the following example and tune
it to your needs. I think this is a very powerful abstraction. All of the
default actions are implemented the same way you'd implement custom actions.
You can essentially define an arbitrary callback to run whenever an action is
invoked (the second time you press `c` in mpv). The callback function gets
passed a table with the following properties:
```
inpath, indir, infile, infile_noext, ext
channel
start_time, end_time, duration
start_time_hms, end_time_hms, duration_hms
```
Here is an example overwriting the default `ENCODE` action:
```lua
ACTIONS.ENCODE = function(d)
local args = {
"ffmpeg",
@ -136,12 +178,6 @@ ACTIONS.ENCODE = function(d)
playback_only = false,
}, function() print("Done") end)
end
-- The table that gets passed to an action will have the following properties:
-- inpath, indir, infile, infile_noext, ext
-- channel
-- start_time, end_time, duration
-- start_time_hms, end_time_hms, duration_hms
```
## Optimized MPV Input Config
@ -152,16 +188,18 @@ quickly editing videos.
```
RIGHT seek 2 exact
LEFT seek -2 exact
UP seek 2 keyframes
DOWN seek -2 keyframes
] add speed 0.5
[ add speed -0.5
} add speed 0.25
{ add speed -0.25
\ set speed 1
SPACE cycle pause; set speed 1 # Reset speed whenever pausing.
BS script-binding osc/visibility # Make progress bar stay visible.
UP seek 0.01 keyframes # Seek by keyframes only.
DOWN seek -0.01 keyframes # Seek by keyframes only.
BS script-binding osc/visibility
Alt+= add video-zoom 0.1
```
You may also want to change your key repeat delay and rate by tweaking
@ -249,53 +287,6 @@ editors.
- If the video's compression isn't efficient enough to upload to a messaging
platform or something, you may want to compress it more.
### How Do I Concatenate Videos Manually With ffmpeg?
To concatenate videos with ffmpeg, you need to create a file with content like
this:
```
file cut_1.mp4
file cut_2.mp4
file cut_3.mp4
file cut_4.mp4
```
You can name the file whatever you want, here I named it `concat.txt`.
Then run the command:
```
ffmpeg -f concat -safe 0 -i concat.txt -c copy out.mp4
```
That's annoying though, so you can skip manually creating the file by using
bash. This command will concatenate all files in the current directory that
begin with "COPY_":
```
ffmpeg -f concat -safe 0 -i <(printf 'file %q\n' "$PWD"/COPY_*) -c copy lol.mp4
```
- You need to escape apostrophes which is why we are using `printf %q
"$string"`.
- Instead of actually creating a file we just use process substitution
`<(whatever)` to create a temporary file, which is why we need the `$PWD` in
there for the absolute path.
You can also do it in vim, among other things.
```
ls | vim -
:%s/'/\\'/g
:%norm Ifile
:wq concat.txt
```
This substitution might not cover all cases, but whatever, if you're
concatenating a file named `[{}1;']["!.mp4` you can figure it out yourself.
### Can I Make Seeking And Reverse Playback Faster?
Depending on the encoding of the video file being played, the following may be

View File

@ -111,6 +111,7 @@ CHANNEL = 1
CHANNEL_NAMES = {}
KEY_CUT = "c"
KEY_CANCEL_CUT = "C"
KEY_CYCLE_ACTION = "a"
KEY_BOOKMARK_ADD = "i"
KEY_CHANNEL_INC = "="
@ -187,30 +188,6 @@ local function cycle_action()
print_or_update_text_overlay("ACTION: " .. ACTION)
end
local function make_cuts()
print("MAKING CUTS")
if not MAKE_CUT then print("MAKE_CUT function not found.") return end
local inpath = mp.get_property("path") .. ".list"
local file = io.open(inpath, "r")
if not file then print("Error reading cut list") return end
for line in file:lines() do
if line ~= "" then
local cut = {}
for token in string.gmatch(line, "[^" .. ":" .. "]+") do
table.insert(cut, token)
end
local d = get_data()
d.channel = cut[1]
local t = get_times(tonumber(cut[2]), tonumber(cut[3]))
for k, v in pairs(t) do d[k] = v end
mp.msg.info("MAKE_CUT")
mp.msg.info(table_to_str(d))
MAKE_CUT(d)
end
end
io.close(file)
end
local function cut(start_time, end_time)
local d = get_data()
local t = get_times(start_time, end_time)
@ -237,6 +214,12 @@ local function put_time()
end
end
local function cancel_cut()
text_overlay_off()
START_TIME = nil
print("CANCELLED CUT")
end
local function get_bookmark_file_path()
local d = get_data()
mp.msg.info(table_to_str(d))
@ -289,10 +272,10 @@ local function channel_dec()
end
mp.add_key_binding(KEY_CUT, "cut", put_time)
mp.add_key_binding(KEY_CANCEL_CUT, "cancel_cut", cancel_cut)
mp.add_key_binding(KEY_BOOKMARK_ADD, "bookmark_add", bookmark_add)
mp.add_key_binding(KEY_CHANNEL_INC, "channel_inc", channel_inc)
mp.add_key_binding(KEY_CHANNEL_DEC, "channel_dec", channel_dec)
mp.add_key_binding(KEY_CYCLE_ACTION, "cycle_action", cycle_action)
mp.add_key_binding(KEY_MAKE_CUTS, "make_cuts", make_cuts)
mp.register_event('file-loaded', bookmarks_load)

19
utils Normal file
View File

@ -0,0 +1,19 @@
#! /usr/bin/env bash
concat() {
local prefix="$1"
shift
ffmpeg -f concat -safe 0 -i <(printf 'file %q\n' "$PWD"/"$prefix"*) "$@"
}
make_cuts() {
local list="$1"
local vid="${list%.*}"
local ext="${vid##*.}"
local vid_noext="${vid%.*}"
shift
while IFS=: read -r channel_name start_ts end_ts; do
if [[ -z "$end_ts" ]]; then continue; fi
ffmpeg -nostdin -ss "$start_ts" -to "$end_ts" -i "$vid" "$@" "CUT_${channel_name}_${vid}_${start_ts}_${end_ts}.${ext}"
done < "$list"
}