Git Product home page Git Product logo

Comments (11)

familyfriendlymikey avatar familyfriendlymikey commented on May 23, 2024

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.

lukasschwab avatar lukasschwab commented on May 23, 2024

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 as LIST_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

  1. Dependencies/environments might change in a way that breaks already-generated scripts.
  2. 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.

lukasschwab avatar lukasschwab commented on May 23, 2024

I immediately ran into an issue hardcoding SRT subs from ffmpeg-python: kkroening/ffmpeg-python#663

from mpv-cut.

familyfriendlymikey avatar familyfriendlymikey commented on May 23, 2024

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.

akippnn avatar akippnn commented on May 23, 2024

I'm assuming Node will be abandoned in favour of Python?

from mpv-cut.

familyfriendlymikey avatar familyfriendlymikey commented on May 23, 2024

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.

akippnn avatar akippnn commented on May 23, 2024

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.

familyfriendlymikey avatar familyfriendlymikey commented on May 23, 2024

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.

akippnn avatar akippnn commented on May 23, 2024

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.

familyfriendlymikey avatar familyfriendlymikey commented on May 23, 2024

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.

akippnn avatar akippnn commented on May 23, 2024

I'll see what I can do at the weekend

from mpv-cut.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.