tootsie 0.9.13 → 0.9.14

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,14 +1,9 @@
1
1
  Tootsie
2
2
  =======
3
3
 
4
- Tootsie (formerly called Tranz) is a simple audio/video/image transcoding/modification application written in Ruby. It can transcode audio, video and images between different formats, and also perform basic manipulations such as scaling.
4
+ Tootsie (formerly called Tranz) is a simple, robust, scalable audio/video/image transcoding/modification application.
5
5
 
6
- Tootsie has the following external dependencies:
7
-
8
- * FFmpeg for transcoding of video and audio.
9
- * ImageMagick/GraphicsMagick for image conversion.
10
- * Amazon S3 for loading and storage of files (optional).
11
- * Amazon Simple Queue Service for internal task queue management (optional).
6
+ Tootsie can transcode audio, video and images between different formats, and also perform basic manipulations such as photo scaling and cropping, for generating thumbnails and photos at different resolutions.
12
7
 
13
8
  Overview
14
9
  --------
@@ -17,14 +12,18 @@ Tootsie is divided into multiple independent parts:
17
12
 
18
13
  * Job manager: finds new transcoding jobs and executes them.
19
14
  * FFmpeg, ImageMagick: performs the actual transcoding.
20
- * Queue: currently local file-based queues (for testing) and Amazon Simple Queue Service are supported.
21
- * Storage: currently web servers and Amazon S3 are supported.
15
+ * Queue: stores pending tasks.
16
+ * Storage: loads and saves the file data.
22
17
  * Web service: A small RESTful API for managing jobs.
23
18
 
19
+ For storage, Tootsie supports web resources (ie., reading with HTTP GET, writing with HTTP POST) and Amazon S3 buckets.
20
+
21
+ For queues, Tootsie supports local file-based queues (mostly suitable for testing), AMQP queues (eg., RabbitMQ) and Amazon Simple Queue Service (aka SQS).
22
+
24
23
  The framework is designed to be easily pluggable, and to let you pick the parts you need to build a custom transcoding service. It is also designed to be easily distributed across many nodes.
25
24
 
26
- Execution flow
27
- --------------
25
+ Jobs
26
+ ----
28
27
 
29
28
  The task manager pops jobs from a queue and processes them. Each job specifies an input, an output, and transcoding parameters. Optionally the job may also specify a notification URL which is invoked to inform the caller about job progress.
30
29
 
@@ -51,7 +50,7 @@ FFmpeg and ImageMagick are invoked for each job to perform the transcoding. Thes
51
50
  API
52
51
  ===
53
52
 
54
- To schedule jobs, one uses the web service, a small app that supports job control methods:
53
+ To schedule jobs, one uses the REST service:
55
54
 
56
55
  * POST `/job`: Schedule a job. Returns 201 if the job was created.
57
56
  * GET `/status`: Get current processing status as a JSON hash.
@@ -61,27 +60,9 @@ The job must be posted as an JSON hash with the content type `application/json`.
61
60
  * `type`: Type of job. See sections below for details.
62
61
  * `notification_url`: Optional notification URL. Progress (including completion and failure) will be reported using POSTs.
63
62
  * `retries`: Maximum number of retries, if any. Defaults to 5.
64
- * `access_key`: Access key for calculating notification signature. See below.
65
63
 
66
64
  Job-specific parameters are provided in the key `params`.
67
65
 
68
- Access key
69
- ----------
70
-
71
- (This part has not been written yet. Nor implemented, actually.)
72
-
73
- Notifications
74
- -------------
75
-
76
- If a notification URL is provided, events will be sent to it using `POST` requests as JSON data. These are 'fire and forget' and will currently not be retried on failure, and the response status code is ignored.
77
-
78
- There are several types of events, indicated by the `event` key:
79
-
80
- * `started`: The job was started.
81
- * `complete`: The job was complete. The key `time_taken` will contain the time taken for the job, in seconds. Additional data will be provided that are specific to the type of job.
82
- * `failed`: The job failed. The key `reason` will contain a textual explanation for the failure.
83
- * `failed_will_retry`: The job failed, but is being rescheduled for retrying. The key `reason` will contain a textual explanation for the failure.
84
-
85
66
  Video transcoding jobs
86
67
  ----------------------
87
68
 
@@ -152,8 +133,22 @@ Completion notification provides the following data:
152
133
  * `height`: height, in pixels, of original image.
153
134
  * `depth`: depth, in bits, of original image.
154
135
 
