hydra-derivatives 3.2.2 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|