enigmamachine 0.4.3 → 0.5.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/Rakefile CHANGED
@@ -9,14 +9,15 @@ begin
9
9
  gem.description = %Q{A RESTful video encoder which you can use as either a front-end to ffmpeg or headless on a server.}
10
10
  gem.email = "dave@caprica"
11
11
  gem.homepage = "http://github.com/futurechimp/enigmamachine"
12
- gem.authors = ["Dave Hrycyszyn"]
12
+ gem.authors = ["Dave Hrycyszyn", "Dmitry Brazhkin"]
13
13
  gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
- gem.add_dependency "data_mapper", "=1.0.0"
15
- gem.add_dependency "eventmachine", "=0.12.10"
16
- gem.add_dependency "dm-sqlite-adapter", "=1.0.0"
14
+ gem.add_dependency "data_mapper", ">=1.0.2"
15
+ gem.add_dependency "dm-sqlite-adapter", ">=1.0.2"
16
+ gem.add_dependency "eventmachine", ">=0.12.10"
17
17
  gem.add_dependency "rack-flash"
18
18
  gem.add_dependency "ruby-debug"
19
- gem.add_dependency "sinatra", "=1.0.0"
19
+ gem.add_dependency "sinatra", ">=1.0.0"
20
+ gem.add_dependency "streamio-ffmpeg", ">=0.7.3"
20
21
  gem.add_dependency "thin"
21
22
 
22
23
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.3
1
+ 0.5.0
data/bin/enigmamachine CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Enigmamachine command line interface script.
4
4
  # Run <tt>enigmamachine -h</tt> to get more usage.
5
- require File.dirname(__FILE__) + '/../lib/enigmamachine'
5
+ require 'rubygems'
6
6
  require 'thin'
7
7
 
8
8
  rackup_file = "#{File.dirname(__FILE__)}/../lib/enigmamachine/config.ru"
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{enigmamachine}
8
- s.version = "0.4.3"
8
+ s.version = "0.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Dave Hrycyszyn"]
12
- s.date = %q{2010-09-15}
11
+ s.authors = ["Dave Hrycyszyn", "Dmitry Brazhkin"]
12
+ s.date = %q{2010-10-04}
13
13
  s.default_executable = %q{enigmamachine}
14
14
  s.description = %q{A RESTful video encoder which you can use as either a front-end to ffmpeg or headless on a server.}
15
15
  s.email = %q{dave@caprica}