155
- Note about S3 URLs
156
- ------------------
136
+ Notifications
137
+ -------------
138
+
139
+ If a notification URL is provided, events will be sent to it using `POST` requests as JSON data. These are 'fire and forget' and will currently not be retried on failure, and the response status code is ignored.
140
+
141
+ There are several types of events, indicated by the `event` key:
142
+
143
+ * `started`: The job was started.
144
+ * `complete`: The job was complete. The key `time_taken` will contain the time taken for the job, in seconds. Additional data will be provided that are specific to the type of job.
145
+ * `failed`: The job failed. The key `reason` will contain a textual explanation for the failure.
146
+ * `failed_will_retry`: The job failed, but is being rescheduled for retrying. The key `reason` will contain a textual explanation for the failure.
147
+
148
+ Resource URLs
149
+ -------------
150
+
151
+ Tootsie supports referring to inputs and outputs using URLs, namely `file:` and `http:`. Additionally, Tootsie supports its own proprietary S3 URL format.
157
152
 
158
153
  To specify S3 URLs, we use a custom URI format:
159
154
 
@@ -186,8 +181,7 @@ Current limitations
186
181
  Requirements
187
182
  ============
188
183
 
189
- * Ruby 1.9.1 or later.
190
- * Bundler.
184
+ * Ruby 1.8.7 or later.
191
185
 
192
186
  For video jobs:
193
187
 
@@ -199,12 +193,15 @@ For image jobs:
199
193
  * Exiv2
200
194
  * pngcrush (optional)
201
195
 
196
+ Optional dependencies:
197
+
198
+ * Amazon S3 for loading and storage of files.
199
+ * AMQP-compliant server (such as RabbitMQ) or Amazon Simple Queue Service for internal task queue management.
200
+
202
201
  Installation
203
202
  ============
204
203
 
205
- * Fetch Git repositroy: `git clone git@github.com:origo/tootsie.git`.
206
- * Install Bundler with `gem install bundler`.
207
- * Install dependencies with `cd tootsie; bundle install`.
204
+ `gem install tootsie`
208
205
 
209
206
  Running
210
207
  =======
@@ -212,9 +209,11 @@ Running
212
209
  Create a configuration, eg. `tootsie.conf`:
213
210
 
214
211
  ---
212
+ queue:
213
+ adapter: sqs
214
+ queue: tootise
215
215
  aws_access_key_id: <your Amazon key>
216
216
  aws_secret_access_key: <your Amazon secret>
217
- sqs_queue_name: tootsie
218
217
  pid_path: <where to write pid file>
219
218
  log_path: <where to write log file>
220
219
  worker_count: <number of workers>
@@ -234,7 +233,7 @@ Jobs may now be posted to the web service API. For example:
234
233
  'notification_url': 'http://example.com/transcoder_notification',
