moshy 1.0.2 → 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/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