View Full Version : run writefile within eval and create 5 files in loop (segments)
magnatique
12th June 2009, 14:44
I'm trying to run writefile within an eval quote..
actually, what I'm trying to accomplish is to write X different files, to load X portion of a master file.
so I'd import the initial file
find the framcount
find num_clips depending on specified length of clips
then do a writefile based on how many clips there is to be made (import(file).trim(start,end))
but since there is no real for loops, I'm trying to do something with eval, but it won't let me get to writefile properly...
here's where am at right now.
if anyone has suggestions, let me know!
d = 2 >= 2 ? Eval("""
test="SHt"
name="name.txt"
WriteFile(name, test)
""") : Eval("""
"No"
""")
Gavino
12th June 2009, 15:34
The arguments to WriteFile (apart from the filename) are expressions to be evaluated at run-time. So you need to say
WriteFile(name, "test")
EDIT: Looking more closely at what you want to do, I think you would use WriteFileStart rather than WriteFile.
To write a dynamically calculated number of lines, you can use the following approach:
function Write(clip c, string file, int n) {
n > 0 ? WriteFileStart(c, file, "f(n)", true).Write(file, n-1) : c
}
where f is a function that decides what to write on the nth line.
Or something like that. ;)
magnatique
13th June 2009, 18:07
to be honnest, I am a bit confused with the way avisynth works when coding it beyond the basics...
here's what I want to do , in a php style language :
## let's say I got to the point where I know how many frames are in the clip:
$Filename="file_to_split";
$Path="C:\document\\"; #fgfgg
$Ext=".avs";
$Total_Frames=30000; ####EXAMPLE: 8991####
$Frames_per_clip=round(29.97*60*5,0); ##FPS * seconds * mins = 5minclip ####EXAMPLE= 8991####
$Num_Clips=round($Total_Frames/$Frames_per_clip,0); ## makes equal clips of equal length close to target frames per clip ####EXAMPLE= 3####
$Real_Frames_Per_Clip=round($Total_Frames/$Num_Clips,0); ###EXAMPLE=10000####
### Now build files, looping for each clip to write
for ($x=1;$x<=$Num_Clips;$x++) {
$start_Frame=(($x-1)*$Real_Frames_Per_Clip)+1;
$End_Frame=($x*$Real_Frames_Per_Clip);
$Text= "Import(\"$Path$Filename$Ext\")
Trim($start_Frame,$End_Frame)
";
echo $Text;
## The next line is not a proper php writefile script, but it is just for proof of concept..3
if ($x<10) {
$New_Filename=$Filename . "_0" . $x . $ext ;
}
else {
$New_Filename=$Filename . "_" . $x . $ext ;
}
write_file($path.$New_Filename,$$Text);
}
Desired output = 3 files :
C:\document\file_to_split_01.avs created with content:
Import("C:\document\file_to_split.avs")
Trim(1,10000)
C:\document\file_to_split_02.avs created with content:
Import("C:\document\file_to_split.avs")
Trim(10001,20000)
C:\document\file_to_split_03.avs created with content:
Import("C:\document\file_to_split.avs")
Trim(20001,30000)
kemuri-_9
13th June 2009, 19:44
from what my understanding is, you're trying to take file X and split it into Y number of separate files using avisynth.
At best you can have a single avisynth script loop through segments of a given file and you encode each run (which would be each section) of the script as a different file, incrementing the file name as necessary.
Saves the work of having to make Y number of files and encode each of them for the different segments
I do something like this to run several instances of the same script (each doing different segments) simultaneously to get an MT effect of the original script.
here's how i have it setup to work for my own use:
source.avs
# whatever your source and processing stuffs goes here
# and no trimming for the specific segments goes here
Version.FadeOut(240) #example
source.cur.avs
cur_sgmt = 0
split_func.avsi
#split a video into equivalent length sections (last section generally a bit longer if not an even split)
function split(clip clip, int "section", int "total") {
section = Default(section, 0)
total = Default(total, 2)
Assert( total > 1, "total number of segments must be >=2" )
Assert( section >= 0 && section < total, "section must be in the range of 0 to total-1" )
FPS = (Framecount(clip) / total) #frames per split
Assert( FPS > 1, "too many splits for given video, reduce number of total sections!" )
return (section != (total-1)) ? clip.trim(FPS*section,FPS*(section+1)-1) : clip.trim(FPS*section, 0)
}
source.split.avs
tot_sgmts = 3 # total number of segments to be created
BlankClip() # create dummy video for WriteFile
Import("split_func.avsi") # if not in autoload dir
Import("source.cur.avs") # get current segment to encode
WriteFileStart("source.cur.avs", """ "cur_sgmt = " + String((cur_sgmt +1) % tot_sgmts) """, append=false)
Import("source.avs") # load the actual source
split(cur_sgmt,tot_sgmts) # segment the source
and then encoding source.split.avs 3 times to split_01, split_02, split_03 respectively or something along those lines has the desired effect...
for the given example based on Version().FadeOut(240)
split_01 would have frames 0-79
split_02 would have frames 80-159
split_03 would have frames 160-240
Gavino
13th June 2009, 20:03
@magnatique
I haven't studied kemuri-_9's solution yet, and it may meet your needs better, but here is my reply to your post.
As you probably know, the way to implement a loop in Avisynth is to use a recursive function. The function body effectively implements one iteration of the loop and calls itself (under the appropriate conditions) to 'go round again'.
So, the loop part of your php code would translate into:
function BuildFiles(string Filename, string Path, string Ext, int Real_Frames_Per_Clip, int x) {
start_Frame = (x-1)*Real_Frames_Per_Clip # (not +1, frames start at 0)
End_Frame = x*Real_Frames_Per_Clip - 1
Text= """Import(" """ + Path + Filename + Ext + """ ")
Trim(""" + string(start_Frame) + "," + string(End_Frame) + ")
"
New_Filename = Filename + (x < 10 ? "_0" : "_") + string(x) + ext
WriteFileStart(BlankClip(), path+New_Filename, "Text");
x > 1 ? BuildFiles(Filename, Path, Ext, Real_Frames_Per_Clip, x-1) : NOP()
}
which would be called as
BuildFiles(Filename, Path, Ext, Real_Frames_Per_Clip, Num_Clips)
If you like, you could use global variables instead of parameters for Filename, Path, Ext and Real_Frames_Per_Clip, but I prefer to avoid globals if at all possible.
magnatique
15th June 2009, 12:31
from what my understanding is, you're trying to take file X and split it into Y number of separate files using avisynth.
At best you can have a single avisynth script loop through segments of a given file and you encode each run (which would be each section) of the script as a different file, incrementing the file name as necessary.
Saves the work of having to make Y number of files and encode each of them for the different segments
I do something like this to run several instances of the same script (each doing different segments) simultaneously to get an MT effect of the original script.
here's how i have it setup to work for my own use:
source.avs
# whatever your source and processing stuffs goes here
# and no trimming for the specific segments goes here
Version.FadeOut(240) #example
source.cur.avs
cur_sgmt = 0
split_func.avsi
#split a video into equivalent length sections (last section generally a bit longer if not an even split)
function split(clip clip, int "section", int "total") {
section = Default(section, 0)
total = Default(total, 2)
Assert( total > 1, "total number of segments must be >=2" )
Assert( section >= 0 && section < total, "section must be in the range of 0 to total-1" )
FPS = (Framecount(clip) / total) #frames per split
Assert( FPS > 1, "too many splits for given video, reduce number of total sections!" )
return (section != (total-1)) ? clip.trim(FPS*section,FPS*(section+1)-1) : clip.trim(FPS*section, 0)
}
source.split.avs
tot_sgmts = 3 # total number of segments to be created
BlankClip() # create dummy video for WriteFile
Import("split_func.avsi") # if not in autoload dir
Import("source.cur.avs") # get current segment to encode
WriteFileStart("source.cur.avs", """ "cur_sgmt = " + String((cur_sgmt +1) % tot_sgmts) """, append=false)
Import("source.avs") # load the actual source
split(cur_sgmt,tot_sgmts) # segment the source
and then encoding source.split.avs 3 times to split_01, split_02, split_03 respectively or something along those lines has the desired effect...
for the given example based on Version().FadeOut(240)
split_01 would have frames 0-79
split_02 would have frames 80-159
split_03 would have frames 160-240
this could work, but I need to queue up hundreds of files with my encoding software, so this would not work to automate everything... plus, if a certain segment fails to encode, re-queueing that one segment would prove hard
magnatique
15th June 2009, 12:35
@magnatique
As you probably know, the way to implement a loop in Avisynth is to use a recursive function. The function body effectively implements one iteration of the loop and calls itself (under the appropriate conditions) to 'go round again'.
....
If you like, you could use global variables instead of parameters for Filename, Path, Ext and Real_Frames_Per_Clip, but I prefer to avoid globals if at all possible.
actually I have only been using avisynth for basic stuff... Last week I was seeing one of my employee work on some files and doing too much manual labor (like manually copying the main avs file, adding trims he'd calculate by hand) and looking for some function I came up with writefile... so I figured I would have a little fun with the coding capabilities of avisynth and try to automate it all ;) your example proves to be REALLY useful.
I will try and implement this right away and see what I can come up with :D
thank you so much !
magnatique
15th June 2009, 12:59
just a quick note to say it works like a charm, I didn't have to modify much and it is doing what I intended ;)
wrapping it up, thanks to you !
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.