moshy 1.0.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/moshy/bake.rb CHANGED
@@ -1,68 +1,68 @@
1
- module Moshy
2
- class Bake
3
- def cli(args)
4
- opts = Slop::Options.new
5
- opts.separator 'Required Parameters:'
6
- opts.string '-i', '--input', 'Input file path - can be anything that ffmpeg supports.'
7
- opts.string '-o', '--output', 'File output path - should end in .avi.'
8
- opts.separator 'Optional Parameters:'
9
- opts.integer '-b', '--bitrate', 'Bitrate amount (kb/s). Defaults to 4196. Larger number means higher quality, but larger size.'
10
- opts.string '-p', '--pframes', 'Makes sure that there are only P-Frames (no B-Frames). Set this true if you plan to mosh your baked file again. Defaults false.'
11
- opts.integer '-n', '--iframe-interval', 'Ideal interval for I-Frames to be distributed. Set this to a high number (600) if you plan to mosh your baked file again.'
12
-
13
- default = {
14
- :bitrate => 4196
15
- }
16
-
17
- parser = Slop::Parser.new(opts)
18
- slop_options = parser.parse(ARGV)
19
- @options = default.merge(slop_options) { |key, oldval, newval|
20
- if newval.nil?
21
- oldval
22
- else
23
- newval
24
- end
25
- }
26
-
27
- if @options[:pframes] == "false"
28
- @options[:pframes] = false
29
- else
30
- @options[:pframes] = true
31
- end
32
-
33
- # Check mandatory params
34
- mandatory = [:input, :output]
35
- missing = mandatory.select{ |param| @options[param].nil? }
36
- unless missing.empty?
37
- puts "Missing options: #{missing.join(', ')}"
38
- puts slop_options
39
- exit
40
- end
41
-
42
- prep @options[:input], @options[:output], @options[:pframes], @options[:'iframe-interval'], @options[:bitrate]
43
- end
44
-
45
- def prep(file, output, pframes, iframe_interval, bitrate)
46
- ffmpeg = Av::Commands::Ffmpeg.new
47
- ffmpeg.add_source file
48
- ffmpeg.add_destination output
49
-
50
- # Ensures all frames come out as P-frames, B-frames don't
51
- # dupe or mosh properly
52
- if pframes
53
- ffmpeg.add_output_param ['bf', 0]
54
- end
55
-
56
- # Keyframe interval, sets as few I-frames as possible.
57
- # ffmpeg will complain about anything over 600 and cap it.
58
- if iframe_interval
59
- ffmpeg.add_output_param ['g', iframe_interval.to_s]
60
- end
61
-
62
- # Bitrate
63
- ffmpeg.add_output_param ['b:v', bitrate.to_s + 'k']
64
-
65
- ffmpeg.run
66
- end
67
- end
68
- end
1
+ module Moshy
2
+ class Bake
3
+ def cli(args)
4
+ opts = Slop::Options.new
5
+ opts.separator 'Required Parameters:'
6
+ opts.string '-i', '--input', 'Input file path - can be anything that ffmpeg supports.'
7
+ opts.string '-o', '--output', 'File output path - should end in .avi.'
8
+ opts.separator 'Optional Parameters:'
9
+ opts.integer '-b', '--bitrate', 'Bitrate amount (kb/s). Defaults to 4196. Larger number means higher quality, but larger size.'
10
+ opts.string '-p', '--pframes', 'Makes sure that there are only P-Frames (no B-Frames). Set this true if you plan to mosh your baked file again. Defaults false.'
11
+ opts.integer '-n', '--iframe-interval', 'Ideal interval for I-Frames to be distributed. Set this to a high number (600) if you plan to mosh your baked file again.'
12
+
13
+ default = {
14
+ :bitrate => 4196
15
+ }
16
+
17
+ parser = Slop::Parser.new(opts)
18
+ slop_options = parser.parse(ARGV)
19
+ @options = default.merge(slop_options) { |key, oldval, newval|
20
+ if newval.nil?
21
+ oldval
22
+ else
23
+ newval
24
+ end
25
+ }
26
+
27
+ if @options[:pframes] == "false"
28
+ @options[:pframes] = false
29
+ else
30
+ @options[:pframes] = true
31
+ end
32
+
33
+ # Check mandatory params
34
+ mandatory = [:input, :output]
35
+ missing = mandatory.select{ |param| @options[param].nil? }
36
+ unless missing.empty?
37
+ puts "Missing options: #{missing.join(', ')}"
38
+ puts slop_options
39
+ exit
40
+ end
41
+
42
+ prep @options[:input], @options[:output], @options[:pframes], @options[:'iframe-interval'], @options[:bitrate]
43
+ end
44
+
45
+ def prep(file, output, pframes, iframe_interval, bitrate)
46
+ ffmpeg = Av::Commands::Ffmpeg.new
47
+ ffmpeg.add_source file
48
+ ffmpeg.add_destination output
49
+
50
+ # Ensures all frames come out as P-frames, B-frames don't
51
+ # dupe or mosh properly
52
+ if pframes
53
+ ffmpeg.add_output_param ['bf', 0]
54
+ end
55
+
56
+ # Keyframe interval, sets as few I-frames as possible.
57
+ # ffmpeg will complain about anything over 600 and cap it.
58
+ if iframe_interval
59
+ ffmpeg.add_output_param ['g', iframe_interval.to_s]
60
+ end
61
+
62
+ # Bitrate
63
+ ffmpeg.add_output_param ['b:v', bitrate.to_s + 'k']
64
+
65
+ ffmpeg.run
66
+ end
67
+ end
68
+ end
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