AkarinVS / vapoursynth-plugin

My experimental VapourSynth plugin: (1) an enhanced LLVM-based std.Expr (aka lexpr), Select, PropExpr, Text and Tmpl. (2) DLISR. (3) DLVFX (4) CAMBI.
GNU Lesser General Public License v3.0
36 stars 7 forks source link

Please commit #26

Open Bo26fhmC5M opened 7 months ago

Bo26fhmC5M commented 7 months ago

I want to use PickFrames feature introduced in v0.96g on Linux. However, there doesn't seem to be a commit for that content on GitHub. Could you provide the latest source code to compile?

Bo26fhmC5M commented 7 months ago

I needed PickFrames of v0.96g to use the latest version of vsmlrt on Linux. Since I am a vapoursynth newbie, I created a function that mimics the same function, but the execution speed seems to be slow.

def PickFrames(clip: vs.VideoNode, indices: Union[int, Sequence[int]]) -> vs.VideoNode:
    if isinstance(indices, Sequence):
        # return core.std.Splice([clip[i] for i in indices], mismatch=False)
        return core.std.Splice(list(map(clip.__getitem__, indices)), mismatch=False)
    else:
        return clip[indices]
Setsugennoao commented 7 months ago

This is an optimized function doing the same

https://github.com/Jaded-Encoding-Thaumaturgy/vs-tools/blob/master/vstools/utils/ranges.py#L227

Bo26fhmC5M commented 7 months ago

This is an optimized function doing the same

https://github.com/Jaded-Encoding-Thaumaturgy/vs-tools/blob/master/vstools/utils/ranges.py#L227

Thank you for your response! By switching to std.FrameEval, the execution time has been significantly improved:) When I first asked ChatGPT, it said using std.BlankClip consumes a lot of memory, so I implemented it in a different way, but it seems this was a better approach.

def PickFrames2(clip: vs.VideoNode, indices: Union[int, Sequence[int]]) -> vs.VideoNode:
    if isinstance(indices, Sequence):
        new = clip.std.BlankClip(length=len(indices))
        return new.std.FrameEval(lambda n: clip[indices[n]], None, clip)
    else:
        return clip[indices]
couleurm commented 7 months ago

@Bo26fhmC5M what would be some sample arguments you could feed into PickFrames2 per example?

Bo26fhmC5M commented 7 months ago

@couleurm I simply created a list with random elements as shown below and then performed a performance comparison.

clip = core.lsmas.LWLibavSource(source=r"/home/user/video.mkv")
indices = random.choices(range(clip.num_frames), k=100000)
picked = PickFrames2(clip, indices)

Ultimately, I just needed akarin.PickFrames function called in vsmlrt.py. https://github.com/AmusementClub/vs-mlrt/blob/cd198e064f7fd88dd3bd86b1388063b3aa0dfcd3/scripts/vsmlrt.py#L1226

couleurm commented 7 months ago

so with these indices it cuts from [0] to [1], [2] to [3]... correct?

Bo26fhmC5M commented 7 months ago

You can find the definition of the PickFrames function on the page https://github.com/AkarinVS/vapoursynth-plugin/releases/tag/v0.96. I hope this helps.

PickFrames(c, indices) is functionally equivalent to c[indices[0]] + c[indices[1]] + ... + c[indices[-1]], only more efficient as you only need to create one filter instance, especially when len(indices) is very large. As long as all indices are within range [0, c.num_frames-1], there is no limit on the the indices.