Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > VapourSynth

Reply
 
Thread Tools Search this Thread Display Modes
Old 28th April 2014, 16:52   #1  |  Link
jackoneill
unsigned int
 
jackoneill's Avatar
 
Join Date: Oct 2012
Location: 🇪🇺
Posts: 760
WWXD: Faster Xvid-like scene change detection for VapourSynth

Code:
WWXD is basically Xvid's frame type decision code stuffed into a VapourSynth
plugin.

The output is somewhat different from Scxvid's, because Xvid's decisions are
also affected by data calculated while encoding frames. WWXD may miss more
scene changes than Scxvid. It may also detect some that Scxvid missed.

WWXD is considerably faster than Scxvid, possibly about six times.

There is no log file. Instead, the frames are tagged with the property
"SceneChange" (1 or 0).

The license is the same as Xvid's, i.e. GPL2.

To compile:
gcc -o libwwxd.so -fPIC -shared -O2 -Wall -Wextra -Wno-unused-parameter $(pkg-config --cflags vapoursynth) src/wwxd.c src/detection.c

To use:
core.wwxd.WWXD(clip=src)
Source code and DLLs here: https://github.com/dubhater/vapoursynth-wwxd
__________________
Buy me a "coffee" and/or hire me to write code!
jackoneill is offline   Reply With Quote
Old 10th August 2017, 18:38   #2  |  Link
lansing
Registered User
 
Join Date: Sep 2006
Posts: 1,657
There's a typo in the namespace, the plugin uses "Scenechange" instead of "SceneChange" in the readme.
lansing is offline   Reply With Quote
Old 17th August 2017, 16:03   #3  |  Link
lansing
Registered User
 
Join Date: Sep 2006
Posts: 1,657
Hi can you add an option to output the result to a list? Getting the list of scene changes by iterating the clip took way too much time.
lansing is offline   Reply With Quote
Old 17th August 2017, 16:37   #4  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,100
Getting it to execute would still require requesting all frames, you know. But this is VS, not Avisynth. We're in a Python script, we have way nicer tools available. If you want to generate a list of scene changes before running the rest of the script, you are free to recursively exec vspipe on your script and pass in the generated frame list as a command line argument to yourself, or something along those lines. You'll have to decode the source file twice but eh who cares.
TheFluff is offline   Reply With Quote
Old 17th August 2017, 18:55   #5  |  Link
lansing
Registered User
 
Join Date: Sep 2006
Posts: 1,657
Quote:
Originally Posted by TheFluff View Post
Getting it to execute would still require requesting all frames, you know. But this is VS, not Avisynth. We're in a Python script, we have way nicer tools available. If you want to generate a list of scene changes before running the rest of the script, you are free to recursively exec vspipe on your script and pass in the generated frame list as a command line argument to yourself, or something along those lines. You'll have to decode the source file twice but eh who cares.
How do you do that with vspipe? I tested something like this on a range of 10000, and got the error "RecursionError: maximum recursion depth exceeded while pickling an object" around just 1000 count.

Code:
sample_range = range(1,10001)
my_list = []

def test_recursion(num, sc_list):
	print(str(num))
	if (num == 0):	
		return sc_list
	if (num % 2 == 0):	
		sc_list.append(num)
		
	test_recursion(num-1, sc_list)

my_sc_list = test_recursion(len(sample_range), my_list)

print(my_sc_list)
lansing is offline   Reply With Quote
Old 17th August 2017, 19:59   #6  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,100
Not like that. I mean, you can use the subprocess module (or if you're feeling adventurous, os.execl) from your .vpy to run another instance of vspipe (on the same script, if you want - use the --arg stuff in vspipe to determine which mode to operate in) which gets the frame numbers for you. You can retrieve them from that other instance simply by printing them to stdout, for example in a FrameEval, and reading them back in your main script. Or write them to a file, or something.
TheFluff is offline   Reply With Quote
Old 18th August 2017, 19:38   #7  |  Link
lansing
Registered User
 
Join Date: Sep 2006
Posts: 1,657
That's a lot of stuffs to learn...

So I'm trying to get the subprocess on vspipe working first, I did a simple caller and child script, but I don't know how to catch the returned video. I'm getting the error "AttributeError: 'bytes' object has no attribute 'set_output'".

caller.vpy
Code:
import vapoursynth as vs
import subprocess

core = vs.get_core(accept_lowercase=True)

command = "vspipe child.vpy -"

child = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
child_clip = child.stdout

child_clip.output()
child.vpy
Code:
import vapoursynth as vs

core = vs.get_core(accept_lowercase=True)

clip = core.std.BlankClip(width=640, height=480, length=1000)

clip.set_output()
lansing is offline   Reply With Quote
Old 18th August 2017, 22:35   #8  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,100
No that way won't work. vspipe normally writes frame data to stdout (assuming you use - as the output filename) and status/progress messages to stderr. You don't want raw frame data though, that's of no use to you. What you do want is frame numbers. My idea was that to capture the WWXD scene change numbers you'd tack on a FrameEval after WWXD and inspect the frame props in there. Once you have a frame number you can either make a list of them in python and write that to a file or something, or you can go with my original idea and just print() them. print() writes to stdout, so normally you don't want to do that in a .vpy since it'd get mixed in with your actual frame data that vspipe is writing to stdout at the same time, so you'd have to use . as the output filename to get vspipe to leave stdout alone. When you do that, you can read the frame numbers from the stdout pipe in caller.vpy by calling child.stdout.readlines(). You'll get them back as a line of strings.
TheFluff is offline   Reply With Quote
Old 19th August 2017, 02:53   #9  |  Link
lansing
Registered User
 
Join Date: Sep 2006
Posts: 1,657
Quote:
Originally Posted by TheFluff View Post
No that way won't work. vspipe normally writes frame data to stdout (assuming you use - as the output filename) and status/progress messages to stderr. You don't want raw frame data though, that's of no use to you. What you do want is frame numbers. My idea was that to capture the WWXD scene change numbers you'd tack on a FrameEval after WWXD and inspect the frame props in there. Once you have a frame number you can either make a list of them in python and write that to a file or something, or you can go with my original idea and just print() them. print() writes to stdout, so normally you don't want to do that in a .vpy since it'd get mixed in with your actual frame data that vspipe is writing to stdout at the same time, so you'd have to use . as the output filename to get vspipe to leave stdout alone. When you do that, you can read the frame numbers from the stdout pipe in caller.vpy by calling child.stdout.readlines(). You'll get them back as a line of strings.
um I still getting the same error even with the "." at the end of the vspipe command.

caller
Code:
import vapoursynth as vs
import subprocess

core = vs.get_core(accept_lowercase=True)

command = "vspipe child.vpy ."

sc_list = []

child = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

while True:
	line = child.stdout.readline()
	if line == '':   
		break
	sc_list.append(line)
child
Code:
import vapoursynth as vs

core = vs.get_core(accept_lowercase=True)

clip = core.ffms2.Source(r"abc.avi")
clip = core.wwxd.WWXD(clip)

def PrintSC(n,f,clip):
	if f.props.Scenechange:
		print(n)
	return clip

sc_clip = core.std.FrameEval(clip, functools.partial(PrintSC, clip=clip), clip)

sc_clip.set_output()
And are you sure that it will speed it up this way? Because I ran the child script in command line and the speed was the same as doing it with the for loop.
lansing is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 21:49.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.