235
234
  'params': {
236
235
  'input_url': 'http://example.com/test.3gp',
237
- 'outputs': {
236
+ 'versions': {
238
237
  'target_url': 's3:mybucket/test.mp4?acl=public_read',
239
238
  'audio_sample_rate': 44100,
240
239
  'audio_bitrate': 64000,
@@ -250,7 +249,7 @@ License
250
249
 
251
250
  This software is licensed under the MIT License.
252
251
 
253
- Copyright © 2010, 2011 Alexander Staubo
252
+ Copyright © 2010, 2011, 2012 Alexander Staubo
254
253
 
255
254
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
256
255
 
data/Tootsie.gemspec CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.add_runtime_dependency 'xml-simple', ['~> 1.0.12']
28
28
  s.add_runtime_dependency 'thin', ['~> 1.2.7']
29
29
  s.add_runtime_dependency 's3', ['~> 0.3.8']
30
+ s.add_runtime_dependency 'bunny', ['~> 0.7.8']
30
31
  s.add_runtime_dependency 'sqs', ['~> 0.1.2']
31
32
  s.add_runtime_dependency 'unicorn', ['~> 4.1.1']
32
33
  s.add_runtime_dependency 'i18n', ['>= 0.4.2']
data/config.ru CHANGED
@@ -7,10 +7,4 @@ config_path ||= '/etc/tootsie/tootsie.conf'
7
7
  app = Tootsie::Application.new(:logger => ENV["rack.logger"])
8
8
  app.configure!(config_path)
9
9
 
10
- if ENV['RACK_ENV'] == 'development'
11
- Thread.new do
12
- Tootsie::Application.get.task_manager.run!
13
- end
14
- end
15
-
16
10
  run Tootsie::WebService
@@ -18,21 +18,37 @@ module Tootsie
18
18
  else
19
19
  @logger = Logger.new($stderr)
20
20
  end
21
- @queue = Tootsie::SqsQueue.new(@configuration.sqs_queue_name, sqs_service)
21
+ @logger.info "Starting"
22
+
23
+ queue_options = @configuration.queue_options ||= {}
24
+
25
+ adapter = (queue_options[:adapter] || 'sqs').to_s
26
+ case adapter
27
+ when 'sqs'
28
+ @queue = Tootsie::SqsQueue.new(
29
+ queue_options[:queue],
30
+ @configuration.aws_access_key_id,
31
+ @configuration.aws_secret_access_key)
32
+ when 'amqp'
33
+ @queue = Tootsie::AmqpQueue.new(
34
+ queue_options[:host],
35
+ queue_options[:queue])
36
+ when 'file'
37
+ @queue = Tootsie::FileSystemQueue.new(queue_options[:root])
38
+ else
39
+ raise 'Invalid queue configuration'
40
+ end
41
+
22
42
  @task_manager = TaskManager.new(@queue)
23
43
  end
24
44
 
25
45
  def s3_service
46
+ abort "AWS access key and secret required" unless
47
+ @configuration.aws_access_key_id and @configuration.aws_secret_access_key
26
48
  return @s3_service ||= ::S3::Service.new(
27
49
  :access_key_id => @configuration.aws_access_key_id,
28
50
  :secret_access_key => @configuration.aws_secret_access_key)
29
51
  end
30
-
31
- def sqs_service
32
- return @sqs_service ||= ::Sqs::Service.new(
33
- :access_key_id => @configuration.aws_access_key_id,
34
- :secret_access_key => @configuration.aws_secret_access_key)
35
- end
36
52
 
37
53
  class << self
38
54
  def get
@@ -5,28 +5,34 @@ module Tootsie
5
5
  def initialize
6
6
  @ffmpeg_thread_count = 1
7
7
  @worker_count = 4
8
- @sqs_queue_name = 'tootsie'
8
+ @queue_options = {}
9
9
  end
10
10
 
11
11
  def load_from_file(file_name)
12
12
  config = (YAML.load(File.read(file_name)) || {}).with_indifferent_access
13
- [:aws_access_key_id, :aws_secret_access_key, :ffmpeg_thread_count,
14
- :sqs_queue_name, :worker_count, :pid_path, :log_path].each do |key|
13
+ [:ffmpeg_thread_count, :worker_count, :pid_path, :log_path,
14
+ :aws_access_key_id, :aws_secret_access_key].each do |key|
15
15
  if config.include?(key)
16
16
  value = config[key]
17
17
  value = $1.to_i if value =~ /\A\s*(\d+)\s*\z/
18
18
  instance_variable_set("@#{key}", value)
19
19
  end
20
20
  end
21
+
22
+ @queue_options = (config[:queue] ||= {}).symbolize_keys
23
+
24
+ # Backwards compatibility with old options
25
+ @queue_options[:adapter] ||= 'sqs'
26
+ @queue_options[:queue] ||= config[:sqs_queue_name]
21
27
  end
22
28
 
23
- attr_accessor :aws_access_key_id
24
- attr_accessor :aws_secret_access_key
29
+ attr_accessor :queue_options
25
30
  attr_accessor :ffmpeg_thread_count
26
- attr_accessor :sqs_queue_name
27
31
  attr_accessor :pid_path
28
32
  attr_accessor :log_path
29
33
  attr_accessor :worker_count
34
+ attr_accessor :aws_secret_access_key
35
+ attr_accessor :aws_access_key_id
30
36
 
31
37
  end
32
38
 
@@ -8,11 +8,9 @@ module Tootsie
8
8
  @ffmpeg_arguments = {}
9
9
  @ffmpeg_arguments['threads'] = (options[:thread_count] || 1)
10
10
  @ffmpeg_arguments['v'] = 1
11
- if false
12
- # TODO: Only in newer FFmpeg versions
13
- @ffmpeg_arguments['xerror'] = true
14
- @ffmpeg_arguments['loglevel'] = 'verbose'
15
- end
11
+ @ffmpeg_arguments['xerror'] = true
12
+ # TODO: Only in newer FFmpeg versions
13
+ #@ffmpeg_arguments['loglevel'] = 'verbose'
16
14
  @ffmpeg_arguments['y'] = true
17
15
  end
18
16
 
@@ -69,7 +67,7 @@ module Tootsie
69
67
  result_width, result_height = $1.to_i, $2.to_i
70
68
  end
71
69
  end
72
- progress.call(elapsed_time, expected_duration) if elapsed_time
70
+ progress.call(elapsed_time, expected_duration) if elapsed_time and expected_duration
73
71
  end
74
72
  end
75
73
 
@@ -91,7 +89,7 @@ module Tootsie
91
89
  :an => true,
92
90
  :f => :rawvideo,
93
91
  :s => "#{thumb_width}x#{thumb_height}"))
94
- rescue FfmpegAdapterExecutionFailed => e
92
+ rescue CommandExecutionFailed => e
95
93
  @logger.error("Thumbnail rendering failed, ignoring: #{e}")
96
94
  end
97
95
  end
@@ -44,9 +44,8 @@ module Tootsie
44
44
  end
45
45
  when /^http(s?):\/\//
46
46
  File.open(@temp_file.path, 'wb') do |file|
47
- HTTPClient.new.get_content(@url) do |chunk|
48
- file << chunk
49
- end
47
+ HTTPClient.new.post(@url, [],
48
+ {'Content-Type' => @content_type, :data => file})
50
49
  end
51
50
  else
52
51
  raise IncompatibleOutputError, "Don't know to store output URL: #{@url}"
@@ -43,7 +43,11 @@ module Tootsie
43
43
  begin
44
44
  adapter_options = version_options.dup
45
45
  adapter_options.delete(:target_url)
46
- adapter_options[:thumbnail] = @thumbnail_options.merge(:filename => thumbnail_output.file_name) if thumbnail_output
46
+ if thumbnail_output
47
+ adapter_options[:thumbnail] = @thumbnail_options.merge(:filename => thumbnail_output.file_name)
48
+ else
49
+ adapter_options.delete(:thumbnail)
50
+ end
47
51
 
48
52
  adapter = Tootsie::FfmpegAdapter.new(:thread_count => @thread_count)
49
53
  if block
@@ -0,0 +1,119 @@
1
+ module Tootsie
2
+
3
+ # A queue which uses the AMQP protocol.
4
+ class AmqpQueue
5
+
6
+ def initialize(host_name, queue_name)
7
+ @logger = Application.get.logger
8
+ @host_name = host_name || 'localhost'
9
+ @queue_name = queue_name || 'tootsie'
10
+ connect!
11
+ end
12
+
13
+ def count
14
+ nil
15
+ end
16
+
17
+ def push(item)
18
+ data = item.to_json
19
+ with_retry do
20
+ with_reconnect do
21
+ @exchange.publish(data, :persistent => true, :key => @queue_name)
22
+ end
23
+ end
24
+ end
25
+
26
+ def pop(options = {})
27
+ item = nil
28
+ loop do
29
+ with_backoff do
30
+ message = nil
31
+ with_retry do
32
+ with_reconnect do
33
+ message = @queue.pop(:ack => true)
34
+ end
35
+ end
36
+ if message
37
+ data = message[:payload]
38
+ data = nil if data == :queue_empty
39
+ if data
40
+ @logger.info "Popped: #{data.inspect}"
41
+ item = JSON.parse(data)
42
+ with_reconnect do
43
+ @queue.ack(:delivery_tag => message[:delivery_details][:delivery_tag])
44
+ end
45
+ true
46
+ end
47
+ end
48
+ end
49
+ break if item
50
+ end
51
+ item
52
+ end
53
+
54
+ private
55
+
56
+ def with_backoff(&block)
57
+ @backoff ||= 0.5
58
+ loop do
59
+ result = yield
60
+ if result
61
+ @backoff /= 2.0
62
+ return result
63
+ else
64
+ @backoff = [@backoff * 1.1, 1.0].min
65
+ @logger.info "Backing off #{@backoff}"
66
+ sleep(@backoff)
67
+ end
68
+ end
69
+ end
70
+
71
+ def with_reconnect(&block)
72
+ begin
73
+ result = yield
74
+ rescue Bunny::ServerDownError
75
+ @logger.error "Error connecting to AMQP server, retrying"
76
+ connect!
77
+ retry
78
+ else
79
+ result
80
+ end
81
+ end
82
+
83
+ def with_retry(&block)
84
+ begin
85
+ result = yield
86
+ rescue Exception => exception
87
+ check_exception(exception)
88
+ @logger.error("Queue access failed with exception #{exception.class} (#{exception.message}), will retry")
89
+ sleep(0.5)
90
+ retry
91
+ else
92
+ result
93
+ end
94
+ end
95
+
96
+ def connect!
97
+ begin
98
+ @logger.info "Connecting to AMQP server on #{@host_name}"
99
+
100
+ @connection = Bunny.new(:host => @host_name)
101
+ @connection.start
102
+
103
+ @exchange = @connection.exchange('')
104
+
105
+ @queue = @connection.queue(@queue_name, :durable => true)
106
+ rescue Bunny::ServerDownError
107
+ sleep(0.5)
108
+ retry
109
+ end
110
+ end
111
+
112
+ def check_exception(exception)
113
+ raise exception if exception.is_a?(SystemExit)
114
+ raise exception if exception.is_a?(SignalException) and not exception.is_a?(Timeout::Error)
115
+ end
116
+
117
+ end
118
+
119
+ end
@@ -9,16 +9,19 @@ module Tootsie
9
9
  # A queue which uses Amazon's Simple Queue Service (SQS).
10
10
  class SqsQueue
11
11
 
12
- def initialize(queue_name, sqs_service)
12
+ def initialize(queue_name, access_key_id, secret_access_key)
13
+ @sqs_service = ::Sqs::Service.new(
14
+ :access_key_id => access_key_id,
15
+ :secret_access_key => secret_access_key)
13
16
  @logger = Application.get.logger
14
- @sqs_service = sqs_service
15
17
  @queue = @sqs_service.queues.find_first(queue_name)
16
18
  unless @queue
19
+ @logger.info "Queue #{queue_name} does not exist, creating it"
17
20
  @sqs_service.queues.create(queue_name)
18
21
  begin
19
- timeout(5) do
22
+ timeout(30) do
20
23
  while not @queue
21
- sleep(0.5)
24
+ sleep(1)
22
25
  @queue = @sqs_service.queues.find_first(queue_name)
23
26
  end
24
27
  end
@@ -1,3 +1,3 @@
1
1
  module Tootsie
2
- VERSION = '0.9.13'
2
+ VERSION = '0.9.14'
3
3
  end
data/lib/tootsie.rb CHANGED
@@ -4,6 +4,10 @@ require 's3'
4
4
  require 'sqs'
5
5
  require 'yaml'
6
6
  require 'optparse'
7
+ require 'json'
8
+ require 'sqs'
9
+ require 'timeout'
10
+ require 'bunny'
7
11
 
8
12
  require 'tootsie/application'
9
13
  require 'tootsie/client'
@@ -22,5 +26,6 @@ require 'tootsie/processors/video_processor'
22
26
  require 'tootsie/processors/image_processor'
23
27
  require 'tootsie/queues/sqs_queue'
24
28
  require 'tootsie/queues/file_system_queue'
29
+ require 'tootsie/queues/amqp_queue'
25
30
  require 'tootsie/s3_utilities'
26
31
  require 'tootsie/runner'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tootsie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.13
4
+ version: 0.9.14
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-22 00:00:00.000000000Z
12
+ date: 2012-01-23 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70265487044840 !ruby/object:Gem::Requirement
16
+ requirement: &70277516115920 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.4.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70265487044840
24
+ version_requirements: *70277516115920
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sinatra
27
- requirement: &70265487044320 !ruby/object:Gem::Requirement
27
+ requirement: &70277516115400 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70265487044320
35
+ version_requirements: *70277516115400
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: activesupport
38
- requirement: &70265487043840 !ruby/object:Gem::Requirement
38
+ requirement: &70277516114920 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 3.0.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70265487043840
46
+ version_requirements: *70277516114920
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: httpclient
49
- requirement: &70265487043360 !ruby/object:Gem::Requirement
49
+ requirement: &70277516114440 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 2.2.1
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70265487043360
57
+ version_requirements: *70277516114440
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: builder
60
- requirement: &70265487042880 !ruby/object:Gem::Requirement
60
+ requirement: &70277516113960 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 2.1.2
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70265487042880
68
+ version_requirements: *70277516113960
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: mime-types
71
- requirement: &70265487042400 !ruby/object:Gem::Requirement
71
+ requirement: &70277516113480 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '1.16'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70265487042400
79
+ version_requirements: *70277516113480
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: xml-simple
82
- requirement: &70265487041920 !ruby/object:Gem::Requirement
82
+ requirement: &70277516113000 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 1.0.12
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70265487041920
90
+ version_requirements: *70277516113000
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: thin
93
- requirement: &70265487041440 !ruby/object:Gem::Requirement
93
+ requirement: &70277505792900 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: 1.2.7
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *70265487041440
101
+ version_requirements: *70277505792900
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: s3
104
- requirement: &70265487040960 !ruby/object:Gem::Requirement
104
+ requirement: &70277505792420 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,10 +109,21 @@ dependencies:
109
109
  version: 0.3.8
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *70265487040960
112
+ version_requirements: *70277505792420
113
+ - !ruby/object:Gem::Dependency
114
+ name: bunny
115
+ requirement: &70277505791940 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ~>
119
+ - !ruby/object:Gem::Version
120
+ version: 0.7.8
121
+ type: :runtime
122
+ prerelease: false
123
+ version_requirements: *70277505791940
113
124
  - !ruby/object:Gem::Dependency
114
125
  name: sqs
115
- requirement: &70265487040480 !ruby/object:Gem::Requirement
126
+ requirement: &70277505791460 !ruby/object:Gem::Requirement
116
127
  none: false
117
128
  requirements:
118
129
  - - ~>
@@ -120,10 +131,10 @@ dependencies:
120
131
  version: 0.1.2
121
132
  type: :runtime
122
133
  prerelease: false
123
- version_requirements: *70265487040480
134
+ version_requirements: *70277505791460
124
135
  - !ruby/object:Gem::Dependency
125
136
  name: unicorn
126
- requirement: &70265487040000 !ruby/object:Gem::Requirement
137
+ requirement: &70277505790980 !ruby/object:Gem::Requirement
127
138
  none: false
128
139
  requirements:
129
140
  - - ~>
@@ -131,10 +142,10 @@ dependencies:
131
142
  version: 4.1.1
132
143
  type: :runtime
133
144
  prerelease: false
134
- version_requirements: *70265487040000
145
+ version_requirements: *70277505790980
135
146
  - !ruby/object:Gem::Dependency
136
147
  name: i18n
137
- requirement: &70265487039520 !ruby/object:Gem::Requirement
148
+ requirement: &70277505790500 !ruby/object:Gem::Requirement
138
149
  none: false
139
150
  requirements:
140
151
  - - ! '>='
@@ -142,10 +153,10 @@ dependencies:
142
153
  version: 0.4.2
143
154
  type: :runtime
144
155
  prerelease: false
145
- version_requirements: *70265487039520
156
+ version_requirements: *70277505790500
146
157
  - !ruby/object:Gem::Dependency
147
158
  name: scashin133-syslog_logger
148
- requirement: &70265487039040 !ruby/object:Gem::Requirement
159
+ requirement: &70277505790020 !ruby/object:Gem::Requirement
149
160
  none: false
150
161
  requirements:
151
162
  - - ~>
@@ -153,10 +164,10 @@ dependencies:
153
164
  version: 1.7.3
154
165
  type: :runtime
155
166
  prerelease: false
156
- version_requirements: *70265487039040
167
+ version_requirements: *70277505790020
157
168
  - !ruby/object:Gem::Dependency
158
169
  name: rspec
159
- requirement: &70265489455040 !ruby/object:Gem::Requirement
170
+ requirement: &70277505789640 !ruby/object:Gem::Requirement
160
171
  none: false
161
172
  requirements:
162
173
  - - ! '>='
@@ -164,10 +175,10 @@ dependencies:
164
175
  version: '0'
165
176
  type: :development
166
177
  prerelease: false
167
- version_requirements: *70265489455040
178
+ version_requirements: *70277505789640
168
179
  - !ruby/object:Gem::Dependency
169
180
  name: rake
170
- requirement: &70265489454580 !ruby/object:Gem::Requirement
181
+ requirement: &70277505789180 !ruby/object:Gem::Requirement
171
182
  none: false
172
183
  requirements:
173
184
  - - ! '>='
@@ -175,7 +186,7 @@ dependencies:
175
186
  version: '0'
176
187
  type: :development
177
188
  prerelease: false
178
- version_requirements: *70265489454580
189
+ version_requirements: *70277505789180
179
190
  description: Tootsie is a simple audio/video/image transcoding/modification application.
180
191
  email:
181
192
  - alex@origo.no
@@ -203,6 +214,7 @@ files:
203
214
  - lib/tootsie/output.rb
204
215
  - lib/tootsie/processors/image_processor.rb
205
216
  - lib/tootsie/processors/video_processor.rb
217
+ - lib/tootsie/queues/amqp_queue.rb
206
218
  - lib/tootsie/queues/file_system_queue.rb
207
219
  - lib/tootsie/queues/sqs_queue.rb
208
220
  - lib/tootsie/runner.rb