polly-ffmpeg 0.1.1

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/README.rdoc ADDED
@@ -0,0 +1,41 @@
1
+ = FFMpeg
2
+
3
+ A DSL for building and executing ffmpeg commands.
4
+
5
+ == Requirements
6
+
7
+ It requires that you already have ffmpeg installed, obviously :)
8
+
9
+ == Install
10
+
11
+ gem install polly-ffmpeg --source http://gems.github.com
12
+
13
+ == Usage
14
+
15
+ To build and execute a command you would use the FFMpeg::convert method and then call the FFMpeg::run method like this:
16
+
17
+ include FFMpeg
18
+
19
+ convert "file.ext", :to => "new_file.ext" do
20
+ seek "00:01:13"
21
+ duration "00:10:01"
22
+ end.run
23
+
24
+ == Extending
25
+
26
+ FFMpeg takes a lot of options, I mean alot ;), so I haven't been able to add methods for wrapping them all yet.
27
+ Luckily it's really easy to add your own wrapper methods, just add them to the class that's including the FFMpeg module.
28
+ So if you wanted to add a method for say, setting the video quantizer scale blur for example, here's how you could do it:
29
+
30
+ def quantizer_scale_blur(blur)
31
+ FFMpegCommand << "-qblur #{blur}"
32
+ end
33
+
34
+ You would then call it inside the convert block just like any other method:
35
+
36
+ convert "file.ext", :to => "new_file.ext" do
37
+ quantizer_scale_blur "0.5"
38
+ end
39
+
40
+ If you where to add a method with the same name as one already defined in the library your method will take precedence
41
+ over the predefined one, a warning message informing you about the conflict will be printed out through $stderr however.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 1
3
+ :patch: 1
4
+ :major: 0
@@ -0,0 +1,18 @@
1
+ module FFMpeg
2
+ module ClassMethods
3
+ def check_method(name)
4
+ print_error_message_for name if method_defined? name
5
+ end
6
+
7
+ def method_defined?(name)
8
+ FFMpeg.instance_methods.include?(name.to_s) || FFMpeg.instance_methods.include?(name.to_sym)
9
+ end
10
+ private :method_defined?
11
+
12
+ def print_error_message_for(name)
13
+ $stderr.puts "WARNING: Possible conflict with FFMpeg extension:" +
14
+ "FFMpeg##{name} already exists and will be overwritten"
15
+ end
16
+ private :print_error_message_for
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ module FFMpegCommand
2
+ extend self
3
+
4
+ @commands = []
5
+
6
+ def <<(cmd)
7
+ @commands << cmd
8
+ end
9
+
10
+ def add_at(cmd, pos)
11
+ @commands.insert(pos, cmd)
12
+ end
13
+
14
+ def clear
15
+ @commands.clear
16
+ end
17
+
18
+ def command(prefix="")
19
+ returning prefix.to_s do |prefix|
20
+ @commands.each do |command|
21
+ prefix << " #{command}"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ module FFMpeg
2
+ module HelperMethods
3
+ def returning(value)
4
+ yield value
5
+ return value
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,165 @@
1
+ module FFMpeg
2
+ module MainOptions
3
+
4
+ def source(*filename)
5
+ FFMpegCommand << "-i #{filename}"
6
+ end
7
+
8
+ def target(target)
9
+ FFMpegCommand << "#{target}"
10
+ end
11
+
12
+ #
13
+ # Overwrite output file if it already exists
14
+ #
15
+ def overwrite_existing_file
16
+ FFMpegCommand.add_at("-y", 0)
17
+ end
18
+
19
+ #
20
+ # Set the duration specified in seconds.
21
+ # hh:mm:ss[.xxx] syntax is also supported
22
+ #
23
+ # duration "600"
24
+ #
25
+ # or
26
+ #
27
+ # duration "00:10:00"
28
+ #
29
+ def duration(duration)
30
+ FFMpegCommand << "-t #{duration}"
31
+ end
32
+
33
+ #
34
+ # Set a file size limit in bytes
35
+ #
36
+ # file_size_limit 104_857_600
37
+ #
38
+ def file_size_limit(limit)
39
+ FFMpegCommand << "-fs #{limit.to_s}"
40
+ end
41
+
42
+ #
43
+ # Seek to given time position in seconds.
44
+ # hh:mm:ss[.xxx] syntax is also supported.
45
+ #
46
+ # seek "600"
47
+ #
48
+ # or
49
+ #
50
+ # seek "00:10:00"
51
+ #
52
+ def seek(position)
53
+ FFMpegCommand << "-ss #{position}"
54
+ end
55
+
56
+ #
57
+ # Set the input time offset in seconds.
58
+ # [-]hh:mm:ss[.xxx] syntax is also supported.
59
+ # This option affects all the input files that follow it.
60
+ # The offset is added to the timestamps of the input files.
61
+ # Specifying a positive offset means that the corresponding
62
+ # streams are delayed by 'offset' seconds.
63
+ #
64
+ # offset "600"
65
+ #
66
+ # or
67
+ #
68
+ # offset "00:10:00"
69
+ #
70
+ def offset(offset)
71
+ FFMpegCommand << "-itsoffset #{offset}"
72
+ end
73
+
74
+ #
75
+ # Set the title.
76
+ #
77
+ # title "Some Title"
78
+ #
79
+ def title(title)
80
+ FFMpegCommand << "-title '#{title}'"
81
+ end
82
+
83
+ #
84
+ # Set the author.
85
+ #
86
+ # author "PMH"
87
+ #
88
+ def author(author)
89
+ FFMpegCommand << "-author '#{author}'"
90
+ end
91
+
92
+ #
93
+ # Set the copyright.
94
+ #
95
+ # copyright "(c) Patrik Hedman 2009"
96
+ #
97
+ def copyright(copyright)
98
+ FFMpegCommand << "-copyright '#{copyright}'"
99
+ end
100
+
101
+ #
102
+ # Set the comment.
103
+ #
104
+ # comment "Some comment"
105
+ #
106
+ def comment(comment)
107
+ FFMpegCommand << "-comment '#{comment}'"
108
+ end
109
+
110
+ #
111
+ # Set the album.
112
+ #
113
+ # album "An awesome album"
114
+ #
115
+ def album(album)
116
+ FFMpegCommand << "-album '#{album}'"
117
+ end
118
+
119
+ #
120
+ # Set the track number:
121
+ #
122
+ # track 1
123
+ #
124
+ def track(track)
125
+ FFMpegCommand << "-track #{track}"
126
+ end
127
+
128
+ #
129
+ # Set the year.
130
+ #
131
+ # year 1985
132
+ #
133
+ def year(year)
134
+ FFMpegCommand << "-year #{year}"
135
+ end
136
+
137
+ #
138
+ # Specify target file type ("vcd", "svcd", "dvd", "dv", "dv50", "pal-vcd", "ntsc-svcd", ... ).
139
+ # All the format options (bitrate, codecs, buffer sizes) are then set automatically.
140
+ # Nevertheless you can specify additional options as long as you know they do not conflict
141
+ # with the standard.
142
+ #
143
+ # target "vcd"
144
+ #
145
+ def target(target)
146
+ FFMpegCommand << "-target #{target}"
147
+ end
148
+
149
+ #
150
+ # Set the number of frames to record.
151
+ #
152
+ # frames_to_record 50
153
+ #
154
+ def frames_to_record(frames)
155
+ FFMpegCommand << "-dframes #{frames}"
156
+ end
157
+
158
+ #
159
+ # Force subtitle codec ('copy' to copy stream)
160
+ #
161
+ def subtitle_codec(codec)
162
+ FFMpegCommand << "-scodec #{codec}"
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,70 @@
1
+ module FFMpeg
2
+ module VideoOptions
3
+ #
4
+ # Set frame size. The format is `wxh' (ffserver default = 160x128, ffmpeg default = same as source).
5
+ # The following abbreviations are recognized:
6
+ #
7
+ # 'sqcif'
8
+ # 128x96
9
+ # 'qcif'
10
+ # 176x144
11
+ # 'cif'
12
+ # 352x288
13
+ # '4cif'
14
+ # 704x576
15
+ # 'qqvga'
16
+ # 160x120
17
+ # 'qvga'
18
+ # 320x240
19
+ # 'vga'
20
+ # 640x480
21
+ # 'svga'
22
+ # 800x600
23
+ # 'xga'
24
+ # 1024x768
25
+ # 'uxga'
26
+ # 1600x1200
27
+ # 'qxga'
28
+ # 2048x1536
29
+ # 'sxga'
30
+ # 1280x1024
31
+ # 'qsxga'
32
+ # 2560x2048
33
+ # 'hsxga'
34
+ # 5120x4096
35
+ # 'wvga'
36
+ # 852x480
37
+ # 'wxga'
38
+ # 1366x768
39
+ # 'wsxga'
40
+ # 1600x1024
41
+ # 'wuxga'
42
+ # 1920x1200
43
+ # 'woxga'
44
+ # 2560x1600
45
+ # 'wqsxga'
46
+ # 3200x2048
47
+ # 'wquxga'
48
+ # 3840x2400
49
+ # 'whsxga'
50
+ # 6400x4096
51
+ # 'whuxga'
52
+ # 7680x4800
53
+ # 'cga'
54
+ # 320x200
55
+ # 'ega'
56
+ # 640x350
57
+ # 'hd480'
58
+ # 852x480
59
+ # 'hd720'
60
+ # 1280x720
61
+ # 'hd1080'
62
+ # 1920x1080
63
+ #
64
+ #
65
+ #
66
+ def resolution(resolution)
67
+ FFMpegCommand << "-s #{resolution}"
68
+ end
69
+ end
70
+ end
data/lib/ffmpeg.rb ADDED
@@ -0,0 +1,80 @@
1
+ require 'ffmpeg/class_methods'
2
+ require 'ffmpeg/main_options'
3
+ require 'ffmpeg/video_options'
4
+ require 'ffmpeg/ffmpeg_command'
5
+ require 'ffmpeg/helper_methods'
6
+
7
+ module FFMpeg
8
+ include HelperMethods
9
+ include MainOptions
10
+ include VideoOptions
11
+
12
+ #
13
+ # When mixed into a class, extend
14
+ # it with the ClassMethods module
15
+ #
16
+ def self.included(klass)
17
+ klass.extend ClassMethods
18
+
19
+ #
20
+ # Everytime a method is added to the
21
+ # class, check for conflicts with existing
22
+ # module methods
23
+ #
24
+ def klass.method_added(name)
25
+ check_method(name) if method_checking_enabled?
26
+ end
27
+ end
28
+
29
+ #
30
+ # Sets up an FFmpegCommand for converting files:
31
+ #
32
+ # convert "file1.ext", :to => "file2.ext" do
33
+ # seek "00:03:00"
34
+ # duration "01:10:00"
35
+ # resolution "800x600"
36
+ # end
37
+ #
38
+ def convert(from_file, to_file = {})
39
+ FFMpegCommand << "-i #{from_file}"
40
+ FFMpegCommand << "#{to_file[:to]}" unless to_file[:to].nil?
41
+ begin
42
+ yield if block_given?
43
+ rescue Exception => exception
44
+ Thread.current[:'method checking enabled'] = true
45
+ raise exception
46
+ end
47
+ end
48
+
49
+ #
50
+ # Runs ffmpeg
51
+ #
52
+ def run
53
+ execute_command FFMpegCommand.command(locate_ffmpeg)
54
+ end
55
+
56
+ private
57
+
58
+ #
59
+ #
60
+ #
61
+ def method_checking_enabled?
62
+ !Thread.current[:'method checking enabled']
63
+ end
64
+
65
+ #
66
+ # Tries to locate the FFmpeg executable
67
+ #
68
+ def locate_ffmpeg
69
+ ffmpeg_executable = %x[which ffmpeg].strip
70
+ end
71
+
72
+ #
73
+ # Executes FFmpeg with the specified command
74
+ #
75
+ def execute_command(cmd)
76
+ puts "Executing: #{cmd}}"
77
+ %x[#{cmd}]
78
+ puts $?.success?
79
+ end
80
+ end
@@ -0,0 +1,162 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "FFMpeg" do
4
+ before(:each) do
5
+ @from_file, @to_file = "~/Desktop/test.avi", "~/Desktop/test2.avi"
6
+ FFMpegCommand.clear
7
+ end
8
+
9
+ it "should generate a valid command" do
10
+ convert @from_file, :to => @to_file
11
+
12
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file}")
13
+ end
14
+
15
+ it "should generate a valid command when fed an empty block" do
16
+ convert(@from_file, :to => @to_file) {}
17
+
18
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file}")
19
+ end
20
+ end
21
+
22
+ describe "FFMpeg Main Options" do
23
+ before(:each) do
24
+ @from_file, @to_file = "~/Desktop/test.avi", "~/Desktop/test2.avi"
25
+ FFMpegCommand.clear
26
+ end
27
+
28
+ it "should overwrite existing files" do
29
+ convert @from_file, :to => @to_file do
30
+ overwrite_existing_file
31
+ end
32
+
33
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -y -i #{@from_file} #{@to_file}")
34
+ end
35
+
36
+ it "should set a duration" do
37
+ convert @from_file, :to => @to_file do
38
+ duration "00:03:01"
39
+ end
40
+
41
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -t 00:03:01")
42
+ end
43
+
44
+ it "should set a file size limit" do
45
+ convert @from_file, :to => @to_file do
46
+ file_size_limit 104_857_600
47
+ end
48
+
49
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -fs 104857600")
50
+ end
51
+
52
+ it "should seek to the specified time position" do
53
+ convert @from_file, :to => @to_file do
54
+ seek "00:03:01"
55
+ end
56
+
57
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -ss 00:03:01")
58
+ end
59
+
60
+ it "should the input time offset" do
61
+ convert @from_file, :to => @to_file do
62
+ offset "00:03:01"
63
+ end
64
+
65
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -itsoffset 00:03:01")
66
+ end
67
+
68
+ it "should the title" do
69
+ convert @from_file, :to => @to_file do
70
+ title "Some Title"
71
+ end
72
+
73
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -title 'Some Title'")
74
+ end
75
+
76
+ it "should the author" do
77
+ convert @from_file, :to => @to_file do
78
+ author "PMH"
79
+ end
80
+
81
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -author 'PMH'")
82
+ end
83
+
84
+ it "should the copyright" do
85
+ convert @from_file, :to => @to_file do
86
+ copyright "(c) Patrik Hedman 2009"
87
+ end
88
+
89
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -copyright '(c) Patrik Hedman 2009'")
90
+ end
91
+
92
+ it "should the comment" do
93
+ convert @from_file, :to => @to_file do
94
+ comment "Some Comment"
95
+ end
96
+
97
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -comment 'Some Comment'")
98
+ end
99
+
100
+ it "should the album" do
101
+ convert @from_file, :to => @to_file do
102
+ album "An awesome album"
103
+ end
104
+
105
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -album 'An awesome album'")
106
+ end
107
+
108
+ it "should the track" do
109
+ convert @from_file, :to => @to_file do
110
+ track 1
111
+ end
112
+
113
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -track 1")
114
+ end
115
+
116
+ it "should the year" do
117
+ convert @from_file, :to => @to_file do
118
+ year 1985
119
+ end
120
+
121
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -year 1985")
122
+ end
123
+
124
+ it "should the target" do
125
+ convert @from_file, :to => @to_file do
126
+ target "vcd"
127
+ end
128
+
129
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -target vcd")
130
+ end
131
+
132
+ it "should the number of frames to record" do
133
+ convert @from_file, :to => @to_file do
134
+ frames_to_record 50
135
+ end
136
+
137
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -dframes 50")
138
+ end
139
+
140
+ it "should set the subtitle codec" do
141
+ convert @from_file, :to => @to_file do
142
+ subtitle_codec 'copy'
143
+ end
144
+
145
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -scodec copy")
146
+ end
147
+ end
148
+
149
+ describe "FFMpeg Video Options" do
150
+ before(:each) do
151
+ @from_file, @to_file = "~/Desktop/test.avi", "~/Desktop/test2.avi"
152
+ FFMpegCommand.clear
153
+ end
154
+
155
+ it "should set the resolution" do
156
+ convert @from_file, :to => @to_file do
157
+ resolution "vga"
158
+ end
159
+
160
+ FFMpegCommand.command("ffmpeg").should eql("ffmpeg -i #{@from_file} #{@to_file} -s vga")
161
+ end
162
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+
6
+ require 'ffmpeg'
7
+ include FFMpeg
8
+
9
+ Spec::Runner.configure do |config|
10
+
11
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: polly-ffmpeg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Patrik Hedman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-17 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: TODO
17
+ email: patrik@moresale.se
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.rdoc
26
+ - VERSION.yml
27
+ - lib/ffmpeg
28
+ - lib/ffmpeg/class_methods.rb
29
+ - lib/ffmpeg/ffmpeg_command.rb
30
+ - lib/ffmpeg/helper_methods.rb
31
+ - lib/ffmpeg/main_options.rb
32
+ - lib/ffmpeg/video_options.rb
33
+ - lib/ffmpeg.rb
34
+ - spec/ffmpeg_spec.rb
35
+ - spec/spec_helper.rb
36
+ has_rdoc: true
37
+ homepage: http://github.com/polly/ffmpeg
38
+ post_install_message:
39
+ rdoc_options:
40
+ - --inline-source
41
+ - --charset=UTF-8
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.2.0
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: TODO
63
+ test_files: []
64
+