@@ -76,48 +76,51 @@ Gem::Specification.new do |s|
76
76
  s.homepage = %q{http://github.com/futurechimp/enigmamachine}
77
77
  s.rdoc_options = ["--charset=UTF-8"]
78
78
  s.require_paths = ["lib"]
79
- s.rubygems_version = %q{1.3.7}
79
+ s.rubygems_version = %q{1.3.6}
80
80
  s.summary = %q{A RESTful video encoder.}
81
81
  s.test_files = [
82
- "test/helper.rb",
83
- "test/test_enigmamachine.rb",
84
- "test/support/blueprints.rb",
82
+ "test/support/blueprints.rb",
83
+ "test/helper.rb",
85
84
  "test/test_encoding_queue.rb",
85
+ "test/test_video.rb",
86
86
  "test/test_encoder.rb",
87
- "test/test_video.rb"
87
+ "test/test_enigmamachine.rb"
88
88
  ]
89
89
 
90
90
  if s.respond_to? :specification_version then
91
91
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
92
92
  s.specification_version = 3
93
93
 
94
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
94
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
95
95
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
96
- s.add_runtime_dependency(%q<data_mapper>, ["= 1.0.0"])
97
- s.add_runtime_dependency(%q<eventmachine>, ["= 0.12.10"])
98
- s.add_runtime_dependency(%q<dm-sqlite-adapter>, ["= 1.0.0"])
96
+ s.add_runtime_dependency(%q<data_mapper>, [">= 1.0.2"])
97
+ s.add_runtime_dependency(%q<dm-sqlite-adapter>, [">= 1.0.2"])
98
+ s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.10"])
99
99
  s.add_runtime_dependency(%q<rack-flash>, [">= 0"])
100
100
  s.add_runtime_dependency(%q<ruby-debug>, [">= 0"])
101
- s.add_runtime_dependency(%q<sinatra>, ["= 1.0.0"])
101
+ s.add_runtime_dependency(%q<sinatra>, [">= 1.0.0"])
102
+ s.add_runtime_dependency(%q<streamio-ffmpeg>, [">= 0.7.3"])
102
103
  s.add_runtime_dependency(%q<thin>, [">= 0"])
103
104
  else
104
105
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
105
- s.add_dependency(%q<data_mapper>, ["= 1.0.0"])
106
- s.add_dependency(%q<eventmachine>, ["= 0.12.10"])
107
- s.add_dependency(%q<dm-sqlite-adapter>, ["= 1.0.0"])
106
+ s.add_dependency(%q<data_mapper>, [">= 1.0.2"])
107
+ s.add_dependency(%q<dm-sqlite-adapter>, [">= 1.0.2"])
108
+ s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
108
109
  s.add_dependency(%q<rack-flash>, [">= 0"])
109
110
  s.add_dependency(%q<ruby-debug>, [">= 0"])
110
- s.add_dependency(%q<sinatra>, ["= 1.0.0"])
111
+ s.add_dependency(%q<sinatra>, [">= 1.0.0"])
112
+ s.add_dependency(%q<streamio-ffmpeg>, [">= 0.7.3"])
111
113
  s.add_dependency(%q<thin>, [">= 0"])
112
114
  end
113
115
  else
114
116
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
115
- s.add_dependency(%q<data_mapper>, ["= 1.0.0"])
116
- s.add_dependency(%q<eventmachine>, ["= 0.12.10"])
117
- s.add_dependency(%q<dm-sqlite-adapter>, ["= 1.0.0"])
117
+ s.add_dependency(%q<data_mapper>, [">= 1.0.2"])
118
+ s.add_dependency(%q<dm-sqlite-adapter>, [">= 1.0.2"])
119
+ s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
118
120
  s.add_dependency(%q<rack-flash>, [">= 0"])
119
121
  s.add_dependency(%q<ruby-debug>, [">= 0"])
120
- s.add_dependency(%q<sinatra>, ["= 1.0.0"])
122
+ s.add_dependency(%q<sinatra>, [">= 1.0.0"])
123
+ s.add_dependency(%q<streamio-ffmpeg>, [">= 0.7.3"])
121
124
  s.add_dependency(%q<thin>, [">= 0"])
122
125
  end
123
126
  end
data/lib/enigmamachine.rb CHANGED
@@ -10,6 +10,7 @@ require 'dm-validations'
10
10
  require 'dm-migrations'
11
11
  require 'open3'
12
12
  require 'logger'
13
+ require 'streamio-ffmpeg'
13
14
 
14
15
  # Extensions to Sinatra
15
16
  #
@@ -270,5 +271,13 @@ class EnigmaMachine < Sinatra::Base
270
271
  end
271
272
  end
272
273
 
274
+ # Deletes a video.
275
+ #
276
+ delete '/videos/:id' do |id|
277
+ @video = Video.get(id)
278
+ @video.destroy
279
+ redirect "/videos"
280
+ end
281
+
273
282
  end
274
283
 
@@ -6,6 +6,7 @@ class EncodingQueue
6
6
  # starts looking for unencoded videos.
7
7
  #
8
8
  def initialize
9
+ @threads = YAML.load_file(Dir.getwd + '/config.yml')['threads'] if @threads.nil?
9
10
  EM.add_periodic_timer(5) {
10
11
  encode_next_video
11
12
  }
@@ -15,7 +16,7 @@ class EncodingQueue
15
16
  # Gets the next unencoded Video from the database and starts encoding it.
16
17
  #
17
18
  def encode_next_video
18
- if Video.unencoded.count > 0 && ::Video.encoding.count == 0
19
+ if Video.unencoded.count > 0 && ::Video.encoding.count < @threads
19
20
  video = Video.unencoded.first
20
21
  begin
21
22
  video.encoder.encode(video)
@@ -33,20 +33,16 @@ class Encoder
33
33
  #
34
34
  def ffmpeg(task, video)
35
35
  current_task_index = encoding_tasks.index(task)
36
- command_string = "ffmpeg -y -i #{video.file} #{task.command} #{video.file + task.output_file_suffix}"
36
+ movie = FFMPEG::Movie.new(video.file)
37
37
  encoding_operation = proc {
38
- video.state = "encoding"
39
- video.save
40
- Open3.popen3 "nice -n 19 #{command_string}" do |stdin, stdout, stderr|
41
- while stderr.gets()
42
- puts stderr.gets
43
- end
38
+ video.update(:state => 'encoding')
39
+ movie.transcode(video.file + task.output_file_suffix, task.command) do |p|
40
+ puts p*100
44
41
  end
45
42
  }
46
43
  completion_callback = proc {|result|
47
44
  if task == encoding_tasks.last
48
- video.state = "complete"
49
- video.save
45
+ video.update(:state => 'complete')
50
46
  video.notify_complete
51
47
  else
52
48
  next_task_index = current_task_index + 1
@@ -16,8 +16,15 @@ class Video
16
16
  property :encoder_id, Integer, :required => true
17
17
  property :callback_url, String
18
18
 
19
+ validates_with_method :file, :method => :check_file
20
+ validates_uniqueness_of :file, :scope => :encoder_id,
21
+ :message => "Same file with same encoder already exists"
19
22
  belongs_to :encoder
20
23
 
24
+ before :destroy, :check_destroy
25
+
26
+ default_scope(:default).update(:order => [:created_at.asc])
27
+
21
28
  # Notifies a calling application that processing has completed by sending
22
29
  # a GET request to the video's callback_url.
23
30
  #
@@ -68,5 +75,29 @@ class Video
68
75
  end
69
76
  end
70
77
 
78
+ private
79
+
80
+ def check_file
81
+ return [false, "Give a file name, not nil"] if self.file.nil?
82
+ return [false, "Give a file name, not a blank string"] if self.file.to_s.empty?
83
+ return [false, "#{self.file} does not exist"] unless File.exist? self.file
84
+ return [false, "#{self.file} is a directory"] if File.directory? self.file
85
+ movie = FFMPEG::Movie.new(self.file)
86
+ return [false, "#{self.file} is not a media file"] unless movie.valid?
87
+ return true
88
+ end
89
+
90
+ def check_destroy
91
+ return true if (self.state != 'encoding')
92
+ encoder = Encoder.get(self.encoder_id)
93
+ return true if stop_encode
94
+ throw :halt
95
+ end
96
+
97
+ def stop_encode
98
+ return false
99
+ #TODO Kill the encoder process
100
+ end
101
+
71
102
  end
72
103
 
@@ -1,6 +1,11 @@
1
1
  <% video = videos_video %>
2
2
  <li>
3
3
  <strong><%= video.state %></strong> - <%=h video.file %> -
4
- created at <%=h video.created_at.strftime("%m/%d/%Y at %H:%M:%S")%><br/>
4
+ created at <%=h video.created_at.strftime("%m/%d/%Y at %H:%M:%S")%>
5
+ <form action="/videos/<%= video.id %>" method="POST">
6
+ <input name="_method" value="DELETE" type="hidden"/>
7
+ <input type="submit" value="Delete"/>
8
+ </form>
9
+ <br/>
5
10
  </li>
6
11
 
@@ -1,3 +1,3 @@
1
1
  username: admin
2
2
  password: admin
3
-
3
+ threads: 1
@@ -3,7 +3,7 @@ require 'faker'
3
3
  require 'sham'
4
4
 
5
5
  Encoder.blueprint do
6
- name {"Blah encoder"}
6
+ name { Faker::Name.name }
7
7
  end
8
8
 
9
9
  Video.blueprint do
@@ -21,13 +21,13 @@ end
21
21
  EncodingTask.blueprint do
22
22
  name { "320x240 flv"}
23
23
  output_file_suffix { ".foo.flv" }
24
- command { "-ss 00:00:02 -t 00:00:01 -vcodec mjpeg -vframes 1 -an -f rawvideo -s 180x136 -y"}
24
+ command { "-ss 00:00:02 -t 00:00:01 -vcodec mjpeg -vframes 1 -an -f rawvideo -s 180x136"}
25
25
  end
26
26
 
27
27
  EncodingTask.blueprint(:with_encoder) do
28
28
  name { "320x240 flv"}
29
29
  output_file_suffix { ".foo.flv" }
30
- command { "-ss 00:00:02 -t 00:00:01 -vcodec mjpeg -vframes 1 -an -f rawvideo -s 180x136 -y"}
30
+ command { "-ss 00:00:02 -t 00:00:01 -vcodec mjpeg -vframes 1 -an -f rawvideo -s 180x136"}
31
31
  encoder
32
32
  end
33
33
 
data/test/test_video.rb CHANGED
@@ -5,12 +5,18 @@ class TestVideo < Test::Unit::TestCase
5
5
 
6
6
  context "A Video instance" do
7
7
 
8
- should "be invalid without a file path" do
8
+ should "be invalid with a bad file path" do
9
9
  resource = ::Video.make
10
10
  resource.file = ""
11
- assert !resource.valid?
11
+ assert(!resource.valid?, "must not be empty")
12
12
  resource.file = nil
13
- assert !resource.valid?
13
+ assert(!resource.valid?, "must not be nil")
14
+ resource.file = "/fdfdf/sfdsdfsd/fse.gfr"
15
+ assert(!resource.valid?, "must be exist")
16
+ resource.file = File.dirname(__FILE__)
17
+ assert(!resource.valid?, "must not be a directory")
18
+ resource.file = __FILE__
19
+ assert(!resource.valid?, "must be media file")
14
20
  end
15
21
 
16
22
  should "be valid without a callback_url" do
@@ -27,9 +33,8 @@ class TestVideo < Test::Unit::TestCase
27
33
  assert resource.valid?
28
34
  end
29
35
 
30
- should "be valid with a file path" do
36
+ should "be valid with a correct file path" do
31
37
  resource = ::Video.make
32
- resource.file = "foo.mpg"
33
38
  assert resource.valid?
34
39
  end
35
40
 
@@ -76,6 +81,48 @@ class TestVideo < Test::Unit::TestCase
76
81
  end
77
82
  end
78
83
 
84
+ context "when try to delete any kind of videos from base" do
85
+ setup do
86
+ clear_videos
87
+ 5.times { Video.make }
88
+ end
89
+
90
+ should "be delete an unencoded videos" do
91
+ count = Video.unencoded.count
92
+ 2.times { Video.unencoded.first.destroy }
93
+ assert_equal count - 2, Video.unencoded.count
94
+ end
95
+
96
+ should "be delete a completed videos" do
97
+ 3.times { Video.unencoded.first.update(:state => "complete") }
98
+ count = Video.complete.count
99
+ 2.times { Video.complete.first.destroy }
100
+ assert_equal count - 2, Video.complete.count
101
+ end
102
+
103
+ should "be delete a videos with errors" do
104
+ 3.times { Video.unencoded.first.update(:state => "error") }
105
+ count = Video.with_errors.count
106
+ 2.times { Video.with_errors.first.destroy }
107
+ assert_equal count - 2, Video.with_errors.count
108
+ end
109
+
110
+ should "not be delete an encoding videos" do
111
+ 3.times { Video.unencoded.first.update(:state => "encoding") }
112
+ count = Video.encoding.count
113
+ 2.times { Video.encoding.first.destroy }
114
+ assert_equal count, Video.encoding.count
115
+ end
116
+
117
+ should "be hard delete an encoding videos" do
118
+ 3.times { Video.unencoded.first.update(:state => "encoding") }
119
+ count = Video.encoding.count
120
+ 2.times { Video.encoding.first.destroy! }
121
+ assert_equal count - 2, Video.encoding.count
122
+ end
123
+
124
+ end
125
+
79
126
  should "be able to grab all completed videos" do
80
127
  assert Video.respond_to? "complete"
81
128
  end
@@ -91,7 +138,7 @@ class TestVideo < Test::Unit::TestCase
91
138
  end
92
139
 
93
140
  def clear_videos
94
- Video.all.each {|v| v.destroy }
141
+ Video.all.each {|v| v.destroy! }
95
142
  end
96
143
 
97
144
  end
metadata CHANGED
@@ -1,32 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enigmamachine
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 4
9
- - 3
10
- version: 0.4.3
7
+ - 5
8
+ - 0
9
+ version: 0.5.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Dave Hrycyszyn
13
+ - Dmitry Brazhkin
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-09-15 00:00:00 +01:00
18
+ date: 2010-10-04 00:00:00 +01:00
19
19
  default_executable: enigmamachine
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: thoughtbot-shoulda
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
25
  requirements:
27
26
  - - ">="
28
27
  - !ruby/object:Gem::Version
29
- hash: 3
30
28
  segments:
31
29
  - 0
32
30
  version: "0"
@@ -36,59 +34,51 @@ dependencies:
36
34
  name: data_mapper
37
35
  prerelease: false
38
36
  requirement: &id002 !ruby/object:Gem::Requirement
39
- none: false
40
37
  requirements:
41
- - - "="
38
+ - - ">="
42
39
  - !ruby/object:Gem::Version
43
- hash: 23
44
40
  segments:
45
41
  - 1
46
42
  - 0
47
- - 0
48
- version: 1.0.0
43
+ - 2
44
+ version: 1.0.2
49
45
  type: :runtime
50
46
  version_requirements: *id002
51
47
  - !ruby/object:Gem::Dependency
52
- name: eventmachine
48
+ name: dm-sqlite-adapter
53
49
  prerelease: false
54
50
  requirement: &id003 !ruby/object:Gem::Requirement
55
- none: false
56
51
  requirements:
57
- - - "="
52
+ - - ">="
58
53
  - !ruby/object:Gem::Version
59
- hash: 59
60
54
  segments:
55
+ - 1
61
56
  - 0
62
- - 12
63
- - 10
64
- version: 0.12.10
57
+ - 2
58
+ version: 1.0.2
65
59
  type: :runtime
66
60
  version_requirements: *id003
67
61
  - !ruby/object:Gem::Dependency
68
- name: dm-sqlite-adapter
62
+ name: eventmachine
69
63
  prerelease: false
70
64
  requirement: &id004 !ruby/object:Gem::Requirement
71
- none: false
72
65
  requirements:
73
- - - "="
66
+ - - ">="
74
67
  - !ruby/object:Gem::Version
75
- hash: 23
76
68
  segments:
77
- - 1
78
69
  - 0
79
- - 0
80
- version: 1.0.0
70
+ - 12
71
+ - 10
72
+ version: 0.12.10
81
73
  type: :runtime
82
74
  version_requirements: *id004
83
75
  - !ruby/object:Gem::Dependency
84
76
  name: rack-flash
85
77
  prerelease: false
86
78
  requirement: &id005 !ruby/object:Gem::Requirement
87
- none: false
88
79
  requirements:
89
80
  - - ">="
90
81
  - !ruby/object:Gem::Version
91
- hash: 3
92
82
  segments:
93
83
  - 0
94
84
  version: "0"
@@ -98,11 +88,9 @@ dependencies:
98
88
  name: ruby-debug
99
89
  prerelease: false
100
90
  requirement: &id006 !ruby/object:Gem::Requirement
101
- none: false
102
91
  requirements:
103
92
  - - ">="
104
93
  - !ruby/object:Gem::Version
105
- hash: 3
106
94
  segments:
107
95
  - 0
108
96
  version: "0"
@@ -112,11 +100,9 @@ dependencies:
112
100
  name: sinatra
113
101
  prerelease: false
114
102
  requirement: &id007 !ruby/object:Gem::Requirement
115
- none: false
116
103
  requirements:
117
- - - "="
104
+ - - ">="
118
105
  - !ruby/object:Gem::Version
119
- hash: 23
120
106
  segments:
121
107
  - 1
122
108
  - 0
@@ -125,19 +111,31 @@ dependencies:
125
111
  type: :runtime
126
112
  version_requirements: *id007
127
113
  - !ruby/object:Gem::Dependency
128
- name: thin
114
+ name: streamio-ffmpeg
129
115
  prerelease: false
130
116
  requirement: &id008 !ruby/object:Gem::Requirement
131
- none: false
132
117
  requirements:
133
118
  - - ">="
134
119
  - !ruby/object:Gem::Version
135
- hash: 3
136
120
  segments:
137
121
  - 0
138
- version: "0"
122
+ - 7
123
+ - 3
124
+ version: 0.7.3
139
125
  type: :runtime
140
126
  version_requirements: *id008
127
+ - !ruby/object:Gem::Dependency
128
+ name: thin
129
+ prerelease: false
130
+ requirement: &id009 !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ segments:
135
+ - 0
136
+ version: "0"
137
+ type: :runtime
138
+ version_requirements: *id009
141
139
  description: A RESTful video encoder which you can use as either a front-end to ffmpeg or headless on a server.
142
140
  email: dave@caprica
143
141
  executables:
@@ -211,34 +209,30 @@ rdoc_options:
211
209
  require_paths:
212
210
  - lib
213
211
  required_ruby_version: !ruby/object:Gem::Requirement
214
- none: false
215
212
  requirements:
216
213
  - - ">="
217
214
  - !ruby/object:Gem::Version
218
- hash: 3
219
215
  segments:
220
216
  - 0
221
217
  version: "0"
222
218
  required_rubygems_version: !ruby/object:Gem::Requirement
223
- none: false
224
219
  requirements:
225
220
  - - ">="
226
221
  - !ruby/object:Gem::Version
227
- hash: 3
228
222
  segments:
229
223
  - 0
230
224
  version: "0"
231
225
  requirements: []
232
226
 
233
227
  rubyforge_project:
234
- rubygems_version: 1.3.7
228
+ rubygems_version: 1.3.6
235
229
  signing_key:
236
230
  specification_version: 3
237
231
  summary: A RESTful video encoder.
238
232
  test_files:
239
- - test/helper.rb
240
- - test/test_enigmamachine.rb
241
233
  - test/support/blueprints.rb
234
+ - test/helper.rb
242
235
  - test/test_encoding_queue.rb
243
- - test/test_encoder.rb
244
236
  - test/test_video.rb
237
+ - test/test_encoder.rb
238
+ - test/test_enigmamachine.rb