hydra-derivatives 3.2.2 → 3.3.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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/README.md +25 -0
- data/VERSION +1 -1
- data/doc/amazon_elastic_transcoder.md +116 -0
- data/hydra-derivatives.gemspec +3 -1
- data/lib/hydra/derivatives.rb +4 -1
- data/lib/hydra/derivatives/config.rb +9 -1
- data/lib/hydra/derivatives/processors.rb +1 -0
- data/lib/hydra/derivatives/processors/active_encode.rb +56 -0
- data/lib/hydra/derivatives/processors/document.rb +1 -1
- data/lib/hydra/derivatives/processors/ffmpeg.rb +1 -1
- data/lib/hydra/derivatives/processors/jpeg2k_image.rb +1 -1
- data/lib/hydra/derivatives/runners/active_encode_derivatives.rb +44 -0
- data/lib/hydra/derivatives/services/persist_basic_contained_output_file_service.rb +37 -13
- data/lib/hydra/derivatives/services/persist_external_file_output_file_service.rb +20 -0
- data/lib/hydra/derivatives/services/remote_source_file.rb +18 -0
- data/spec/processors/active_encode_spec.rb +132 -0
- data/spec/processors/full_text_spec.rb +4 -1
- data/spec/runners/active_encode_derivatives_spec.rb +38 -0
- data/spec/services/persist_basic_contained_output_file_service_spec.rb +18 -5
- data/spec/services/persist_external_file_output_file_service_spec.rb +26 -0
- data/spec/services/remote_source_file_spec.rb +33 -0
- data/spec/units/config_spec.rb +6 -0
- data/spec/units/derivatives_spec.rb +4 -0
- metadata +46 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b300c88a53fe0b8e79f9ace11145653e878f8614
|
|
4
|
+
data.tar.gz: dfe48e84c0bd64e74d77d3a4c9cb103f2aaee0dc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f1f0183aae8af14487552ebf3c5f9453db4fa64c7f51fa9f1ac6bc4453cf58d3b9bf0a25c5296450c4006eb7b45b4fb6d6093f1cf46a7548d0a189854cfdb19
|
|
7
|
+
data.tar.gz: '058e7057eae73e19451e8d9926576305f85416bd1c3db0bdba279acc97bd629fa27d9ac6200dd56f84505a780d1371937e74f8eab970983a3276af1d3092fd27'
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
|
@@ -52,6 +52,8 @@ Then when you call `obj.create_derivatives` two new files, 'thumbnail' and 'cont
|
|
|
52
52
|
|
|
53
53
|
We recommend you run `obj.create_derivatives` in a background worker, because some derivative creation (especially videos) can take a long time.
|
|
54
54
|
|
|
55
|
+
The ActiveEncode runner provides support for using external video transcoding services like Amazon Elastic Transcoder. See [ActiveEncode](https://github.com/samvera-labs/active_encode) for details on specific adapters supported.
|
|
56
|
+
|
|
55
57
|
## Configuration
|
|
56
58
|
|
|
57
59
|
### Retrieving from a basic container in Fedora
|
|
@@ -74,6 +76,7 @@ Hydra::Derivatives::Processors::Video::Processor.timeout = 10.minutes
|
|
|
74
76
|
Hydra::Derivatives::Processors::Document.timeout = 5.minutes
|
|
75
77
|
Hydra::Derivatives::Processors::Audio.timeout = 10.minutes
|
|
76
78
|
Hydra::Derivatives::Processors::Image.timeout = 5.minutes
|
|
79
|
+
Hydra::Derivatives::Processors::ActiveEncode.timeout = 5.minutes
|
|
77
80
|
|
|
78
81
|
```
|
|
79
82
|
|
|
@@ -88,6 +91,28 @@ Hydra::Derivatives::Processors::Video::Processor.config.mkv.codec = '-vcodec ffv
|
|
|
88
91
|
Hydra::Derivatives::Processors::Video::Processor.config.jpeg.codec = '-vcodec mjpeg'
|
|
89
92
|
```
|
|
90
93
|
|
|
94
|
+
### Configuration for Audio/Video Processing with ActiveEncode
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
# Set the transcoding engine
|
|
98
|
+
ActiveEncode::Base.engine_adapter = :elastic_transcoder
|
|
99
|
+
|
|
100
|
+
# Sleep time (in seconds) to poll for status of encoding job
|
|
101
|
+
Hydra::Derivatives.active_encode_poll_time = 10
|
|
102
|
+
|
|
103
|
+
# If you want to use a different class for the source file service
|
|
104
|
+
Hydra::Derivatives::ActiveEncodeDerivatives.source_file_service = MyCustomSourceFileService
|
|
105
|
+
|
|
106
|
+
# If you want to use a different class for the output file service
|
|
107
|
+
Hydra::Derivatives::ActiveEncodeDerivatives.output_file_service = MyCustomOutputFileService
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Note: Please don't confuse these methods with the similar methods in the parent class:
|
|
111
|
+
`Hydra::Derivatives.source_file_service` and `Hydra::Derivatives.output_file_service`
|
|
112
|
+
|
|
113
|
+
For additional documentation on using ActiveEncode, see:
|
|
114
|
+
* [Using Amazon Elastic Transcoder](doc/amazon_elastic_transcoder.md)
|
|
115
|
+
|
|
91
116
|
### Additional Directives
|
|
92
117
|
|
|
93
118
|
#### Layers
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.3.0
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Create Audio and Video Derivatives using Amazon Elastic Transcoder
|
|
2
|
+
|
|
3
|
+
`hydra-derivatives` uses the
|
|
4
|
+
[active\_encode gem](https://github.com/projecthydra-labs/active_encode)
|
|
5
|
+
to allow you to use different encoding services.
|
|
6
|
+
These instructions are for Amazon's Elastic Transcoder service.
|
|
7
|
+
|
|
8
|
+
## Prerequsites
|
|
9
|
+
|
|
10
|
+
### Set up the Elastic Transcoder Pipeline
|
|
11
|
+
|
|
12
|
+
Set up a pipeline on AWS Elastic Transcoder that defines:
|
|
13
|
+
|
|
14
|
+
* input bucket
|
|
15
|
+
* bucket for transcoded files
|
|
16
|
+
* bucket for thumbnails
|
|
17
|
+
|
|
18
|
+
### Configure AWS credentials
|
|
19
|
+
|
|
20
|
+
Optional: If you don't want to pass these values in your ruby code using `Aws.config`, you can set environment variables instead:
|
|
21
|
+
|
|
22
|
+
* AWS\_ACCESS\_KEY\_ID
|
|
23
|
+
* AWS\_SECRET\_ACCESS\_KEY
|
|
24
|
+
* AWS\_REGION
|
|
25
|
+
|
|
26
|
+
### Install gems
|
|
27
|
+
|
|
28
|
+
Add to your `Gemfile`:
|
|
29
|
+
|
|
30
|
+
* aws-sdk
|
|
31
|
+
|
|
32
|
+
### Configure initializer
|
|
33
|
+
|
|
34
|
+
In an initializer file such as `config/initializers/active_encode.rb`, make sure you have the following code:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
# Use Amazon's Elastic Transcoder
|
|
38
|
+
ActiveEncode::Base.engine_adapter = :elastic_transcoder
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## How to create derivatives (Multiple derivatives per Elastic Transcoder job)
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
# Access config for AWS
|
|
45
|
+
Aws.config[:access_key_id] = 'put your access key here'
|
|
46
|
+
Aws.config[:secret_access_key] = 'put your secret key here'
|
|
47
|
+
Aws.config[:region] = 'us-east-1'
|
|
48
|
+
|
|
49
|
+
# The pipeline that I set up in Elastic Transcoder
|
|
50
|
+
pipeline_id = '1490715200916-25b08y'
|
|
51
|
+
|
|
52
|
+
# The file "sample_data.mp4" has already been uploaded to the input bucket for my pipeline.
|
|
53
|
+
input_file = 'sample_data.mp4'
|
|
54
|
+
|
|
55
|
+
# Choose a name for the output files
|
|
56
|
+
base_file_name = 'output_file_17'
|
|
57
|
+
|
|
58
|
+
# Settings for a low-res video derivative using a preset for a 320x240 resolution mp4 file
|
|
59
|
+
low_res_video = { key: "#{base_file_name}.mp4", preset_id: '1351620000001-000061' }
|
|
60
|
+
|
|
61
|
+
# Settings for a flash video derivative
|
|
62
|
+
flash_video = { key: "#{base_file_name}.flv", preset_id: '1351620000001-100210' }
|
|
63
|
+
|
|
64
|
+
# Settings to send to the Elastic Transcoder job
|
|
65
|
+
job_settings = { pipeline_id: pipeline_id, output_key_prefix: "active_encode-demo_app/", outputs: [low_res_video, flash_video] }
|
|
66
|
+
|
|
67
|
+
# Run the encoding
|
|
68
|
+
Hydra::Derivatives::ActiveEncodeDerivatives.create(input_file, outputs: [job_settings])
|
|
69
|
+
|
|
70
|
+
# Note: Your rails console will not return to the prompt until the encoding is complete,
|
|
71
|
+
# so it might sit there for several minutes with no feedback.
|
|
72
|
+
# Use the AWS console to see the current status of the encoding.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## How to create derivatives (One derivative per Elastic Transcoder job)
|
|
76
|
+
|
|
77
|
+
If you want to run a separate Elastic Transcoder job for each derivative file, you could do something like this:
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
# Settings for a low-res video derivative using a preset for a 320x240 resolution mp4 file.
|
|
81
|
+
low_res_preset_id = '1351620000001-000061'
|
|
82
|
+
low_res_output_file = 'output_15.mp4'
|
|
83
|
+
low_res_video = { pipeline_id: pipeline_id, output_key_prefix: "active_encode-demo_app/", outputs: [{ key: low_res_output_file, preset_id: low_res_preset_id }] }
|
|
84
|
+
|
|
85
|
+
# Settings for a flash video derivative
|
|
86
|
+
flash_preset_id = '1351620000001-100210'
|
|
87
|
+
flash_output_file = 'output_15.flv'
|
|
88
|
+
flash_video = { pipeline_id: pipeline_id, output_key_prefix: "active_encode-demo_app/", outputs: [{ key: flash_output_file, preset_id: flash_preset_id }] }
|
|
89
|
+
|
|
90
|
+
Hydra::Derivatives::ActiveEncodeDerivatives.create(input_file, outputs: [low_res_video, flash_video])
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## How to pass in a ruby object
|
|
94
|
+
|
|
95
|
+
If you want to pass in an `ActiveFedora::Base` object (or some other record) instead of just a String for the input file name, you need to set the `source` option to specify which method to call on your object to get the file name. For example:
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
# Some object that contains the source file name
|
|
99
|
+
class Video
|
|
100
|
+
attr_accessor :source_file_name
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
video_record = Video.new
|
|
104
|
+
video_record.source_file_name = 'sample_data.mp4'
|
|
105
|
+
|
|
106
|
+
Hydra::Derivatives::ActiveEncodeDerivatives.create(video_record, source: :source_file_name, outputs: [low_res_video])
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## How to pass in a custom encode class
|
|
110
|
+
|
|
111
|
+
If you don't want to use the default encode class `::ActiveEncode::Base`, you can pass in `encode_class`:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
Hydra::Derivatives::ActiveEncodeDerivatives.create(video_record, encode_class: MyCustomEncode, source: :source_file_name, outputs: [low_res_video])
|
|
115
|
+
```
|
|
116
|
+
|
data/hydra-derivatives.gemspec
CHANGED
|
@@ -23,10 +23,12 @@ Gem::Specification.new do |spec|
|
|
|
23
23
|
spec.add_development_dependency "solr_wrapper", "~> 0.4"
|
|
24
24
|
spec.add_development_dependency 'fcrepo_wrapper', '~> 0.2'
|
|
25
25
|
|
|
26
|
-
spec.add_dependency 'active-fedora', '>=
|
|
26
|
+
spec.add_dependency 'active-fedora', '>= 11.3.1', '< 12'
|
|
27
27
|
spec.add_dependency 'mini_magick', '>= 3.2', '< 5'
|
|
28
28
|
spec.add_dependency 'activesupport', '>= 4.0', '< 6'
|
|
29
29
|
spec.add_dependency 'mime-types', '> 2.0', '< 4.0'
|
|
30
|
+
spec.add_dependency 'active_encode', '~>0.1'
|
|
31
|
+
spec.add_dependency 'addressable', '~>2.5'
|
|
30
32
|
spec.add_dependency 'deprecation'
|
|
31
33
|
end
|
|
32
34
|
|
data/lib/hydra/derivatives.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Hydra
|
|
|
11
11
|
# Runners take a single input and produce one or more outputs
|
|
12
12
|
# The runner typically accomplishes this by using one or more processors
|
|
13
13
|
autoload_under 'runners' do
|
|
14
|
+
autoload :ActiveEncodeDerivatives
|
|
14
15
|
autoload :AudioDerivatives
|
|
15
16
|
autoload :DocumentDerivatives
|
|
16
17
|
autoload :FullTextExtract
|
|
@@ -30,8 +31,10 @@ module Hydra
|
|
|
30
31
|
|
|
31
32
|
autoload_under 'services' do
|
|
32
33
|
autoload :RetrieveSourceFileService
|
|
34
|
+
autoload :RemoteSourceFile
|
|
33
35
|
autoload :PersistOutputFileService
|
|
34
36
|
autoload :PersistBasicContainedOutputFileService
|
|
37
|
+
autoload :PersistExternalFileOutputFileService
|
|
35
38
|
autoload :TempfileService
|
|
36
39
|
autoload :MimeTypeService
|
|
37
40
|
end
|
|
@@ -48,7 +51,7 @@ module Hydra
|
|
|
48
51
|
end
|
|
49
52
|
|
|
50
53
|
CONFIG_METHODS = [:ffmpeg_path, :libreoffice_path, :temp_file_base, :fits_path, :kdu_compress_path,
|
|
51
|
-
:kdu_compress_recipes, :enable_ffmpeg, :source_file_service, :output_file_service].freeze
|
|
54
|
+
:kdu_compress_recipes, :enable_ffmpeg, :source_file_service, :output_file_service, :active_encode_poll_time].freeze
|
|
52
55
|
CONFIG_METHODS.each do |method|
|
|
53
56
|
module_eval <<-RUBY
|
|
54
57
|
def self.#{method}
|
|
@@ -5,7 +5,8 @@ module Hydra
|
|
|
5
5
|
class Config
|
|
6
6
|
attr_writer :ffmpeg_path, :libreoffice_path, :temp_file_base,
|
|
7
7
|
:source_file_service, :output_file_service, :fits_path,
|
|
8
|
-
:enable_ffmpeg, :kdu_compress_path, :kdu_compress_recipes
|
|
8
|
+
:enable_ffmpeg, :kdu_compress_path, :kdu_compress_recipes,
|
|
9
|
+
:active_encode_poll_time
|
|
9
10
|
|
|
10
11
|
def ffmpeg_path
|
|
11
12
|
@ffmpeg_path ||= 'ffmpeg'
|
|
@@ -72,6 +73,13 @@ module Hydra
|
|
|
72
73
|
"Stiles={1024,1024}" ).gsub(/\s+/, " ").strip
|
|
73
74
|
}
|
|
74
75
|
end
|
|
76
|
+
|
|
77
|
+
# The poll time (in seconds) that the active encode
|
|
78
|
+
# processor will sleep before it checks the status of an
|
|
79
|
+
# encoding job.
|
|
80
|
+
def active_encode_poll_time
|
|
81
|
+
@active_encode_poll_time ||= 10
|
|
82
|
+
end
|
|
75
83
|
end
|
|
76
84
|
end
|
|
77
85
|
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'active_encode'
|
|
2
|
+
|
|
3
|
+
module Hydra::Derivatives::Processors
|
|
4
|
+
class ActiveEncodeError < StandardError
|
|
5
|
+
def initialize(status, source_path, errors = [])
|
|
6
|
+
msg = "ActiveEncode status was \"#{status}\" for #{source_path}"
|
|
7
|
+
msg = "#{msg}: #{errors.join(' ; ')}" if errors.any?
|
|
8
|
+
super(msg)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class ActiveEncode < Processor
|
|
13
|
+
class_attribute :timeout
|
|
14
|
+
attr_accessor :encode_class
|
|
15
|
+
attr_reader :encode_job
|
|
16
|
+
|
|
17
|
+
def initialize(source_path, directives, opts = {})
|
|
18
|
+
super
|
|
19
|
+
@encode_class = opts.delete(:encode_class) || ::ActiveEncode::Base
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def process
|
|
23
|
+
@encode_job = encode_class.create(source_path, directives)
|
|
24
|
+
timeout ? wait_for_encode_job_with_timeout : wait_for_encode_job
|
|
25
|
+
encode_job.output.each do |output|
|
|
26
|
+
output_file_service.call(output, directives)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def wait_for_encode_job_with_timeout
|
|
33
|
+
Timeout.timeout(timeout) { wait_for_encode_job }
|
|
34
|
+
rescue Timeout::Error
|
|
35
|
+
cleanup_after_timeout
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Wait until the encoding job is finished. If the status
|
|
39
|
+
# is anything other than 'completed', raise an error.
|
|
40
|
+
def wait_for_encode_job
|
|
41
|
+
sleep Hydra::Derivatives.active_encode_poll_time while encode_job.reload.running?
|
|
42
|
+
raise ActiveEncodeError.new(encode_job.state, source_path, encode_job.errors) unless encode_job.completed?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# After a timeout error, try to cancel the encoding.
|
|
46
|
+
def cleanup_after_timeout
|
|
47
|
+
encode_job.cancel!
|
|
48
|
+
rescue => e
|
|
49
|
+
cancel_error = e
|
|
50
|
+
ensure
|
|
51
|
+
msg = "Unable to process ActiveEncode derivative: The command took longer than #{timeout} seconds to execute. Encoding will be cancelled."
|
|
52
|
+
msg = "#{msg} An error occurred while trying to cancel encoding: #{cancel_error}" if cancel_error
|
|
53
|
+
raise Hydra::Derivatives::TimeoutError, msg
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -3,7 +3,7 @@ module Hydra::Derivatives::Processors
|
|
|
3
3
|
include ShellBasedProcessor
|
|
4
4
|
|
|
5
5
|
def self.encode(path, format, outdir)
|
|
6
|
-
execute "#{Hydra::Derivatives.libreoffice_path} --invisible --headless --convert-to #{format} --outdir #{outdir} #{path}"
|
|
6
|
+
execute "#{Hydra::Derivatives.libreoffice_path} --invisible --headless --convert-to #{format} --outdir #{outdir} #{Shellwords.escape(path)}"
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
# Converts the document to the format specified in the directives hash.
|
|
@@ -14,7 +14,7 @@ module Hydra::Derivatives::Processors
|
|
|
14
14
|
def encode(path, options, output_file)
|
|
15
15
|
inopts = options[INPUT_OPTIONS] ||= "-y"
|
|
16
16
|
outopts = options[OUTPUT_OPTIONS] ||= ""
|
|
17
|
-
execute "#{Hydra::Derivatives.ffmpeg_path} #{inopts} -i
|
|
17
|
+
execute "#{Hydra::Derivatives.ffmpeg_path} #{inopts} -i #{Shellwords.escape(path)} #{outopts} #{output_file}"
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -75,7 +75,7 @@ module Hydra::Derivatives::Processors
|
|
|
75
75
|
|
|
76
76
|
def encode(path, recipe, output_file)
|
|
77
77
|
kdu_compress = Hydra::Derivatives.kdu_compress_path
|
|
78
|
-
execute "#{kdu_compress} -quiet -i #{path} -o #{output_file} #{recipe}"
|
|
78
|
+
execute "#{kdu_compress} -quiet -i #{Shellwords.escape(path)} -o #{output_file} #{recipe}"
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def tmp_file(ext)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Hydra::Derivatives
|
|
2
|
+
class ActiveEncodeDerivatives < Runner
|
|
3
|
+
# @param [String, ActiveFedora::Base] object_or_filename source file name (or path), or an object that has a method that will return the file name
|
|
4
|
+
# @param [Hash] options options to pass to the encoder
|
|
5
|
+
# @option options [Symbol] :source a method that can be called on the object to retrieve the source file's name
|
|
6
|
+
# @option options [Symbol] :encode_class class name of the encode object (usually a subclass of ::ActiveEncode::Base)
|
|
7
|
+
# @options options [Array] :outputs a list of desired outputs
|
|
8
|
+
def self.create(object_or_filename, options)
|
|
9
|
+
processor_opts = processor_options(options)
|
|
10
|
+
source_file(object_or_filename, options) do |file_name|
|
|
11
|
+
transform_directives(options.delete(:outputs)).each do |instructions|
|
|
12
|
+
processor = processor_class.new(file_name, instructions, processor_opts)
|
|
13
|
+
processor.process
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Use the source service configured for this class or default to the remote file service
|
|
19
|
+
def self.source_file_service
|
|
20
|
+
@source_file_service || RemoteSourceFile
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Use the output service configured for this class or default to the external file service
|
|
24
|
+
def self.output_file_service
|
|
25
|
+
@output_file_service || PersistExternalFileOutputFileService
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.processor_class
|
|
29
|
+
Processors::ActiveEncode
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
# Build an options hash specifically for the processor isolated from the runner options
|
|
36
|
+
def processor_options(options)
|
|
37
|
+
opts = { output_file_service: output_file_service }
|
|
38
|
+
encode_class = options.delete(:encode_class)
|
|
39
|
+
opts = opts.merge(encode_class: encode_class) if encode_class
|
|
40
|
+
opts
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -9,31 +9,55 @@ module Hydra::Derivatives
|
|
|
9
9
|
#
|
|
10
10
|
# NOTE: Uses basic containment. If you want to use direct containment (ie. with PCDM) you must use a different service (ie. Hydra::Works::AddFileToGenericFile Service)
|
|
11
11
|
#
|
|
12
|
-
# @param [
|
|
12
|
+
# @param [IO,String] content the data to be persisted
|
|
13
13
|
# @param [Hash] directives directions which can be used to determine where to persist to.
|
|
14
14
|
# @option directives [String] url This can determine the path of the object.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
uri = URI(directives.fetch(:url))
|
|
20
|
-
raise ArgumentError, "#{uri} is not an http uri" unless uri.scheme == 'http'
|
|
21
|
-
remote_file = ActiveFedora::File.new(uri.to_s)
|
|
15
|
+
# @option directives [String] format The file extension (e.g. 'jpg')
|
|
16
|
+
def self.call(content, directives)
|
|
17
|
+
file = io(content, directives)
|
|
18
|
+
remote_file = retrieve_remote_file(directives)
|
|
22
19
|
remote_file.content = file
|
|
23
|
-
remote_file.mime_type =
|
|
24
|
-
remote_file.original_name =
|
|
20
|
+
remote_file.mime_type = determine_mime_type(file)
|
|
21
|
+
remote_file.original_name = determine_original_name(file)
|
|
25
22
|
remote_file.save
|
|
26
23
|
end
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
# Override this implementation if you need a remote file from a different location
|
|
26
|
+
# @return [ActiveFedora::File]
|
|
27
|
+
def self.retrieve_remote_file(directives)
|
|
28
|
+
uri = URI(directives.fetch(:url))
|
|
29
|
+
raise ArgumentError, "#{uri} is not an http uri" unless uri.scheme == 'http'
|
|
30
|
+
ActiveFedora::File.new(uri.to_s)
|
|
31
|
+
end
|
|
32
|
+
private_class_method :retrieve_remote_file
|
|
33
|
+
|
|
34
|
+
def self.io(content, directives)
|
|
35
|
+
Hydra::Derivatives::IoDecorator.new(content, new_mime_type(directives.fetch(:format), charset(content)))
|
|
36
|
+
end
|
|
37
|
+
private_class_method :io
|
|
38
|
+
|
|
39
|
+
def self.new_mime_type(extension, charset = nil)
|
|
40
|
+
fmt = mime_format(extension)
|
|
41
|
+
fmt += "; charset=#{charset}" if charset
|
|
42
|
+
fmt
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Strings (from FullText) have encoding. Retrieve it
|
|
46
|
+
def self.charset(content)
|
|
47
|
+
content.encoding.name if content.respond_to?(:encoding)
|
|
48
|
+
end
|
|
49
|
+
private_class_method :charset
|
|
50
|
+
|
|
51
|
+
def self.mime_format(extension)
|
|
52
|
+
case extension
|
|
30
53
|
when 'mp4'
|
|
31
54
|
'video/mp4' # default is application/mp4
|
|
32
55
|
when 'webm'
|
|
33
56
|
'video/webm' # default is audio/webm
|
|
34
57
|
else
|
|
35
|
-
MIME::Types.type_for(
|
|
58
|
+
MIME::Types.type_for(extension).first.to_s
|
|
36
59
|
end
|
|
37
60
|
end
|
|
61
|
+
private_class_method :mime_format
|
|
38
62
|
end
|
|
39
63
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'addressable'
|
|
2
|
+
|
|
3
|
+
module Hydra::Derivatives
|
|
4
|
+
class PersistExternalFileOutputFileService < PersistOutputFileService
|
|
5
|
+
# Persists a new file at specified location that points to external content
|
|
6
|
+
# @param [Hash] output information about the external derivative file
|
|
7
|
+
# @option output [String] url the location of the external content
|
|
8
|
+
# @param [Hash] directives directions which can be used to determine where to persist to.
|
|
9
|
+
# @option directives [String] url This can determine the path of the object.
|
|
10
|
+
def self.call(output, directives)
|
|
11
|
+
external_file = ActiveFedora::File.new(directives[:url])
|
|
12
|
+
# TODO: Replace the following two lines with the shorter call to #external_url once active_fedora/pull/1234 is merged
|
|
13
|
+
external_file.content = ''
|
|
14
|
+
external_file.mime_type = "message/external-body; access-type=URL; URL=\"#{output[:url]}\""
|
|
15
|
+
# external_file.external_url = output[:url]
|
|
16
|
+
external_file.original_name = Addressable::URI.parse(output[:url]).path.split('/').last
|
|
17
|
+
external_file.save
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# For the case where the source file is a remote file, and we
|
|
2
|
+
# don't want to download the file locally, just return the
|
|
3
|
+
# file name or file path (or whatever we need to pass to the
|
|
4
|
+
# encoding service so that it can find the file).
|
|
5
|
+
|
|
6
|
+
module Hydra::Derivatives
|
|
7
|
+
class RemoteSourceFile
|
|
8
|
+
# Finds the file name of the remote source file.
|
|
9
|
+
# @param [String, ActiveFedora::Base] object file name, or an object that has a method that will return the file name
|
|
10
|
+
# @param [Hash] options
|
|
11
|
+
# @option options [Symbol] :source a method that can be called on the object to retrieve the source file's name
|
|
12
|
+
# @yield [String] the file name
|
|
13
|
+
def self.call(object, options, &_block)
|
|
14
|
+
source_name = options.fetch(:source, :to_s)
|
|
15
|
+
yield(object.send(source_name))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Hydra::Derivatives::Processors::ActiveEncode do
|
|
4
|
+
let(:file_path) { File.join(fixture_path, 'videoshort.mp4') }
|
|
5
|
+
let(:directives) { { url: '12345/derivative' } }
|
|
6
|
+
let(:output_file_service) { Hydra::Derivatives::PersistExternalFileOutputFileService }
|
|
7
|
+
let(:options) { { output_file_service: output_file_service } }
|
|
8
|
+
let(:processor) { described_class.new(file_path, directives, options) }
|
|
9
|
+
|
|
10
|
+
describe '#process' do
|
|
11
|
+
subject { processor.process }
|
|
12
|
+
|
|
13
|
+
# Mock out the actual encoding, just pretend that the
|
|
14
|
+
# encode finished and returned a certain status.
|
|
15
|
+
let(:failed_status) { false }
|
|
16
|
+
let(:cancelled_status) { false }
|
|
17
|
+
let(:completed_status) { false }
|
|
18
|
+
let(:state) { :completed }
|
|
19
|
+
let(:errors) { [] }
|
|
20
|
+
let(:external_url) { 'http://www.example.com/external/content' }
|
|
21
|
+
let(:output) { [{ url: external_url }] }
|
|
22
|
+
let(:encode_job_double) do
|
|
23
|
+
enc = double('encode_job',
|
|
24
|
+
state: state,
|
|
25
|
+
errors: errors,
|
|
26
|
+
output: output,
|
|
27
|
+
running?: false,
|
|
28
|
+
completed?: completed_status,
|
|
29
|
+
failed?: failed_status,
|
|
30
|
+
cancelled?: cancelled_status)
|
|
31
|
+
allow(enc).to receive(:reload).and_return(enc)
|
|
32
|
+
enc
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'with a custom encode class' do
|
|
36
|
+
before do
|
|
37
|
+
class TestEncode < ::ActiveEncode::Base; end
|
|
38
|
+
|
|
39
|
+
# For this spec we don't care what happens with output,
|
|
40
|
+
# so stub it out to speed up the spec.
|
|
41
|
+
allow(output_file_service).to receive(:call)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
after { Object.send(:remove_const, :TestEncode) }
|
|
45
|
+
|
|
46
|
+
let(:completed_status) { true }
|
|
47
|
+
let(:state) { :completed }
|
|
48
|
+
let(:options) do
|
|
49
|
+
{
|
|
50
|
+
encode_class: TestEncode,
|
|
51
|
+
output_file_service: output_file_service
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'uses the configured encode class' do
|
|
56
|
+
expect(TestEncode).to receive(:create).and_return(encode_job_double)
|
|
57
|
+
subject
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context 'when the encoding failed' do
|
|
62
|
+
let(:state) { :failed }
|
|
63
|
+
let(:failed_status) { true }
|
|
64
|
+
let(:errors) { ['error 1', 'error 2'] }
|
|
65
|
+
|
|
66
|
+
before do
|
|
67
|
+
# Don't really encode the file during specs
|
|
68
|
+
allow(::ActiveEncode::Base).to receive(:create).and_return(encode_job_double)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'raises an exception' do
|
|
72
|
+
expect { subject }.to raise_error(Hydra::Derivatives::Processors::ActiveEncodeError, "ActiveEncode status was \"failed\" for #{file_path}: error 1 ; error 2")
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context 'when the encoding was cancelled' do
|
|
77
|
+
let(:state) { :cancelled }
|
|
78
|
+
let(:cancelled_status) { true }
|
|
79
|
+
|
|
80
|
+
before do
|
|
81
|
+
# Don't really encode the file during specs
|
|
82
|
+
allow(::ActiveEncode::Base).to receive(:create).and_return(encode_job_double)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'raises an exception' do
|
|
86
|
+
expect { subject }.to raise_error(Hydra::Derivatives::Processors::ActiveEncodeError, "ActiveEncode status was \"cancelled\" for #{file_path}")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'when the timeout is set' do
|
|
91
|
+
before do
|
|
92
|
+
processor.timeout = 0.01
|
|
93
|
+
allow(processor).to receive(:wait_for_encode_job) { sleep 0.1 }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'raises a timeout exception' do
|
|
97
|
+
msg = "Unable to process ActiveEncode derivative: The command took longer than 0.01 seconds to execute. Encoding will be cancelled."
|
|
98
|
+
expect { processor.process }.to raise_error Hydra::Derivatives::TimeoutError, msg
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'when the timeout is not set' do
|
|
103
|
+
before do
|
|
104
|
+
processor.timeout = nil
|
|
105
|
+
# Don't really encode the file during specs
|
|
106
|
+
allow(::ActiveEncode::Base).to receive(:create).and_return(encode_job_double)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'processes the encoding without a timeout' do
|
|
110
|
+
expect(processor).not_to receive(:wait_for_encode_job_with_timeout)
|
|
111
|
+
expect(processor).to receive(:wait_for_encode_job).once
|
|
112
|
+
processor.process
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context 'when error occurs during timeout cleanup' do
|
|
117
|
+
let(:error) { StandardError.new('some error message') }
|
|
118
|
+
|
|
119
|
+
before do
|
|
120
|
+
processor.timeout = 0.01
|
|
121
|
+
allow(processor).to receive(:wait_for_encode_job) { sleep 0.1 }
|
|
122
|
+
allow(::ActiveEncode::Base).to receive(:create).and_return(encode_job_double)
|
|
123
|
+
allow(encode_job_double).to receive(:cancel!).and_raise(error)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'doesnt lose the timeout error, but adds the new error message' do
|
|
127
|
+
msg = "Unable to process ActiveEncode derivative: The command took longer than 0.01 seconds to execute. Encoding will be cancelled. An error occurred while trying to cancel encoding: some error message"
|
|
128
|
+
expect { processor.process }.to raise_error Hydra::Derivatives::TimeoutError, msg
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -7,7 +7,10 @@ describe Hydra::Derivatives::Processors::FullText do
|
|
|
7
7
|
|
|
8
8
|
describe "#process" do
|
|
9
9
|
it 'extracts fulltext and stores the results' do
|
|
10
|
-
expect(processor.output_file_service).to receive(:call)
|
|
10
|
+
expect(processor.output_file_service).to receive(:call) do |first, second|
|
|
11
|
+
expect(first).to match(/Project Charter for E-Content Delivery Platform Review/)
|
|
12
|
+
expect(second).to eq directives
|
|
13
|
+
end
|
|
11
14
|
processor.process
|
|
12
15
|
end
|
|
13
16
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Hydra::Derivatives::ActiveEncodeDerivatives do
|
|
4
|
+
context '.create' do
|
|
5
|
+
before do
|
|
6
|
+
class TestVideo < ActiveFedora::Base
|
|
7
|
+
attr_accessor :remote_file_name
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
after { Object.send(:remove_const, :TestVideo) }
|
|
12
|
+
|
|
13
|
+
let(:file_path) { 'some/path/to/my_video.mp4' }
|
|
14
|
+
let(:video_record) { TestVideo.new(remote_file_name: file_path) }
|
|
15
|
+
let(:options) { { source: :remote_file_name, outputs: [low_res_video] } }
|
|
16
|
+
let(:low_res_video) { { some_key: 'some options to pass to my encoder service' } }
|
|
17
|
+
let(:processor) { double('processor') }
|
|
18
|
+
|
|
19
|
+
it 'calls the processor with the right arguments' do
|
|
20
|
+
expect(Hydra::Derivatives::Processors::ActiveEncode).to receive(:new).with(file_path, low_res_video, output_file_service: Hydra::Derivatives::PersistExternalFileOutputFileService).and_return(processor)
|
|
21
|
+
expect(processor).to receive(:process)
|
|
22
|
+
described_class.create(video_record, options)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'with a custom encode class' do
|
|
26
|
+
before { class TestEncode < ::ActiveEncode::Base; end }
|
|
27
|
+
after { Object.send(:remove_const, :TestEncode) }
|
|
28
|
+
|
|
29
|
+
let(:options) { { encode_class: TestEncode, source: :remote_file_name, outputs: [low_res_video] } }
|
|
30
|
+
|
|
31
|
+
it 'calls the processor with the right arguments' do
|
|
32
|
+
expect(Hydra::Derivatives::Processors::ActiveEncode).to receive(:new).with(file_path, low_res_video, output_file_service: Hydra::Derivatives::PersistExternalFileOutputFileService, encode_class: TestEncode).and_return(processor)
|
|
33
|
+
expect(processor).to receive(:process)
|
|
34
|
+
described_class.create(video_record, options)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -17,11 +17,24 @@ describe Hydra::Derivatives::PersistBasicContainedOutputFileService do
|
|
|
17
17
|
# not be sufficient.
|
|
18
18
|
context "when file is basic contained (default assumption)" do
|
|
19
19
|
let(:object) { BasicContainerObject.create }
|
|
20
|
-
let(:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
let(:content) { StringIO.new("fake file content") }
|
|
21
|
+
let(:resource) { object.public_send(destination_name.to_sym) }
|
|
22
|
+
context "and the content is a stream" do
|
|
23
|
+
it "persists the file to the specified destination on the given object" do
|
|
24
|
+
described_class.call(content, format: 'jpg', url: "#{object.uri}/the_derivative_name")
|
|
25
|
+
expect(resource.content).to start_with("fake file content")
|
|
26
|
+
expect(resource.content_changed?).to eq false
|
|
27
|
+
expect(resource.mime_type).to eq 'image/jpeg'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "and content is a string" do
|
|
32
|
+
let(:content) { "fake file content - ÅÄÖ" }
|
|
33
|
+
it "persists the file to the specified destination on the given object" do
|
|
34
|
+
described_class.call(content, format: 'txt', url: "#{object.uri}/the_derivative_name")
|
|
35
|
+
expect(resource.content).to eq("fake file content - ÅÄÖ")
|
|
36
|
+
expect(resource.mime_type).to eq 'text/plain;charset=UTF-8'
|
|
37
|
+
end
|
|
25
38
|
end
|
|
26
39
|
end
|
|
27
40
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Hydra::Derivatives::PersistExternalFileOutputFileService do
|
|
4
|
+
before do
|
|
5
|
+
class ExternalDerivativeContainerObject < ActiveFedora::Base
|
|
6
|
+
has_subresource "external_derivative"
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
after do
|
|
10
|
+
Object.send(:remove_const, :ExternalDerivativeContainerObject)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
let(:object) { ExternalDerivativeContainerObject.create }
|
|
14
|
+
let(:directives) { { url: "#{object.uri}/external_derivative" } }
|
|
15
|
+
let(:external_url) { 'http://www.example.com/external/content' }
|
|
16
|
+
let(:output) { { url: external_url } }
|
|
17
|
+
let(:destination_name) { 'external_derivative' }
|
|
18
|
+
|
|
19
|
+
describe '.call' do
|
|
20
|
+
it "persists the external file to the specified destination on the given object" do
|
|
21
|
+
described_class.call(output, directives)
|
|
22
|
+
expect(object.send(destination_name.to_sym).mime_type).to eq "message/external-body;access-type=URL;url=\"http://www.example.com/external/content\""
|
|
23
|
+
expect(object.send(destination_name.to_sym).content).to eq ''
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class TestObject < ActiveFedora::Base
|
|
4
|
+
attr_accessor :source_file_name
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
describe Hydra::Derivatives::RemoteSourceFile do
|
|
8
|
+
describe '.call' do
|
|
9
|
+
let(:file_name) { 'my_source_file.mp4' }
|
|
10
|
+
|
|
11
|
+
context 'when you pass in a String file name' do
|
|
12
|
+
let(:input_obj) { file_name }
|
|
13
|
+
let(:options) { Hash.new }
|
|
14
|
+
|
|
15
|
+
it 'it yields the file name' do
|
|
16
|
+
expect do |blk|
|
|
17
|
+
described_class.call(input_obj, options, &blk)
|
|
18
|
+
end.to yield_with_args(file_name)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context 'when you pass in an ActiveFedora::Base object ' do
|
|
23
|
+
let(:input_obj) { TestObject.new(source_file_name: file_name) }
|
|
24
|
+
let(:options) { { source: :source_file_name } }
|
|
25
|
+
|
|
26
|
+
it 'it yields the file name' do
|
|
27
|
+
expect do |blk|
|
|
28
|
+
described_class.call(input_obj, options, &blk)
|
|
29
|
+
end.to yield_with_args(file_name)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/spec/units/config_spec.rb
CHANGED
|
@@ -41,4 +41,10 @@ describe "the configuration" do
|
|
|
41
41
|
subject.source_file_service = source_file_service
|
|
42
42
|
expect(subject.source_file_service).to eq(source_file_service)
|
|
43
43
|
end
|
|
44
|
+
|
|
45
|
+
it "lets you set the poll time for ActiveEncode jobs" do
|
|
46
|
+
expect(subject.active_encode_poll_time).to eq 10
|
|
47
|
+
subject.active_encode_poll_time = 15
|
|
48
|
+
expect(subject.active_encode_poll_time).to eq 15
|
|
49
|
+
end
|
|
44
50
|
end
|
|
@@ -53,6 +53,10 @@ describe Hydra::Derivatives do
|
|
|
53
53
|
subject.kdu_compress_path = '/usr/local/bin/kdu_compress'
|
|
54
54
|
subject.reset_config!
|
|
55
55
|
expect(subject.kdu_compress_path).to eq('kdu_compress')
|
|
56
|
+
|
|
57
|
+
subject.active_encode_poll_time = 2
|
|
58
|
+
subject.reset_config!
|
|
59
|
+
expect(subject.active_encode_poll_time).to eq 10
|
|
56
60
|
end
|
|
57
61
|
end
|
|
58
62
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hydra-derivatives
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Coyne
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-
|
|
11
|
+
date: 2017-06-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -86,7 +86,7 @@ dependencies:
|
|
|
86
86
|
requirements:
|
|
87
87
|
- - ">="
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version:
|
|
89
|
+
version: 11.3.1
|
|
90
90
|
- - "<"
|
|
91
91
|
- !ruby/object:Gem::Version
|
|
92
92
|
version: '12'
|
|
@@ -96,7 +96,7 @@ dependencies:
|
|
|
96
96
|
requirements:
|
|
97
97
|
- - ">="
|
|
98
98
|
- !ruby/object:Gem::Version
|
|
99
|
-
version:
|
|
99
|
+
version: 11.3.1
|
|
100
100
|
- - "<"
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
102
|
version: '12'
|
|
@@ -160,6 +160,34 @@ dependencies:
|
|
|
160
160
|
- - "<"
|
|
161
161
|
- !ruby/object:Gem::Version
|
|
162
162
|
version: '4.0'
|
|
163
|
+
- !ruby/object:Gem::Dependency
|
|
164
|
+
name: active_encode
|
|
165
|
+
requirement: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - "~>"
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '0.1'
|
|
170
|
+
type: :runtime
|
|
171
|
+
prerelease: false
|
|
172
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
173
|
+
requirements:
|
|
174
|
+
- - "~>"
|
|
175
|
+
- !ruby/object:Gem::Version
|
|
176
|
+
version: '0.1'
|
|
177
|
+
- !ruby/object:Gem::Dependency
|
|
178
|
+
name: addressable
|
|
179
|
+
requirement: !ruby/object:Gem::Requirement
|
|
180
|
+
requirements:
|
|
181
|
+
- - "~>"
|
|
182
|
+
- !ruby/object:Gem::Version
|
|
183
|
+
version: '2.5'
|
|
184
|
+
type: :runtime
|
|
185
|
+
prerelease: false
|
|
186
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
187
|
+
requirements:
|
|
188
|
+
- - "~>"
|
|
189
|
+
- !ruby/object:Gem::Version
|
|
190
|
+
version: '2.5'
|
|
163
191
|
- !ruby/object:Gem::Dependency
|
|
164
192
|
name: deprecation
|
|
165
193
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -195,6 +223,7 @@ files:
|
|
|
195
223
|
- TODO
|
|
196
224
|
- VERSION
|
|
197
225
|
- config/jetty.yml
|
|
226
|
+
- doc/amazon_elastic_transcoder.md
|
|
198
227
|
- hydra-derivatives.gemspec
|
|
199
228
|
- lib/color_profiles/license.txt
|
|
200
229
|
- lib/color_profiles/sRGB_IEC61966-2-1_no_black_scaling.icc
|
|
@@ -204,6 +233,7 @@ files:
|
|
|
204
233
|
- lib/hydra/derivatives/io_decorator.rb
|
|
205
234
|
- lib/hydra/derivatives/logger.rb
|
|
206
235
|
- lib/hydra/derivatives/processors.rb
|
|
236
|
+
- lib/hydra/derivatives/processors/active_encode.rb
|
|
207
237
|
- lib/hydra/derivatives/processors/audio.rb
|
|
208
238
|
- lib/hydra/derivatives/processors/document.rb
|
|
209
239
|
- lib/hydra/derivatives/processors/ffmpeg.rb
|
|
@@ -216,6 +246,7 @@ files:
|
|
|
216
246
|
- lib/hydra/derivatives/processors/video.rb
|
|
217
247
|
- lib/hydra/derivatives/processors/video/config.rb
|
|
218
248
|
- lib/hydra/derivatives/processors/video/processor.rb
|
|
249
|
+
- lib/hydra/derivatives/runners/active_encode_derivatives.rb
|
|
219
250
|
- lib/hydra/derivatives/runners/audio_derivatives.rb
|
|
220
251
|
- lib/hydra/derivatives/runners/document_derivatives.rb
|
|
221
252
|
- lib/hydra/derivatives/runners/full_text_extract.rb
|
|
@@ -227,7 +258,9 @@ files:
|
|
|
227
258
|
- lib/hydra/derivatives/services/capability_service.rb
|
|
228
259
|
- lib/hydra/derivatives/services/mime_type_service.rb
|
|
229
260
|
- lib/hydra/derivatives/services/persist_basic_contained_output_file_service.rb
|
|
261
|
+
- lib/hydra/derivatives/services/persist_external_file_output_file_service.rb
|
|
230
262
|
- lib/hydra/derivatives/services/persist_output_file_service.rb
|
|
263
|
+
- lib/hydra/derivatives/services/remote_source_file.rb
|
|
231
264
|
- lib/hydra/derivatives/services/retrieve_source_file_service.rb
|
|
232
265
|
- lib/hydra/derivatives/services/tempfile_service.rb
|
|
233
266
|
- solr/config/_rest_managed.json
|
|
@@ -261,6 +294,7 @@ files:
|
|
|
261
294
|
- spec/fixtures/test.xls
|
|
262
295
|
- spec/fixtures/test.xlsx
|
|
263
296
|
- spec/fixtures/world.png
|
|
297
|
+
- spec/processors/active_encode_spec.rb
|
|
264
298
|
- spec/processors/document_spec.rb
|
|
265
299
|
- spec/processors/full_text_spec.rb
|
|
266
300
|
- spec/processors/image_spec.rb
|
|
@@ -268,8 +302,11 @@ files:
|
|
|
268
302
|
- spec/processors/processor_spec.rb
|
|
269
303
|
- spec/processors/shell_based_processor_spec.rb
|
|
270
304
|
- spec/processors/video_spec.rb
|
|
305
|
+
- spec/runners/active_encode_derivatives_spec.rb
|
|
271
306
|
- spec/services/audio_derivatives_spec.rb
|
|
272
307
|
- spec/services/persist_basic_contained_output_file_service_spec.rb
|
|
308
|
+
- spec/services/persist_external_file_output_file_service_spec.rb
|
|
309
|
+
- spec/services/remote_source_file_spec.rb
|
|
273
310
|
- spec/services/retrieve_source_file_service_spec.rb
|
|
274
311
|
- spec/services/tempfile_service_spec.rb
|
|
275
312
|
- spec/spec_helper.rb
|
|
@@ -299,7 +336,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
299
336
|
version: '0'
|
|
300
337
|
requirements: []
|
|
301
338
|
rubyforge_project:
|
|
302
|
-
rubygems_version: 2.6.
|
|
339
|
+
rubygems_version: 2.6.12
|
|
303
340
|
signing_key:
|
|
304
341
|
specification_version: 4
|
|
305
342
|
summary: Derivative generation plugin for hydra
|
|
@@ -319,6 +356,7 @@ test_files:
|
|
|
319
356
|
- spec/fixtures/test.xls
|
|
320
357
|
- spec/fixtures/test.xlsx
|
|
321
358
|
- spec/fixtures/world.png
|
|
359
|
+
- spec/processors/active_encode_spec.rb
|
|
322
360
|
- spec/processors/document_spec.rb
|
|
323
361
|
- spec/processors/full_text_spec.rb
|
|
324
362
|
- spec/processors/image_spec.rb
|
|
@@ -326,8 +364,11 @@ test_files:
|
|
|
326
364
|
- spec/processors/processor_spec.rb
|
|
327
365
|
- spec/processors/shell_based_processor_spec.rb
|
|
328
366
|
- spec/processors/video_spec.rb
|
|
367
|
+
- spec/runners/active_encode_derivatives_spec.rb
|
|
329
368
|
- spec/services/audio_derivatives_spec.rb
|
|
330
369
|
- spec/services/persist_basic_contained_output_file_service_spec.rb
|
|
370
|
+
- spec/services/persist_external_file_output_file_service_spec.rb
|
|
371
|
+
- spec/services/remote_source_file_spec.rb
|
|
331
372
|
- spec/services/retrieve_source_file_service_spec.rb
|
|
332
373
|
- spec/services/tempfile_service_spec.rb
|
|
333
374
|
- spec/spec_helper.rb
|