Comments (11)
Not sure if this is considered hacky, but this appears to work well. Can test by placing test_video.mkv
in the same dir.
import os, subprocess
def make_cuts(cut_list):
print()
for index, cut in enumerate(cut_list):
inpath, args, timestamps = cut[2:].strip().split(" : ")
inpath_noext, ext = os.path.splitext(inpath)
args = args.split()
start_time, duration = timestamps.split()
end_time = str(float(start_time) + float(duration)).rstrip('0').rstrip('.')
outpath = f"ENCODE_{inpath_noext}_FROM_{start_time}_TO_{end_time}{ext}"
cmd = [
"ffmpeg",
"-nostdin", "-y", "-loglevel", "error",
"-ss", start_time,
"-t", duration,
"-i", inpath,
"-pix_fmt", "yuv420p",
"-crf", "16",
"-preset", "superfast",
outpath
]
print(f"\x1b[32m({index + 1}/{len(cut_list)})\x1b[0m {inpath} \x1b[32m->\x1b[0m")
print(f"{outpath}\n")
print(f"\x1b[34m{' '.join(cmd)}\x1b[0m\n")
subprocess.run(cmd)
with open(__file__, "r") as this_file:
lines = this_file.readlines()
cut_list_index = lines.index("# BEGIN CUT LIST\n") + 1
cut_list = lines[cut_list_index:]
make_cuts(cut_list)
# BEGIN CUT LIST
# test_video.mkv : encode : 10.438 2.254
# test_video.mkv : encode : 20.843 5.438
If we put the cut list at the bottom like this, we don't have to parse the file in any way, and we can rely on LUA to append lines to the file if it already exists rather than risking reading and writing over an existing file.
from mpv-cut.
Preface: I don't have much use for the cut list feature. I see how it could be useful, but I'm almost always scrubbing for and clipping a single range. Not having an extra step to do that––not having to leave mpv to reencode a range––is what makes mpv-cut useful to me.
You know what you want from cut lists, so I'll gladly defer to you!
But what if we were to forego the cut list and make_cuts files entirely, and instead have
mpv-cut
generate a Python file, such asLIST_CHANNEL_NAME_Source_Video_File_Name.mkv.py
, which would act as both the cut list for backup purposes and as the make_cuts script...
I see two risks with encapsulated cut lists
- Dependencies/environments might change in a way that breaks already-generated scripts.
- Data stored in a Python script is harder to access programmatically, which makes it harder to compose mpv-cut with other scripts.
It seems more natural to me to beef up make_cuts
and use it more consistently, rather than trying to keep it in sync with the ffmpeg logic in cut.lua.
Suppose make_cuts
reads tabular or JSONL data from stdin:
{ "file": "test_video.mkv", "start": 10.438, "end": 2.254 }
{ "file": "test_video.mkv", "start": 20.843, "end": 5.438 }
(JSON is nice because it's easy to extend with named options in the future, without breaking backwards-compatibility with old make_cuts versions and old cut lists).
Then cut.lua could invoke make_cuts instead of calling ffmpeg, passing it a single clip definition:
mp.commandv(
"run",
"echo", '{ "file": "test_video.mkv", "start": 20.843, "end": 5.438 }',
"|", "make_cuts" -- TODO: figure out if you can actually pipe like this.
)
Then make_cuts
can become the flexible/modular part, with options to tailor its behavior (a concat option, a framerate option, etc). cut.lua
passes the local vars that serve as its config as make_cuts
flags.
Of course, I'm totally content to customize these scripts for my own use case and just report whatever I learn about using ffprobe to switch between the ffmpeg subs-encoding options. No pressure!
Cheers
from mpv-cut.
I immediately ran into an issue hardcoding SRT subs from ffmpeg-python
: kkroening/ffmpeg-python#663
from mpv-cut.
Great points, thanks for sharing your thoughts. I'm open to doing that.
Regarding ffmpeg-python, I figured using a wrapper would be more straightforward/robust than parsing the result of ffprobe from scratch, but if not, using child_process or whatever is cool too. I'm not sure if you already had things working for both srt and image subs on your fork, so I hope the ffmpeg-python stuff wasn't too time consuming!
Also, this may no longer be relevant, but regarding getting stdout from a subprocess in mpv:
local r = mp.command_native({
name = "subprocess",
playback_only = false,
capture_stdout = true,
args = {"cat", "/proc/cpuinfo"},
})
if r.status == 0 then
print("result: " .. r.stdout)
end
I'll see about modifying cut.lua
.
from mpv-cut.
I'm assuming Node will be abandoned in favour of Python?
from mpv-cut.
Nope, I implemented the changes in Python but the VM startup seemed pretty slow to me so I rewrote it in Imba targeting Node.
from mpv-cut.
Oh right. I suppose considering you haven't closed it yet, I assume hardcoding subs is still on the scope of the project?
from mpv-cut.
I assume hardcoding subs is still on the scope of the project?
Absolutely. It's just that ffmpeg is a bit of a beast imo, so finding one command to handle every use case is pretty hard. That's why I ended up making the mpv extension as simple as possible (iirc lukas here had some nice ideas that inspired me), and just had it pipe JSON to an arbitrary external script where people could support their own use cases without having to learn lua or mpv's api. I'm now realizing though that most people won't customize the make_cuts script.
Maybe a better solution is to just allow people to supply their own actions in the config.lua
file. So users could potentially do something like:
ACTIONS = {
"COPY": "ffmpeg -ss {start_time} -t {duration} -i {infile} -c copy COPY_{channel}_FROM_{start_time}_TO_{end_time}_{outfile}"
"HARDSUBS_IMAGE": ...
"HARDSUBS_SRT": ...
}
Then users can support their own use cases as long as they have some ffmpeg knowledge, and I might be able to just get rid of the Node dependency altogether.
from mpv-cut.
That sounds about right. I don't think there's one command to handle every use case. I think in this case it's probably better to get information like the subtitle format from ffmpeg -i
and the subtitle track currently being viewed.
Though I assume you can also get the subtitle format from mpv itself, so there's no need to use ffmpeg -i
.
from mpv-cut.
Alright I completely removed the Node dependency and made it very easy to configure custom actions. Example config.lua
:
ACTIONS.ENCODE = function(d)
local args = {
"ffmpeg",
"-nostdin", "-y",
"-loglevel", "error",
"-i", d.inpath,
"-ss", d.start_time,
"-t", d.duration,
"-pix_fmt", "yuv420p",
"-crf", "16",
"-preset", "superfast",
utils.join_path(d.indir, "ENCODE_" .. d.channel .. "_" .. d.infile_noext .. "_FROM_" .. d.start_time_hms .. "_TO_" .. d.end_time_hms .. d.ext)
}
mp.command_native_async({
name = "subprocess",
args = args,
playback_only = false,
}, function() print("Done") end)
end
I'm still interested in having the default encode action account for subs but I'm not really stoked to research ffmpeg stuff for a use case I don't have at this moment, so it'll have to wait unless someone finds a command that works for srt, image, and no subs (or any other cases if there are any).
from mpv-cut.
I'll see what I can do at the weekend
from mpv-cut.
Related Issues (20)
- Wrong duration when using encode HOT 5
- Chapters get overwritten when it shouldn't be HOT 1
- Would it be possible to place the cut on another directory and not where the original one is? HOT 2
- "Error reading cut list" when invoking MAKE_CUTS HOT 9
- Change the position of the overlay text for OSD HOT 2
- DIR Directory to output cutted videos
- Extra duration when using ENCODE HOT 1
- Consider adding a license
- High disk usage compared to other scripts HOT 11
- sorry. please delete this issue
- Is there way to choose audio track to cut from HOT 3
- No response in Celluloid HOT 1
- Encoding causes wrong Timestamps with videos with Subtitles
- Can't cut video from URL
- Cant cut 10bit 4:2:2 HOT 6
- Autoload bookmarks chapters on opening a video
- Subtitle styling is removed. HOT 6
- is there anyway we can pick the Audio we want to keep? HOT 1
- Pressing 'c' doesn't work HOT 3
- When I cut a video for lossless, it only gives me the 1st Audio channel and 1st Subtitle. HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mpv-cut.