shingoncoder 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +15 -0
- data/README.md +54 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/shingoncoder.rb +10 -0
- data/lib/shingoncoder/backend.rb +10 -0
- data/lib/shingoncoder/backend/config.rb +72 -0
- data/lib/shingoncoder/backend/job.rb +27 -0
- data/lib/shingoncoder/backend/job_registry.rb +96 -0
- data/lib/shingoncoder/backend/transcode_job.rb +11 -0
- data/lib/shingoncoder/backend/transcode_service.rb +133 -0
- data/lib/shingoncoder/job.rb +25 -0
- data/lib/shingoncoder/response.rb +11 -0
- data/lib/shingoncoder/version.rb +3 -0
- data/shingoncoder.gemspec +28 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7fb618ddf8d3d2e620724cafc6aa1b70261663ee
|
4
|
+
data.tar.gz: ca0a71f31dd49e557c03f0966de9259370da521a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bf2ce885ed263227ccf3cac248adf7cc7a90046696e824125add9b9c72ec2d2093cbc6f09f8cf8b678efed835442e774255a0c14ef24720f5c2bae981974b988
|
7
|
+
data.tar.gz: c9238d764fe40159ee4557cd55889d1a423d99419061220df8c35e0b0d55e65cf8911b083a37b25e896fef893990dbf971ca665d51cb6a5a8efe03e0a2240afd
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
##########################################################################
|
2
|
+
# Copyright 2013 Notre Dame, Data Curation Experts, WGBH
|
3
|
+
# Additional copyright may be held by others, as reflected in the commit log
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Shingoncoder
|
2
|
+
|
3
|
+
A asynchronous system for handling video transcoding backed by FFMpeg.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Include this gem in your Gemfile
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'shingoncoder'
|
11
|
+
```
|
12
|
+
|
13
|
+
Create the necessary tables:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
rails console
|
17
|
+
Shingoncoder::Backend::JobRegistry.create_tables!
|
18
|
+
```
|
19
|
+
|
20
|
+
The asynchronous behavior is handled by ActiveJob, so you need only start your workers in the usual manner.
|
21
|
+
|
22
|
+
|
23
|
+
## Configuration
|
24
|
+
|
25
|
+
TODO
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
Shingoncoder::Backend::TranscodeService.config.ffmpeg_path = '/usr/bin/ffmpeg'
|
29
|
+
```
|
30
|
+
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
Shingoncoder::Job.create(input: 'file:///opt/originals/full.mov')
|
36
|
+
Shingoncoder::Job.create(input: 'file:///opt/originals/full.mov',
|
37
|
+
outputs: [{ label: 'vp8 for the web',
|
38
|
+
url: 'file:///opt/derivatives/output.webm'}])
|
39
|
+
```
|
40
|
+
|
41
|
+
This returns a Shingoncoder::Response object which contains a Job ID and one or more Output IDs (one per output file).
|
42
|
+
|
43
|
+
### Output options
|
44
|
+
```
|
45
|
+
url - where to put the file, (Must be a file URI for now)
|
46
|
+
size - The resolution of the output video (WxH, in pixels). Defaults to 320x240.
|
47
|
+
label - optional label
|
48
|
+
```
|
49
|
+
|
50
|
+
|
51
|
+
## Contributing
|
52
|
+
|
53
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jcoyne/shingoncoder. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
54
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "shingon"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/lib/shingoncoder.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Shingoncoder::Backend
|
2
|
+
class Config
|
3
|
+
attr_writer :ffmpeg_path, :video_bitrate, :video_attributes, :size_attributes, :audio_attributes
|
4
|
+
|
5
|
+
def ffmpeg_path
|
6
|
+
@ffmpeg_path ||= 'ffmpeg'
|
7
|
+
end
|
8
|
+
|
9
|
+
def video_bitrate
|
10
|
+
@video_bitrate ||= default_video_bitrate
|
11
|
+
end
|
12
|
+
|
13
|
+
def video_attributes
|
14
|
+
@video_attributes ||= default_video_attributes
|
15
|
+
end
|
16
|
+
|
17
|
+
def size_attributes
|
18
|
+
@size_attributes ||= default_size_attributes
|
19
|
+
end
|
20
|
+
|
21
|
+
def audio_attributes
|
22
|
+
@audio_attributes ||= default_audio_attributes
|
23
|
+
end
|
24
|
+
|
25
|
+
def mpeg4
|
26
|
+
@mpeg4 ||= CodecConfig.new('-vcodec libx264 -acodec libfdk_aac')
|
27
|
+
end
|
28
|
+
|
29
|
+
def webm
|
30
|
+
@webm ||= CodecConfig.new('-vcodec libvpx -acodec libvorbis')
|
31
|
+
end
|
32
|
+
|
33
|
+
def mkv
|
34
|
+
@mkv ||= CodecConfig.new('-vcodec ffv1')
|
35
|
+
end
|
36
|
+
|
37
|
+
def jpeg
|
38
|
+
@jpeg ||= CodecConfig.new('-vcodec mjpeg')
|
39
|
+
end
|
40
|
+
|
41
|
+
class CodecConfig
|
42
|
+
attr_writer :codec
|
43
|
+
|
44
|
+
def initialize(default)
|
45
|
+
@codec = default
|
46
|
+
end
|
47
|
+
|
48
|
+
def codec
|
49
|
+
@codec
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
protected
|
55
|
+
def default_video_bitrate
|
56
|
+
'345k'
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_video_attributes
|
60
|
+
"-g 30 -b:v #{video_bitrate}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def default_size_attributes
|
64
|
+
"320x240"
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_audio_attributes
|
68
|
+
"-ac 2 -ab 96k -ar 44100"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Shingoncoder::Backend
|
2
|
+
class Job
|
3
|
+
class << self
|
4
|
+
# Register the job and kicks off several derivatives.
|
5
|
+
# @param [Hash] options
|
6
|
+
# @option [String] :input the url to the file
|
7
|
+
# @return [Integer] :id for the job
|
8
|
+
def create(options)
|
9
|
+
uri = URI(options.fetch(:input))
|
10
|
+
filename = case uri.scheme
|
11
|
+
when 'file'
|
12
|
+
uri.path
|
13
|
+
else
|
14
|
+
raise ArgumentError, "#{uri.scheme} is not yet implemented"
|
15
|
+
end
|
16
|
+
|
17
|
+
job = Shingoncoder::Backend::JobRegistry.create(options)
|
18
|
+
|
19
|
+
job.outputs.each do |output|
|
20
|
+
TranscodeJob.perform_later(output.id)
|
21
|
+
end
|
22
|
+
|
23
|
+
job.id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Shingoncoder
|
2
|
+
module Backend
|
3
|
+
class JobRegistry
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def create(input)
|
7
|
+
raise ArgumentError, "Required argument ':input' is missing" unless input.key?(:input)
|
8
|
+
outputs = input.delete(:outputs)
|
9
|
+
outputs ||= default_output(input)
|
10
|
+
Job.create(Job.input_column_name => input) do |job|
|
11
|
+
outputs.each do |val|
|
12
|
+
raise ArgumentError, "Output directive must have a url" unless val.key?(:url)
|
13
|
+
|
14
|
+
job.outputs.build(Output.input_column_name => val)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_tables!
|
20
|
+
Job.create_table!
|
21
|
+
Output.create_table!
|
22
|
+
end
|
23
|
+
|
24
|
+
def drop_tables!
|
25
|
+
Job.drop_table!
|
26
|
+
Output.drop_table!
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def default_output(input)
|
32
|
+
[{ url: "#{input.fetch(:input)}.mp4" }]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Job < ActiveRecord::Base
|
37
|
+
##
|
38
|
+
# :singleton-method:
|
39
|
+
# Customizable data column name. Defaults to 'data'.
|
40
|
+
cattr_accessor :input_column_name
|
41
|
+
self.input_column_name = 'input'
|
42
|
+
has_many :outputs
|
43
|
+
|
44
|
+
serialize input_column_name, JSON
|
45
|
+
|
46
|
+
class << self
|
47
|
+
def drop_table!
|
48
|
+
connection.schema_cache.clear_table_cache!(table_name)
|
49
|
+
connection.drop_table table_name
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_table!
|
53
|
+
connection.schema_cache.clear_table_cache!(table_name)
|
54
|
+
connection.create_table(table_name) do |t|
|
55
|
+
t.text input_column_name
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Output < ActiveRecord::Base
|
62
|
+
belongs_to :job
|
63
|
+
|
64
|
+
##
|
65
|
+
# :singleton-method:
|
66
|
+
# Customizable data column name. Defaults to 'data'.
|
67
|
+
cattr_accessor :input_column_name
|
68
|
+
self.input_column_name = 'input'
|
69
|
+
serialize input_column_name, JSON
|
70
|
+
|
71
|
+
def url
|
72
|
+
self[input_column_name]['url']
|
73
|
+
end
|
74
|
+
|
75
|
+
def config
|
76
|
+
self[input_column_name]
|
77
|
+
end
|
78
|
+
|
79
|
+
class << self
|
80
|
+
def drop_table!
|
81
|
+
connection.schema_cache.clear_table_cache!(table_name)
|
82
|
+
connection.drop_table table_name
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_table!
|
86
|
+
connection.schema_cache.clear_table_cache!(table_name)
|
87
|
+
connection.create_table(table_name) do |t|
|
88
|
+
t.references :job, index: true, foreign_key: true
|
89
|
+
t.text input_column_name
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'open3'
|
2
|
+
module Shingoncoder::Backend
|
3
|
+
class TranscodeService
|
4
|
+
include Open3
|
5
|
+
class_attribute :config, :timeout
|
6
|
+
self.config = Config.new
|
7
|
+
|
8
|
+
BLOCK_SIZE = 1024
|
9
|
+
|
10
|
+
# @param [Fixnum] id the Output ID (not to be confused with the job_id)
|
11
|
+
def initialize(id)
|
12
|
+
@id = id
|
13
|
+
end
|
14
|
+
|
15
|
+
def transcode
|
16
|
+
execute "#{config.ffmpeg_path} #{input_options} -i \"#{input_path}\" #{output_options} #{output_path}"
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def output_path
|
22
|
+
URI(output.url).path
|
23
|
+
end
|
24
|
+
|
25
|
+
def input_path
|
26
|
+
URI(output.job.input.fetch('input')).path
|
27
|
+
end
|
28
|
+
|
29
|
+
def output
|
30
|
+
@output ||= JobRegistry::Output.find(@id)
|
31
|
+
end
|
32
|
+
|
33
|
+
def output_format
|
34
|
+
@format ||= File.extname(output.url).sub(/\./, '')
|
35
|
+
end
|
36
|
+
|
37
|
+
def size_attribute
|
38
|
+
output.config.fetch('size', config.size_attributes)
|
39
|
+
end
|
40
|
+
|
41
|
+
def codecs(format)
|
42
|
+
case format
|
43
|
+
when 'mp4'
|
44
|
+
config.mpeg4.codec
|
45
|
+
when 'webm'
|
46
|
+
config.webm.codec
|
47
|
+
when "mkv"
|
48
|
+
config.mkv.codec
|
49
|
+
when "jpg"
|
50
|
+
config.jpeg.codec
|
51
|
+
else
|
52
|
+
raise ArgumentError, "Unknown format `#{format}'"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def input_options
|
57
|
+
output_format == 'jpg' ? " -itsoffset -2" : ''
|
58
|
+
end
|
59
|
+
|
60
|
+
def output_options
|
61
|
+
output_options = "-s #{size_attribute} #{codecs(output_format)}"
|
62
|
+
|
63
|
+
output_options+= case output_format
|
64
|
+
when "jpg"
|
65
|
+
" -vframes 1 -an -f rawvideo"
|
66
|
+
else
|
67
|
+
" #{config.video_attributes} #{config.audio_attributes}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def execute(command)
|
72
|
+
context = {}
|
73
|
+
if timeout
|
74
|
+
execute_with_timeout(timeout, command, context)
|
75
|
+
else
|
76
|
+
execute_without_timeout(command, context)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def execute_with_timeout(timeout, command, context)
|
81
|
+
begin
|
82
|
+
status = Timeout::timeout(timeout) do
|
83
|
+
execute_without_timeout(command, context)
|
84
|
+
end
|
85
|
+
rescue Timeout::Error => ex
|
86
|
+
pid = context[:pid]
|
87
|
+
Process.kill("KILL", pid)
|
88
|
+
raise TimeoutError, "Unable to execute command \"#{command}\"\nThe command took longer than #{timeout} seconds to execute"
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
def execute_without_timeout(command, context)
|
94
|
+
exit_status = nil
|
95
|
+
err_str = ''
|
96
|
+
stdin, stdout, stderr, wait_thr = popen3(command)
|
97
|
+
context[:pid] = wait_thr[:pid]
|
98
|
+
stdin.close
|
99
|
+
stdout.close
|
100
|
+
files = [stderr]
|
101
|
+
|
102
|
+
until all_eof?(files) do
|
103
|
+
ready = IO.select(files, nil, nil, 60)
|
104
|
+
|
105
|
+
if ready
|
106
|
+
readable = ready[0]
|
107
|
+
readable.each do |f|
|
108
|
+
fileno = f.fileno
|
109
|
+
|
110
|
+
begin
|
111
|
+
data = f.read_nonblock(BLOCK_SIZE)
|
112
|
+
|
113
|
+
case fileno
|
114
|
+
when stderr.fileno
|
115
|
+
err_str << data
|
116
|
+
end
|
117
|
+
rescue EOFError
|
118
|
+
Rails.logger "Caught an eof error in ShellBasedProcessor"
|
119
|
+
# No big deal.
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
exit_status = wait_thr.value
|
125
|
+
|
126
|
+
raise "Unable to execute command \"#{command}\". Exit code: #{exit_status}\nError message: #{err_str}" unless exit_status.success?
|
127
|
+
end
|
128
|
+
|
129
|
+
def all_eof?(files)
|
130
|
+
files.find { |f| !f.eof }.nil?
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Shingoncoder
|
2
|
+
class Job
|
3
|
+
class << self
|
4
|
+
# @param [Hash] options
|
5
|
+
# @option [String] :input the url to the file
|
6
|
+
def create(options = {})
|
7
|
+
id = Backend::Job.create(options)
|
8
|
+
# TODO in the future the backend could be via a HTTP API
|
9
|
+
Response.new('id' => id, 'code' => 201)
|
10
|
+
end
|
11
|
+
|
12
|
+
def cancel
|
13
|
+
fail NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def progress
|
17
|
+
fail NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
def details
|
21
|
+
fail NotImplementedError
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'shingoncoder/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "shingoncoder"
|
8
|
+
spec.version = Shingoncoder::VERSION
|
9
|
+
spec.authors = ["Justin Coyne"]
|
10
|
+
spec.email = ["jcoyne@justincoyne.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Create and manage asynchronous transcoding jobs}
|
13
|
+
spec.description = %q{Backed by ActiveJob and FFMpeg}
|
14
|
+
spec.homepage = "https://github.com/jcoyne/shingoncoder"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'activerecord'
|
22
|
+
spec.add_dependency 'railties'
|
23
|
+
spec.add_dependency 'activejob'
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shingoncoder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Coyne
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: railties
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activejob
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.10'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Backed by ActiveJob and FFMpeg
|
98
|
+
email:
|
99
|
+
- jcoyne@justincoyne.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".travis.yml"
|
107
|
+
- CODE_OF_CONDUCT.md
|
108
|
+
- Gemfile
|
109
|
+
- LICENSE.txt
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- bin/console
|
113
|
+
- bin/setup
|
114
|
+
- lib/shingoncoder.rb
|
115
|
+
- lib/shingoncoder/backend.rb
|
116
|
+
- lib/shingoncoder/backend/config.rb
|
117
|
+
- lib/shingoncoder/backend/job.rb
|
118
|
+
- lib/shingoncoder/backend/job_registry.rb
|
119
|
+
- lib/shingoncoder/backend/transcode_job.rb
|
120
|
+
- lib/shingoncoder/backend/transcode_service.rb
|
121
|
+
- lib/shingoncoder/job.rb
|
122
|
+
- lib/shingoncoder/response.rb
|
123
|
+
- lib/shingoncoder/version.rb
|
124
|
+
- shingoncoder.gemspec
|
125
|
+
homepage: https://github.com/jcoyne/shingoncoder
|
126
|
+
licenses: []
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 2.4.5.1
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: Create and manage asynchronous transcoding jobs
|
148
|
+
test_files: []
|
149
|
+
has_rdoc:
|