moshy 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/moshy/inspect.rb CHANGED
@@ -1,110 +1,110 @@
1
- module Moshy
2
- class Inspect
3
- def cli(args)
4
- opts = Slop::Options.new
5
- opts.banner = "Usage: moshy -m inspect -i file.avi\nmoshy -m inspect --help for details"
6
- opts.separator 'Required Parameters:'
7
- opts.string '-i', '--input', 'Input file path - must be an .avi.'
8
- opts.on '-h', '--help' do
9
- puts opts
10
- puts "\n"
11
- puts \
12
- "Reads an .avi file and prints which video frames are keyframes (I-Frames)
13
- and which frames are delta frames (P-frames or B-frames). moshy can't
14
- tell the difference between a P-frame or a B-frame, so you will want
15
- to use avidemux or another program if you need to know.
16
-
17
- This is most useful for identifying where I-Frames exist without having
18
- to manually seek through them in a video player/editor. Works well with
19
- moshy's \"isplit\" mode because you can use the I-frames from inspect's
20
- output to decide what segment of clips you want to get by their I-frames.
21
-
22
- The output reads like this:
23
-
24
- 0: keyframe
25
- 1..359: deltaframe
26
- 360: keyframe
27
- 361..441: deltaframe
28
-
29
- Large video files will output a lot of text, so you may want to write the
30
- output to an external file like this:
31
-
32
- moshy -m inspect -i video.avi > inspect.txt"
33
- exit
34
- end
35
-
36
- parser = Slop::Parser.new(opts)
37
- @options = parser.parse(ARGV)
38
-
39
- # Check mandatory params
40
- mandatory = [:input]
41
- missing = mandatory.select{ |param| @options[param].nil? }
42
- unless missing.empty?
43
- puts "Missing options: #{missing.join(', ')}"
44
- puts @options
45
- exit
46
- end
47
-
48
- puts "Opening file " + @options[:input] + "..."
49
- a = AviGlitch.open @options[:input] # Rewrite this line for your file.
50
- puts "Opened!"
51
-
52
- inspect(a)
53
- end
54
-
55
- def inspect(clip)
56
- keyframe_counter = 0
57
- video_frame_counter = 0
58
- last_video_frame = 0
59
- start_of_frame_segment = 0
60
- last_type = nil
61
- type = nil
62
- # Harvest clip details
63
- total_frame_count = clip.frames.count
64
- clip.frames.each_with_index do |f, i|
65
- if f.is_videoframe?
66
- if f.is_keyframe?
67
- type = "keyframe"
68
- elsif f.is_deltaframe?
69
- type = "deltaframe"
70
- end
71
-
72
- if video_frame_counter == 0
73
- last_type = type
74
- end
75
-
76
- if type == last_type
77
- last_video_frame = video_frame_counter
78
- else
79
- # Found a new type segment, print out what we've got
80
- if start_of_frame_segment + 1 == last_video_frame
81
- segment_string = start_of_frame_segment.to_s + ": " + last_type
82
- else
83
- segment_string = start_of_frame_segment.to_s + ".." + (last_video_frame - 1).to_s + ": " + last_type
84
- end
85
- # Let's not add this so we don't confuse the user by making
86
- # them think they want to use isplit according to the keyframe count
87
- # if last_type == "keyframe"
88
- # segment_string += " " + keyframe_counter.to_s
89
- # keyframe_counter += 1
90
- # end
91
- puts segment_string
92
-
93
- # The new last type will be this type during the next frame segment
94
- last_type = type
95
- # Update start of the frame segment to this frame
96
- start_of_frame_segment = video_frame_counter
97
- end
98
- end
99
- video_frame_counter += 1
100
- last_video_frame = video_frame_counter
101
- end
102
- if start_of_frame_segment + 1 == last_video_frame
103
- puts start_of_frame_segment.to_s + ": " + last_type
104
- else
105
- puts start_of_frame_segment.to_s + ".." + (last_video_frame - 1).to_s + ": " + last_type
106
- end
107
- puts "All done!"
108
- end
109
- end
110
- end
1
+ module Moshy
2
+ class Inspect
3
+ def cli(args)
4
+ opts = Slop::Options.new
5
+ opts.banner = "Usage: moshy -m inspect -i file.avi\nmoshy -m inspect --help for details"
6
+ opts.separator 'Required Parameters:'
7
+ opts.string '-i', '--input', 'Input file path - must be an .avi.'
8
+ opts.on '-h', '--help' do
9
+ puts opts
10
+ puts "\n"
11
+ puts \
12
+ "Reads an .avi file and prints which video frames are keyframes (I-Frames)
13
+ and which frames are delta frames (P-frames or B-frames). moshy can't
14
+ tell the difference between a P-frame or a B-frame, so you will want
15
+ to use avidemux or another program if you need to know.
16
+
17
+ This is most useful for identifying where I-Frames exist without having
18
+ to manually seek through them in a video player/editor. Works well with
19
+ moshy's \"isplit\" mode because you can use the I-frames from inspect's
20
+ output to decide what segment of clips you want to get by their I-frames.
21
+
22
+ The output reads like this:
23
+
24
+ 0: keyframe
25
+ 1..359: deltaframe
26
+ 360: keyframe
27
+ 361..441: deltaframe
28
+
29
+ Large video files will output a lot of text, so you may want to write the
30
+ output to an external file like this:
31
+
32
+ moshy -m inspect -i video.avi > inspect.txt"
33
+ exit
34
+ end
35
+
36
+ parser = Slop::Parser.new(opts)
37
+ @options = parser.parse(ARGV)
38
+
39
+ # Check mandatory params
40
+ mandatory = [:input]
41
+ missing = mandatory.select{ |param| @options[param].nil? }
42
+ unless missing.empty?
43
+ puts "Missing options: #{missing.join(', ')}"
44
+ puts @options
45
+ exit
46
+ end
47
+
48
+ puts "Opening file " + @options[:input] + "..."
49
+ a = AviGlitch.open @options[:input] # Rewrite this line for your file.
50
+ puts "Opened!"
51
+
52
+ inspect(a)
53
+ end
54
+
55
+ def inspect(clip)
56
+ keyframe_counter = 0
57
+ video_frame_counter = 0
58
+ last_video_frame = 0
59
+ start_of_frame_segment = 0
60
+ last_type = nil
61
+ type = nil
62
+ # Harvest clip details
63
+ total_frame_count = clip.frames.count
64
+ clip.frames.each_with_index do |f, i|
65
+ if f.is_videoframe?
66
+ if f.is_keyframe?
67
+ type = "keyframe"
68
+ elsif f.is_deltaframe?
69
+ type = "deltaframe"
70
+ end
71
+
72
+ if video_frame_counter == 0
73
+ last_type = type
74
+ end
75
+
76
+ if type == last_type
77
+ last_video_frame = video_frame_counter
78
+ else
79
+ # Found a new type segment, print out what we've got
80
+ if start_of_frame_segment + 1 == last_video_frame
81
+ segment_string = start_of_frame_segment.to_s + ": " + last_type
82
+ else
83
+ segment_string = start_of_frame_segment.to_s + ".." + (last_video_frame - 1).to_s + ": " + last_type
84
+ end
85
+ # Let's not add this so we don't confuse the user by making
86
+ # them think they want to use isplit according to the keyframe count
87
+ # if last_type == "keyframe"
88
+ # segment_string += " " + keyframe_counter.to_s
89
+ # keyframe_counter += 1
90
+ # end
91
+ puts segment_string
92
+
93
+ # The new last type will be this type during the next frame segment
94
+ last_type = type
95
+ # Update start of the frame segment to this frame
96
+ start_of_frame_segment = video_frame_counter
97
+ end
98
+ end
99
+ video_frame_counter += 1
100
+ last_video_frame = video_frame_counter
101
+ end
102
+ if start_of_frame_segment + 1 == last_video_frame
103
+ puts start_of_frame_segment.to_s + ": " + last_type
104
+ else
105
+ puts start_of_frame_segment.to_s + ".." + (last_video_frame - 1).to_s + ": " + last_type
106
+ end
107
+ puts "All done!"
108
+ end
109
+ end
110
+ end
data/lib/moshy/isplit.rb CHANGED
@@ -1,129 +1,129 @@
1
- module Moshy
2
- class ISplit
3
- def cli(args)
4
- opts = Slop::Options.new
5
- opts.banner = "Usage: moshy -m isplit -i file.avi -o file_out\nmoshy -m isplit --help for details"
6
- opts.separator 'Required Parameters:'
7
- opts.string '-i', '--input', 'Input file path - must be an .avi.'
8
- opts.string '-o', '--output', 'Output file path - will be appended with -#.avi for each clip.'
9
- opts.separator 'Optional Parameters:'
10
- opts.integer '-b', '--begin', 'Index of the I-frame at which to begin clipping (inclusive)'
11
- opts.integer '-e', '--end', 'Index of the I-frame at which to stop clipping (inclusive)'
12
- opts.integer '-v', '--verbose', 'Noisy output (default: false)'
13
- opts.on '-h', '--help' do
14
- puts opts
15
- puts "\n"
16
- puts \
17
- "Extracts individual clips from an AVI where each clip is separated
18
- by I-frames in the original AVI. Great for getting specific clips out
19
- of a larger video and later doing I-frame moshing.
20
-
21
- Note that since this creates multiple clips, you should NOT specify
22
- the .avi extension in your output (-o) parameter, as moshy will
23
- automatically append \"-#.avi\" to the output parameter you pass
24
- when it spits out individual clips.
25
-
26
- If you want to only cut clips from a certain section of a larger
27
- video file, you can set the in- and out-points of where to get clips
28
- from by using the -b (--begin) and -e (--end) options, where the
29
- values used in those parameters are the indexes of the I-Frames.
30
- For example, if a video file has 12 I-Frames and you want the clips
31
- between I-Frames 3 and 7, you would use the following command:
32
-
33
- moshy -m isplit -i file.avi -o file_out -b 3 -e 7"
34
- exit
35
- end
36
-
37
- parser = Slop::Parser.new(opts)
38
- @options = parser.parse(ARGV)
39
- # puts @options.to_hash
40
-
41
- # Check mandatory params
42
- mandatory = [:input, :output]
43
- missing = mandatory.select{ |param| @options[param].nil? }
44
- unless missing.empty?
45
- puts "Missing options: #{missing.join(', ')}"
46
- puts @options
47
- exit
48
- end
49
-
50
-
51
- puts "Opening file " + @options[:input] + "..."
52
- a = AviGlitch.open @options[:input] # Rewrite this line for your file.
53
- puts "Opened!"
54
-
55
- split(a, @options[:output], @options[:begin], @options[:end], @options[:verbose])
56
- end
57
-
58
- def clip(frames, out_path, start_index, frame_count)
59
- puts "Clipping " + frame_count.to_s + " frames starting at frame " + start_index.to_s
60
- clip = frames.slice(start_index, frame_count)
61
- o = AviGlitch.open clip
62
- puts "Outputting " + out_path
63
- o.output out_path
64
- end
65
-
66
- def split(clip, output, begin_point, end_point, verbose)
67
- clip_cuts = {}
68
-
69
- clip_count = 0
70
- current_iframe = 0
71
- iframe_index = 0
72
- last_iframe_index = 0
73
- frames_in_clip = 0
74
-
75
- # Harvest clip details
76
- total_frame_count = clip.frames.count
77
- clip.frames.each_with_index do |f, i|
78
- if f.is_keyframe?
79
- iframe_index = i
80
- # Don't process frames that are before our beginning
81
- if current_iframe and begin_point and current_iframe < begin_point
82
- # puts "skipping " + current_iframe.to_s
83
- frames_in_clip = 0
84
- current_iframe = current_iframe + 1
85
- last_iframe_index = iframe_index
86
- # puts "last_iframe_index: " + last_iframe_index.to_s
87
- next
88
- end
89
- break if end_point and current_iframe > end_point
90
-
91
- if current_iframe != 0
92
- if verbose
93
- puts "Storing clip details: iframe_number=" + current_iframe.to_s + "; index=" + last_iframe_index.to_s + "; frame_count=" + frames_in_clip.to_s
94
- end
95
- clip_cuts[current_iframe] = {
96
- :index => last_iframe_index,
97
- :frame_count => frames_in_clip
98
- }
99
- end
100
- frames_in_clip = 0
101
- current_iframe = current_iframe + 1
102
- last_iframe_index = iframe_index
103
- else
104
- frames_in_clip = frames_in_clip + 1
105
- # clip last piece manually if we're at the end, because there's
106
- # no last iframe to detect and trigger the final clip
107
- if i == total_frame_count - 1
108
- if verbose
109
- puts "Storing clip details: iframe_number=" + current_iframe.to_s + "; index=" + last_iframe_index.to_s + "; frame_count=" + frames_in_clip.to_s
110
- end
111
- clip_cuts[current_iframe] = {
112
- :index => last_iframe_index,
113
- :frame_count => frames_in_clip
114
- }
115
- end
116
- end
117
- end
118
-
119
- puts clip_cuts
120
-
121
- clip_cuts.keys.each do |f|
122
- out_path = output + '-' + f.to_s + '.avi'
123
- clip(clip.frames, out_path, clip_cuts[f][:index], clip_cuts[f][:frame_count])
124
- end
125
-
126
- puts "All done!"
127
- end
128
- end
129
- end
1
+ module Moshy
2
+ class ISplit
3
+ def cli(args)
4
+ opts = Slop::Options.new
5
+ opts.banner = "Usage: moshy -m isplit -i file.avi -o file_out\nmoshy -m isplit --help for details"
6
+ opts.separator 'Required Parameters:'
7
+ opts.string '-i', '--input', 'Input file path - must be an .avi.'
8
+ opts.string '-o', '--output', 'Output file path - will be appended with -#.avi for each clip.'
9
+ opts.separator 'Optional Parameters:'
10
+ opts.integer '-b', '--begin', 'Index of the I-frame at which to begin clipping (inclusive)'
11
+ opts.integer '-e', '--end', 'Index of the I-frame at which to stop clipping (inclusive)'
12
+ opts.integer '-v', '--verbose', 'Noisy output (default: false)'
13
+ opts.on '-h', '--help' do
14
+ puts opts
15
+ puts "\n"
16
+ puts \
17
+ "Extracts individual clips from an AVI where each clip is separated
18
+ by I-frames in the original AVI. Great for getting specific clips out
19
+ of a larger video and later doing I-frame moshing.
20
+
21
+ Note that since this creates multiple clips, you should NOT specify
22
+ the .avi extension in your output (-o) parameter, as moshy will
23
+ automatically append \"-#.avi\" to the output parameter you pass
24
+ when it spits out individual clips.
25
+
26
+ If you want to only cut clips from a certain section of a larger
27
+ video file, you can set the in- and out-points of where to get clips
28
+ from by using the -b (--begin) and -e (--end) options, where the
29
+ values used in those parameters are the indexes of the I-Frames.
30
+ For example, if a video file has 12 I-Frames and you want the clips
31
+ between I-Frames 3 and 7, you would use the following command:
32
+
33
+ moshy -m isplit -i file.avi -o file_out -b 3 -e 7"
34
+ exit
35
+ end
36
+
37
+ parser = Slop::Parser.new(opts)
38
+ @options = parser.parse(ARGV)
39
+ # puts @options.to_hash
40
+
41
+ # Check mandatory params
42
+ mandatory = [:input, :output]
43
+ missing = mandatory.select{ |param| @options[param].nil? }
44
+ unless missing.empty?
45
+ puts "Missing options: #{missing.join(', ')}"
46
+ puts @options
47
+ exit
48
+ end
49
+
50
+
51
+ puts "Opening file " + @options[:input] + "..."
52
+ a = AviGlitch.open @options[:input] # Rewrite this line for your file.
53
+ puts "Opened!"
54
+
55
+ split(a, @options[:output], @options[:begin], @options[:end], @options[:verbose])
56
+ end
57
+
58
+ def clip(frames, out_path, start_index, frame_count)
59
+ puts "Clipping " + frame_count.to_s + " frames starting at frame " + start_index.to_s
60
+ clip = frames.slice(start_index, frame_count)
61
+ o = AviGlitch.open clip
62
+ puts "Outputting " + out_path
63
+ o.output out_path
64
+ end
65
+
66
+ def split(clip, output, begin_point, end_point, verbose)
67
+ clip_cuts = {}
68
+
69
+ clip_count = 0
70
+ current_iframe = 0
71
+ iframe_index = 0
72
+ last_iframe_index = 0
73
+ frames_in_clip = 0
74
+
75
+ # Harvest clip details
76
+ total_frame_count = clip.frames.count
77
+ clip.frames.each_with_index do |f, i|
78
+ if f.is_keyframe?
79
+ iframe_index = i
80
+ # Don't process frames that are before our beginning
81
+ if current_iframe and begin_point and current_iframe < begin_point
82
+ # puts "skipping " + current_iframe.to_s
83
+ frames_in_clip = 0
84
+ current_iframe = current_iframe + 1
85
+ last_iframe_index = iframe_index
86
+ # puts "last_iframe_index: " + last_iframe_index.to_s
87
+ next
88
+ end
89
+ break if end_point and current_iframe > end_point
90
+
91
+ if current_iframe != 0
92
+ if verbose
93
+ puts "Storing clip details: iframe_number=" + current_iframe.to_s + "; index=" + last_iframe_index.to_s + "; frame_count=" + frames_in_clip.to_s
94
+ end
95
+ clip_cuts[current_iframe] = {
96
+ :index => last_iframe_index,
97
+ :frame_count => frames_in_clip
98
+ }
99
+ end
100
+ frames_in_clip = 0
101
+ current_iframe = current_iframe + 1
102
+ last_iframe_index = iframe_index
103
+ else
104
+ frames_in_clip = frames_in_clip + 1
105
+ # clip last piece manually if we're at the end, because there's
106
+ # no last iframe to detect and trigger the final clip
107
+ if i == total_frame_count - 1
108
+ if verbose
109
+ puts "Storing clip details: iframe_number=" + current_iframe.to_s + "; index=" + last_iframe_index.to_s + "; frame_count=" + frames_in_clip.to_s
110
+ end
111
+ clip_cuts[current_iframe] = {
112
+ :index => last_iframe_index,
113
+ :frame_count => frames_in_clip
114
+ }
115
+ end
116
+ end
117
+ end
118
+
119
+ puts clip_cuts
120
+
121
+ clip_cuts.keys.each do |f|
122
+ out_path = output + '-' + f.to_s + '.avi'
123
+ clip(clip.frames, out_path, clip_cuts[f][:index], clip_cuts[f][:frame_count])
124
+ end
125
+
126
+ puts "All done!"
127
+ end
128
+ end
129
+ end
data/lib/moshy/pdupe.rb CHANGED
@@ -1,85 +1,85 @@
1
- module Moshy
2
- class PDupe
3
- def cli(args)
4
- opts = Slop::Options.new
5
- opts.banner = "Usage: moshy -m pdupe -i file.avi -o file_out.avi -f <integer>\nmoshy -m pdupe --help for details"
6
- opts.separator 'Required Parameters:'
7
- opts.string '-i', '--input', 'Input file path - must be an .avi.'
8
- opts.string '-o', '--output', 'Output file path, should be an .avi.'
9
- opts.integer '-f', '--frame', 'Index of the frame that should be duplicated'
10
- opts.separator 'Optional Parameters:'
11
- opts.integer '-d', '--dupes', 'Number of times to multiply the frame (default: 30)'
12
- opts.on '-h', '--help' do
13
- puts opts
14
- puts "\n"
15
- puts \
16
- "Duplicates a P-frame at a given frame a certain amount. To find
17
- out which frames are P-frames, use software like avidemux to look at the
18
- frame type. WARNING: This mode is a little glitchy. You may need to set
19
- the interval 1 or 2 above or below the frame number you actually want to
20
- duplicate. I'm not sure why this happens, but try it with a small
21
- duplication amount first. NOTE: This can mode take a while to process
22
- over 60-90 frame dupes.
23
-
24
- You can specify the number of duplicates that you want with the -d parameter."
25
- exit
26
- end
27
-
28
- default = {
29
- :dupes => 30
30
- }
31
-
32
- parser = Slop::Parser.new(opts)
33
- slop_options = parser.parse(ARGV)
34
- @options = default.merge(slop_options) { |key, oldval, newval|
35
- if newval.nil?
36
- oldval
37
- else
38
- newval
39
- end
40
- }
41
-
42
- # Check mandatory params
43
- mandatory = [:input, :output, :frame]
44
- missing = mandatory.select{ |param| @options[param].nil? }
45
- unless missing.empty?
46
- puts "Missing options: #{missing.join(', ')}"
47
- puts slop_options
48
- exit
49
- end
50
-
51
- puts "Opening file " + @options[:input] + "..."
52
- a = AviGlitch.open @options[:input] # Rewrite this line for your file.
53
- puts "Opened!"
54
-
55
- pdupe(a, @options[:output], @options[:frame], @options[:dupes])
56
- end
57
-
58
- def pdupe(clip, output, frame, duplicate_amount)
59
-
60
- puts "Size: " + clip.frames.size_of('videoframe').to_s
61
-
62
- frames = nil
63
- video_frame_counter = 0
64
-
65
- clip.frames.each_with_index do |f, i|
66
- if f.is_videoframe?
67
- video_frame_counter += 1
68
- if video_frame_counter == frame
69
- puts "On frame " + frame.to_s + ", duping " + duplicate_amount.to_s + " times"
70
- clipped = clip.frames[0..(i + 5)]
71
- dupe_clip = clip.frames[(i + 4), 1] * duplicate_amount
72
- frames = clipped + dupe_clip
73
- puts "Added dupe, grabbing rest..."
74
- frames = frames + clip.frames[i..-1]
75
- puts "Done. Output frame count: " + frames.size.to_s
76
- break
77
- end
78
- end
79
- end
80
-
81
- o = AviGlitch.open frames
82
- o.output output
83
- end
84
- end
85
- end
1
+ module Moshy
2
+ class PDupe
3
+ def cli(args)
4
+ opts = Slop::Options.new
5
+ opts.banner = "Usage: moshy -m pdupe -i file.avi -o file_out.avi -f <integer>\nmoshy -m pdupe --help for details"
6
+ opts.separator 'Required Parameters:'
7
+ opts.string '-i', '--input', 'Input file path - must be an .avi.'
8
+ opts.string '-o', '--output', 'Output file path, should be an .avi.'
9
+ opts.integer '-f', '--frame', 'Index of the frame that should be duplicated'
10
+ opts.separator 'Optional Parameters:'
11
+ opts.integer '-d', '--dupes', 'Number of times to multiply the frame (default: 30)'
12
+ opts.on '-h', '--help' do
13
+ puts opts
14
+ puts "\n"
15
+ puts \
16
+ "Duplicates a P-frame at a given frame a certain amount. To find
17
+ out which frames are P-frames, use software like avidemux to look at the
18
+ frame type. WARNING: This mode is a little glitchy. You may need to set
19
+ the interval 1 or 2 above or below the frame number you actually want to
20
+ duplicate. I'm not sure why this happens, but try it with a small
21
+ duplication amount first. NOTE: This can mode take a while to process
22
+ over 60-90 frame dupes.
23
+
24
+ You can specify the number of duplicates that you want with the -d parameter."
25
+ exit
26
+ end
27
+
28
+ default = {
29
+ :dupes => 30
30
+ }
31
+
32
+ parser = Slop::Parser.new(opts)
33
+ slop_options = parser.parse(ARGV)
34
+ @options = default.merge(slop_options) { |key, oldval, newval|
35
+ if newval.nil?
36
+ oldval
37
+ else
38
+ newval
39
+ end
40
+ }
41
+
42
+ # Check mandatory params
43
+ mandatory = [:input, :output, :frame]
44
+ missing = mandatory.select{ |param| @options[param].nil? }
45
+ unless missing.empty?
46
+ puts "Missing options: #{missing.join(', ')}"
47
+ puts slop_options
48
+ exit
49
+ end
50
+
51
+ puts "Opening file " + @options[:input] + "..."
52
+ a = AviGlitch.open @options[:input] # Rewrite this line for your file.
53
+ puts "Opened!"
54
+
55
+ pdupe(a, @options[:output], @options[:frame], @options[:dupes])
56
+ end
57
+
58
+ def pdupe(clip, output, frame, duplicate_amount)
59
+
60
+ puts "Size: " + clip.frames.size_of('videoframe').to_s
61
+
62
+ frames = nil
63
+ video_frame_counter = 0
64
+
65
+ clip.frames.each_with_index do |f, i|
66
+ if f.is_videoframe?
67
+ video_frame_counter += 1
68
+ if video_frame_counter == frame
69
+ puts "On frame " + frame.to_s + ", duping " + duplicate_amount.to_s + " times"
70
+ clipped = clip.frames[0..(i + 5)]
71
+ dupe_clip = clip.frames[(i + 4), 1] * duplicate_amount
72
+ frames = clipped + dupe_clip
73
+ puts "Added dupe, grabbing rest..."
74
+ frames = frames + clip.frames[i..-1]
75
+ puts "Done. Output frame count: " + frames.size.to_s
76
+ break
77
+ end
78
+ end
79
+ end
80
+
81
+ o = AviGlitch.open frames
82
+ o.output output
83
+ end
84
+ end
85
+ end