hydra-derivatives 1.2.1 → 2.0.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 +1 -2
- data/README.md +12 -12
- data/VERSION +1 -1
- data/hydra-derivatives.gemspec +2 -2
- data/lib/hydra/derivatives.rb +26 -3
- data/lib/hydra/derivatives/config.rb +11 -1
- data/lib/hydra/derivatives/document.rb +4 -3
- data/lib/hydra/derivatives/extract_metadata.rb +0 -1
- data/lib/hydra/derivatives/image.rb +22 -12
- data/lib/hydra/derivatives/io_decorator.rb +15 -0
- data/lib/hydra/derivatives/jpeg2k_image.rb +5 -3
- data/lib/hydra/derivatives/processor.rb +9 -13
- data/lib/hydra/derivatives/raw_image.rb +45 -0
- data/lib/hydra/derivatives/services/persist_basic_contained_output_file_service.rb +25 -0
- data/lib/hydra/derivatives/services/persist_output_file_service.rb +31 -0
- data/lib/hydra/derivatives/services/retrieve_source_file_service.rb +12 -0
- data/lib/hydra/derivatives/{tempfile_service.rb → services/tempfile_service.rb} +0 -0
- data/lib/hydra/derivatives/shell_based_processor.rb +4 -3
- data/spec/fixtures/test.dng +0 -0
- data/spec/services/persist_basic_contained_output_file_service_spec.rb +28 -0
- data/spec/services/retrieve_source_file_service_spec.rb +56 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/units/config_spec.rb +15 -1
- data/spec/units/derivatives_spec.rb +15 -0
- data/spec/units/image_spec.rb +3 -3
- data/spec/units/processor_spec.rb +61 -0
- data/spec/units/transcoding_spec.rb +97 -70
- metadata +25 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c023bf84dd9a0305bbecdeda90d7d8986153adc
|
4
|
+
data.tar.gz: 24543bbc4676d4a992249de13bae1750b188622c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7634f4729547506988e49107de96224037b3b036e9d8f7feada641e4f338bcf7e9c3f03eaa77ea5c2ea6301d3bd0a83ac6090f1b464fadc3f651c9e25d12c8c1
|
7
|
+
data.tar.gz: f0e16f0e1652fe06eb9728f76e51aef55b1ac23b7023b99de0587456ae4186ea68df7163bac7b75c2900023beef7dd0d311d24763504a31d8da3feec575e7e46
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -14,15 +14,15 @@ If you have an ActiveFedora class like this:
|
|
14
14
|
makes_derivatives do |obj|
|
15
15
|
case obj.mime_type
|
16
16
|
when 'application/pdf'
|
17
|
-
obj.transform_file :
|
17
|
+
obj.transform_file :original_file, { :thumb => "100x100>" }
|
18
18
|
when 'audio/wav'
|
19
|
-
obj.transform_file :
|
19
|
+
obj.transform_file :original_file, { :mp3 => {format: 'mp3'}, :ogg => {format: 'ogg'} }, processor: :audio
|
20
20
|
when 'video/avi'
|
21
|
-
obj.transform_file :
|
21
|
+
obj.transform_file :original_file, { :mp4 => {format: 'mp4'}, :webm => {format: 'webm'} }, processor: :video
|
22
22
|
when 'image/png', 'image/jpg'
|
23
|
-
obj.transform_file :
|
23
|
+
obj.transform_file :original_file, { :medium => "300x300>", :thumb => "100x100>" }
|
24
24
|
when 'image/tiff'
|
25
|
-
obj.transform_file :
|
25
|
+
obj.transform_file :original_file, { :service => { resize: "3600x3600>" } }, processor: 'jpeg2k_image'
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -34,7 +34,7 @@ Or a class like this:
|
|
34
34
|
class GenericFile < ActiveFedora::Base
|
35
35
|
include Hydra::Derivatives
|
36
36
|
|
37
|
-
contains '
|
37
|
+
contains 'original_file'
|
38
38
|
attr_accessor :mime_type
|
39
39
|
|
40
40
|
# Use a callback method to declare which derivatives you want
|
@@ -43,15 +43,15 @@ Or a class like this:
|
|
43
43
|
def generate_derivatives
|
44
44
|
case mime_type
|
45
45
|
when 'application/pdf'
|
46
|
-
transform_file :
|
46
|
+
transform_file :original_file, { :thumb => "100x100>" }
|
47
47
|
when 'audio/wav'
|
48
|
-
transform_file :
|
48
|
+
transform_file :original_file, { :mp3 => {format: 'mp3'}, :ogg => {format: 'ogg'} }, processor: :audio
|
49
49
|
when 'video/avi'
|
50
|
-
transform_file :
|
50
|
+
transform_file :original_file, { :mp4 => {format: 'mp4'}, :webm => {format: 'webm'} }, processor: :video
|
51
51
|
when 'image/png', 'image/jpg'
|
52
|
-
transform_file :
|
52
|
+
transform_file :original_file, { :medium => "300x300>", :thumb => {size: "100x100>", datastream: 'thumbnail'} }
|
53
53
|
when 'image/tiff'
|
54
|
-
transform_file :
|
54
|
+
transform_file :original_file, { :service => { recipe: :default } }, processor: 'jpeg2k_image'
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -61,7 +61,7 @@ And you add some content to it:
|
|
61
61
|
|
62
62
|
```ruby
|
63
63
|
obj = GenericFile.new
|
64
|
-
obj.
|
64
|
+
obj.original_file.content = File.open(...)
|
65
65
|
obj.mime_type = 'image/jpg'
|
66
66
|
obj.save
|
67
67
|
```
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
data/hydra-derivatives.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_dependency 'hydra-file_characterization', '~> 0.3'
|
27
27
|
spec.add_dependency 'mini_magick', '>= 3.2', '< 5'
|
28
28
|
spec.add_dependency 'activesupport', '~> 4.0'
|
29
|
-
spec.add_dependency 'mime-types', '
|
30
|
-
spec.add_dependency 'deprecation'
|
29
|
+
spec.add_dependency 'mime-types', '< 3'
|
30
|
+
spec.add_dependency 'deprecation'
|
31
31
|
end
|
32
32
|
|
data/lib/hydra/derivatives.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_fedora'
|
2
2
|
require 'hydra/derivatives/railtie' if defined?(Rails)
|
3
3
|
require 'deprecation'
|
4
|
+
|
4
5
|
module Hydra
|
5
6
|
module Derivatives
|
6
7
|
extend ActiveSupport::Concern
|
@@ -18,8 +19,16 @@ module Hydra
|
|
18
19
|
autoload :ExtractMetadata
|
19
20
|
autoload :ShellBasedProcessor
|
20
21
|
autoload :Jpeg2kImage
|
22
|
+
autoload :RawImage
|
21
23
|
autoload :Logger
|
22
24
|
autoload :TempfileService
|
25
|
+
autoload :IoDecorator
|
26
|
+
|
27
|
+
# services
|
28
|
+
autoload :RetrieveSourceFileService, 'hydra/derivatives/services/retrieve_source_file_service'
|
29
|
+
autoload :PersistOutputFileService, 'hydra/derivatives/services/persist_output_file_service'
|
30
|
+
autoload :PersistBasicContainedOutputFileService, 'hydra/derivatives/services/persist_basic_contained_output_file_service'
|
31
|
+
autoload :TempfileService, 'hydra/derivatives/services/tempfile_service'
|
23
32
|
|
24
33
|
# Raised if the timout elapses
|
25
34
|
class TimeoutError < ::Timeout::Error; end
|
@@ -33,7 +42,7 @@ module Hydra
|
|
33
42
|
end
|
34
43
|
|
35
44
|
[:ffmpeg_path, :libreoffice_path, :temp_file_base, :fits_path, :kdu_compress_path,
|
36
|
-
:kdu_compress_recipes, :enable_ffmpeg].each do |method|
|
45
|
+
:kdu_compress_recipes, :enable_ffmpeg, :source_file_service, :output_file_service].each do |method|
|
37
46
|
module_eval <<-RUBY
|
38
47
|
def self.#{method.to_s}
|
39
48
|
config.#{method.to_s}
|
@@ -68,6 +77,9 @@ module Hydra
|
|
68
77
|
# @param file_name
|
69
78
|
# @param [Hash] transform_directives - each key corresponds to a desired derivative. Associated values vary according to processor being used.
|
70
79
|
# @param [Hash] opts for specifying things like choice of :processor (processor defaults to :image)
|
80
|
+
# @option opts [Symbol] :processor (:image) Processor to use
|
81
|
+
# @option opts [Class] :source_file_service (Hydra::Derivatives::RetrieveSourceFileService) service to use when persisting generated derivatives. The default for this can be set in your config file.
|
82
|
+
# @option opts [Class] :output_file_service (Hydra::Derivatives::PersistIndirectlyContainedOutputFile) service to use when retrieving the source. The default for this can be set in your config file.
|
71
83
|
#
|
72
84
|
# @example This will create content_thumb
|
73
85
|
# transform_file :content, { :thumb => "100x100>" }
|
@@ -82,9 +94,14 @@ module Hydra
|
|
82
94
|
# transform_file :content, { :mp3 => {format: 'mp3'}, :ogg => {format: 'ogg'} }, processor: :audio
|
83
95
|
# transform_file :content, { :mp4 => {format: 'mp4'}, :webm => {format: 'webm'} }, processor: :video
|
84
96
|
#
|
97
|
+
# @example Specify an output file service to use when persisting generated derivatives
|
98
|
+
# obj.transform_file :content, { mp4: { format: 'mp4' } }, processor: :video, output_file_service: My::System::PersistOutputFileToTapeStorage
|
99
|
+
#
|
100
|
+
# @example Specify a source file service to use when retrieving the source
|
101
|
+
# obj.transform_file :content, { mp4: { format: 'mp4' } }, processor: :video, source_file_service: My::System::PersistOutputFileToTapeStorage
|
102
|
+
|
85
103
|
def transform_file(file_name, transform_directives, opts={})
|
86
|
-
|
87
|
-
processor.new(self, file_name, transform_directives).process
|
104
|
+
initialize_processor(file_name, transform_directives, opts).process
|
88
105
|
end
|
89
106
|
|
90
107
|
def processor_class(processor)
|
@@ -139,5 +156,11 @@ module Hydra
|
|
139
156
|
end
|
140
157
|
end
|
141
158
|
end
|
159
|
+
|
160
|
+
private
|
161
|
+
def initialize_processor(file_name, transform_directives, opts={})
|
162
|
+
processor_class(opts[:processor] || :image).new(self, file_name, transform_directives, opts)
|
163
|
+
end
|
164
|
+
|
142
165
|
end
|
143
166
|
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
module Hydra
|
2
2
|
module Derivatives
|
3
3
|
class Config
|
4
|
-
attr_writer :ffmpeg_path, :libreoffice_path, :temp_file_base,
|
4
|
+
attr_writer :ffmpeg_path, :libreoffice_path, :temp_file_base,
|
5
|
+
:source_file_service, :output_file_service, :fits_path,
|
5
6
|
:enable_ffmpeg, :kdu_compress_path, :kdu_compress_recipes
|
7
|
+
|
6
8
|
def ffmpeg_path
|
7
9
|
@ffmpeg_path ||= 'ffmpeg'
|
8
10
|
end
|
@@ -15,6 +17,14 @@ module Hydra
|
|
15
17
|
@temp_file_base ||= '/tmp'
|
16
18
|
end
|
17
19
|
|
20
|
+
def source_file_service
|
21
|
+
@source_file_service ||= Hydra::Derivatives::RetrieveSourceFileService
|
22
|
+
end
|
23
|
+
|
24
|
+
def output_file_service
|
25
|
+
@output_file_service ||= Hydra::Derivatives::PersistBasicContainedOutputFileService
|
26
|
+
end
|
27
|
+
|
18
28
|
def fits_path
|
19
29
|
@fits_path ||= 'fits.sh'
|
20
30
|
end
|
@@ -9,7 +9,7 @@ module Hydra
|
|
9
9
|
execute "#{Hydra::Derivatives.libreoffice_path} --invisible --headless --convert-to #{format} --outdir #{outdir} #{path}"
|
10
10
|
end
|
11
11
|
|
12
|
-
def encode_file(
|
12
|
+
def encode_file(destination_name, file_suffix, mime_type, options = { })
|
13
13
|
new_output = ''
|
14
14
|
Hydra::Derivatives::TempfileService.create(source_file) do |f|
|
15
15
|
if mime_type == 'image/jpeg'
|
@@ -23,8 +23,9 @@ module Hydra
|
|
23
23
|
new_output = File.join(Hydra::Derivatives.temp_file_base, [File.basename(f.path).sub(File.extname(f.path), ''), file_suffix].join('.'))
|
24
24
|
end
|
25
25
|
end
|
26
|
-
out_file = File.open(new_output, "rb")
|
27
|
-
|
26
|
+
out_file = Hydra::Derivatives::IoDecorator.new(File.open(new_output, "rb"))
|
27
|
+
out_file.mime_type = mime_type
|
28
|
+
output_file_service.call(object, out_file, destination_name)
|
28
29
|
File.unlink(out_file)
|
29
30
|
end
|
30
31
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'mini_magick'
|
2
|
+
|
2
3
|
module Hydra
|
3
4
|
module Derivatives
|
4
5
|
class Image < Processor
|
@@ -20,9 +21,16 @@ module Hydra
|
|
20
21
|
directives.each do |name, args|
|
21
22
|
opts = args.kind_of?(Hash) ? args : {size: args}
|
22
23
|
format = opts.fetch(:format, 'png')
|
23
|
-
|
24
|
-
create_resized_image(
|
24
|
+
destination_name = output_filename_for(name, opts)
|
25
|
+
create_resized_image(destination_name, opts[:size], format)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def output_filename_for(name, opts = {})
|
30
|
+
if opts.has_key? :datastream
|
31
|
+
Deprecation.warn Hydra::Derivatives::Image, 'The :datastream option is deprecated and will be removed in a future release.'
|
25
32
|
end
|
33
|
+
opts.fetch(:datastream, output_file_id(name))
|
26
34
|
end
|
27
35
|
|
28
36
|
protected
|
@@ -31,26 +39,28 @@ module Hydra
|
|
31
39
|
MIME::Types.type_for(format).first.to_s
|
32
40
|
end
|
33
41
|
|
34
|
-
def create_resized_image(
|
35
|
-
create_image(
|
42
|
+
def create_resized_image(destination_name, size, format, quality=nil)
|
43
|
+
create_image(destination_name, format, quality) do |xfrm|
|
36
44
|
xfrm.resize(size) if size.present?
|
37
45
|
end
|
38
|
-
output_file.mime_type = new_mime_type(format)
|
39
46
|
end
|
40
47
|
|
41
|
-
def create_image(
|
48
|
+
def create_image(destination_name, format, quality=nil)
|
42
49
|
xfrm = load_image_transformer
|
43
50
|
yield(xfrm) if block_given?
|
44
51
|
xfrm.format(format)
|
45
52
|
xfrm.quality(quality.to_s) if quality
|
46
|
-
write_image(
|
53
|
+
write_image(destination_name, format, xfrm)
|
47
54
|
end
|
48
55
|
|
49
|
-
def write_image(
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
56
|
+
def write_image(destination_name, format, xfrm)
|
57
|
+
output_io = Hydra::Derivatives::IoDecorator.new(StringIO.new)
|
58
|
+
output_io.mime_type = new_mime_type(format)
|
59
|
+
|
60
|
+
xfrm.write(output_io)
|
61
|
+
output_io.rewind
|
62
|
+
|
63
|
+
output_file_service.call(object, output_io, destination_name)
|
54
64
|
end
|
55
65
|
|
56
66
|
# Override this method if you want a different transformer, or need to load the
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Nieve implementation of IO wrapper class that adds mime_type and original_name attributes.
|
2
|
+
# This is done so the attributes do not have to be passed as additional arguments,
|
3
|
+
# and are attached properly to the object they describe.
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# Use SimpleDelegator to wrap the given class or instance
|
7
|
+
require 'delegate'
|
8
|
+
|
9
|
+
module Hydra
|
10
|
+
module Derivatives
|
11
|
+
class IoDecorator < SimpleDelegator
|
12
|
+
attr_accessor :mime_type, :original_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -25,7 +25,7 @@ module Hydra
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def encode_file(
|
28
|
+
def encode_file(destination_name, recipe, opts={})
|
29
29
|
output_file = self.class.tmp_file('.jp2')
|
30
30
|
if opts[:file_path]
|
31
31
|
self.class.encode(opts[:file_path], recipe, output_file)
|
@@ -34,8 +34,10 @@ module Hydra
|
|
34
34
|
self.class.encode(f.path, recipe, output_file)
|
35
35
|
end
|
36
36
|
end
|
37
|
-
out_file = File.open(output_file, "rb")
|
38
|
-
|
37
|
+
out_file = Hydra::Derivatives::IoDecorator.new(File.open(output_file, "rb"))
|
38
|
+
out_file.mime_type = "image/jp2"
|
39
|
+
output_file_service.call(object, out_file, destination_name)
|
40
|
+
|
39
41
|
File.unlink(output_file)
|
40
42
|
end
|
41
43
|
|
@@ -1,12 +1,14 @@
|
|
1
1
|
module Hydra
|
2
2
|
module Derivatives
|
3
3
|
class Processor
|
4
|
-
attr_accessor :object, :source_name, :directives
|
4
|
+
attr_accessor :object, :source_name, :directives, :source_file_service, :output_file_service
|
5
5
|
|
6
|
-
def initialize(obj, source_name, directives)
|
6
|
+
def initialize(obj, source_name, directives, opts={})
|
7
7
|
self.object = obj
|
8
8
|
self.source_name = source_name
|
9
9
|
self.directives = directives
|
10
|
+
self.source_file_service = opts.fetch(:source_file_service, Hydra::Derivatives.source_file_service)
|
11
|
+
self.output_file_service = opts.fetch(:output_file_service, Hydra::Derivatives.output_file_service)
|
10
12
|
end
|
11
13
|
|
12
14
|
def process
|
@@ -17,19 +19,13 @@ module Hydra
|
|
17
19
|
[source_name, name].join('_')
|
18
20
|
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
object.attached_files[path]
|
24
|
-
else
|
25
|
-
ActiveFedora::File.new("#{object.uri}/#{path}").tap do |file|
|
26
|
-
object.attach_file(file, path)
|
27
|
-
end
|
28
|
-
end
|
22
|
+
# @deprecated Please use a PersistOutputFileService class to save an object
|
23
|
+
def output_file
|
24
|
+
raise NotImplementedError, "Processor is an abstract class. Utilize an implementation of a PersistOutputFileService class in #{self.class.name}"
|
29
25
|
end
|
30
|
-
|
26
|
+
|
31
27
|
def source_file
|
32
|
-
object
|
28
|
+
@source_file ||= source_file_service.call(object, source_name)
|
33
29
|
end
|
34
30
|
|
35
31
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'mini_magick'
|
2
|
+
|
3
|
+
module Hydra
|
4
|
+
module Derivatives
|
5
|
+
class RawImage < Image
|
6
|
+
class_attribute :timeout
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def create_image(destination_name, format, quality=nil)
|
11
|
+
xfrm = load_image_transformer
|
12
|
+
# Transpose format and scaling due to the fact that ImageMagick can
|
13
|
+
# read but not write RAW files and this will otherwise cause many
|
14
|
+
# cryptic segmentation faults
|
15
|
+
xfrm.format(format)
|
16
|
+
yield(xfrm) if block_given?
|
17
|
+
xfrm.quality(quality.to_s) if quality
|
18
|
+
write_image(destination_name, format, xfrm)
|
19
|
+
remove_temp_files(xfrm)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Delete any temp files that might clutter up the disk if
|
23
|
+
# you are doing a batch or don't touch your temporary storage
|
24
|
+
# for a long time
|
25
|
+
def remove_temp_files(xfrm)
|
26
|
+
xfrm.destroy!
|
27
|
+
end
|
28
|
+
|
29
|
+
# Override this method if you want a different transformer, or # need to load the raw image from a different source (e.g.
|
30
|
+
# external file).
|
31
|
+
#
|
32
|
+
# In this case always add an extension to help out MiniMagick
|
33
|
+
# with RAW files
|
34
|
+
def load_image_transformer
|
35
|
+
extension = MIME::Types[source_file.mime_type].first.extensions.first
|
36
|
+
|
37
|
+
if extension.present?
|
38
|
+
MiniMagick::Image.read(source_file.content, ".#{extension}")
|
39
|
+
else
|
40
|
+
MiniMagick::Image.read(source_file.content)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Hydra::Derivatives
|
2
|
+
# This Service is an implementation of the Hydra::Derivatives::PeristOutputFileService
|
3
|
+
# It supports basic contained files, which is the behavior associated with Fedora 3 file datastreams that were migrated to Fedora 4
|
4
|
+
# and, at the time that this class was authored, corresponds to the behavior of ActiveFedora::Base.attach_file and ActiveFedora::Base.attached_files
|
5
|
+
### Rename this
|
6
|
+
class PersistBasicContainedOutputFileService < PersistOutputFileService
|
7
|
+
|
8
|
+
# This method conforms to the signature of the .call method on Hydra::Derivatives::PeristOutputFileService
|
9
|
+
# * Persists the file within the object at destination_name
|
10
|
+
#
|
11
|
+
# 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)
|
12
|
+
#
|
13
|
+
# @param [ActiveFedora::Base] object file is be persisted to
|
14
|
+
# @param [File] filestream to be added, should respond to :mime_type and :original_name
|
15
|
+
# original_name will get used as the path for a chile resource in fedora, it is not a path to a file on disk.
|
16
|
+
|
17
|
+
def self.call(object, file, destination_path)
|
18
|
+
o_name = determine_original_name(file)
|
19
|
+
m_type = determine_mime_type(file)
|
20
|
+
object.add_file(file, path: destination_path, mime_type: m_type, original_name: o_name)
|
21
|
+
object.save
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Hydra::Derivatives
|
2
|
+
class PersistOutputFileService
|
3
|
+
|
4
|
+
# Persists the file within the object at destination_name. Uses basic containment.
|
5
|
+
# If you want to use direct containment (ie. with PCDM) you must use a different service (ie. Hydra::Works::AddFileToGenericFile Service)
|
6
|
+
# @param [Object] object the source file is attached to
|
7
|
+
# @param [File] filestream to be added, should respond to :mime_type, :original_name
|
8
|
+
# @param [String] destination_name is the fedora path at which the child resource will be found or created beneath the object.
|
9
|
+
|
10
|
+
def self.call(object, file, destination_path)
|
11
|
+
raise NotImplementedError, "PersistOutputFileService is an abstract class. Implement `call' on #{self.class.name}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.determine_original_name( file )
|
15
|
+
if file.respond_to? :original_name
|
16
|
+
file.original_name
|
17
|
+
else
|
18
|
+
"derivative"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.determine_mime_type( file )
|
23
|
+
if file.respond_to? :mime_type
|
24
|
+
file.mime_type
|
25
|
+
else
|
26
|
+
"appliction/octet-stream"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Hydra::Derivatives
|
2
|
+
class RetrieveSourceFileService
|
3
|
+
|
4
|
+
# Retrieves the source
|
5
|
+
# @param [Object] object the source file is attached to
|
6
|
+
# @param [String] method name that can be called on object to retrieve the source file
|
7
|
+
|
8
|
+
def self.call(object, source_name)
|
9
|
+
object.send(source_name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
File without changes
|
@@ -29,14 +29,15 @@ module Hydra
|
|
29
29
|
{}
|
30
30
|
end
|
31
31
|
|
32
|
-
def encode_file(
|
32
|
+
def encode_file(destination_name, file_suffix, mime_type, options)
|
33
33
|
out_file = nil
|
34
34
|
output_file = Dir::Tmpname.create(['sufia', ".#{file_suffix}"], Hydra::Derivatives.temp_file_base){}
|
35
35
|
Hydra::Derivatives::TempfileService.create(source_file) do |f|
|
36
36
|
self.class.encode(f.path, options, output_file)
|
37
37
|
end
|
38
|
-
out_file = File.open(output_file, "rb")
|
39
|
-
|
38
|
+
out_file = Hydra::Derivatives::IoDecorator.new(File.open(output_file, "rb"))
|
39
|
+
out_file.mime_type = mime_type
|
40
|
+
output_file_service.call(object, out_file, destination_name)
|
40
41
|
File.unlink(output_file)
|
41
42
|
end
|
42
43
|
|
Binary file
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::Derivatives::PersistBasicContainedOutputFileService do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class BasicContainerObject < ActiveFedora::Base
|
7
|
+
contains "the_derivative_name"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:object) { BasicContainerObject.new }
|
12
|
+
let(:file_path) { File.join(fixture_path, 'test.tif') }
|
13
|
+
let(:file) { File.new(file_path)}
|
14
|
+
let(:destination_name) { 'the_derivative_name' }
|
15
|
+
|
16
|
+
# alas, we have to support this as the default because all legacy code (and fedora 3 systems) created basic contained files
|
17
|
+
# The new signature does not have a destination_name option. There is a default string that will get applied, but his might
|
18
|
+
# not be sufficient.
|
19
|
+
context "when file is basic contained (default assumption)" do
|
20
|
+
let(:object) { BasicContainerObject.new }
|
21
|
+
it "persists the file to the specified destination on the given object" do
|
22
|
+
described_class.call(object, "fake file content", destination_name)
|
23
|
+
expect(object.send(destination_name.to_sym).content).to eq("fake file content")
|
24
|
+
expect(object.send(destination_name.to_sym).content_changed?).to eq false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::Derivatives::RetrieveSourceFileService do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
|
7
|
+
# Need a class that:
|
8
|
+
# 1) Allows you to set .uri= (to work with directly_contains)
|
9
|
+
# 2) has a metadata_node (to work with directly_contains_one)
|
10
|
+
class FileWithMetadata < ActiveFedora::File
|
11
|
+
include ActiveFedora::WithMetadata
|
12
|
+
end
|
13
|
+
|
14
|
+
class ObjectWithBasicContainer < ActiveFedora::Base
|
15
|
+
contains "contained_file"
|
16
|
+
end
|
17
|
+
|
18
|
+
class DirectContainerObject < ActiveFedora::Base
|
19
|
+
directly_contains :files, has_member_relation: ::RDF::URI("http://pcdm.org/use#hasFile"),
|
20
|
+
class_name: "FileWithMetadata"
|
21
|
+
directly_contains_one :directly_contained_file, through: :files, type: ::RDF::URI("http://pcdm.org/use#OriginalFile")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
subject { described_class.call(object, source_name) }
|
26
|
+
|
27
|
+
context "when file is in basic container (default assumption)" do # alas, we have to support this as the default because all legacy code (and fedora 3 systems) created indirectly contained files
|
28
|
+
let(:object) { ObjectWithBasicContainer.new }
|
29
|
+
let(:content) { "fake file content (basic container)" }
|
30
|
+
let(:source_name) { 'contained_file' }
|
31
|
+
|
32
|
+
before do
|
33
|
+
# attaches the file as an indirectly contained object
|
34
|
+
object.contained_file.content = content
|
35
|
+
end
|
36
|
+
it "persists the file to the specified destination on the given object" do
|
37
|
+
expect(subject).to eq(object.contained_file)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when file is directly contained" do # direct containers are more efficient, but most legacy code will have indirect containers
|
42
|
+
let(:object) { DirectContainerObject.new }
|
43
|
+
let(:content) { "fake file content (direct container)" }
|
44
|
+
let(:source_name) { 'directly_contained_file' }
|
45
|
+
|
46
|
+
before do
|
47
|
+
object.save # can't build directly contained objects without saving the parent first
|
48
|
+
object.build_directly_contained_file
|
49
|
+
object.directly_contained_file.content = content
|
50
|
+
end
|
51
|
+
it "retrieves the file from the specified location on the given object" do
|
52
|
+
expect(subject).to eq(object.directly_contained_file)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -12,4 +12,15 @@ RSpec.configure do |config|
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
# Workaround for RAW image support until these are pushed upstream to
|
16
|
+
# the MIME Types gem
|
17
|
+
require 'mime-types'
|
18
|
+
dng_format = MIME::Type.new('image/x-adobe-dng')
|
19
|
+
dng_format.extensions = 'dng'
|
20
|
+
MIME::Types.add(dng_format)
|
21
|
+
|
15
22
|
$in_travis = !ENV['TRAVIS'].nil? && ENV['TRAVIS'] == 'true'
|
23
|
+
|
24
|
+
def fixture_path
|
25
|
+
File.expand_path("../fixtures", __FILE__)
|
26
|
+
end
|
data/spec/units/config_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "the configuration" do
|
4
|
-
subject {Hydra::Derivatives }
|
4
|
+
subject { Hydra::Derivatives }
|
5
5
|
|
6
6
|
it "should have some configuration defaults" do
|
7
7
|
expect(subject.ffmpeg_path).to eq('ffmpeg')
|
@@ -10,6 +10,8 @@ describe "the configuration" do
|
|
10
10
|
expect(subject.temp_file_base).to eq('/tmp')
|
11
11
|
expect(subject.fits_path).to eq('fits.sh')
|
12
12
|
expect(subject.kdu_compress_path).to eq('kdu_compress')
|
13
|
+
expect(subject.output_file_service).to eq(Hydra::Derivatives::PersistBasicContainedOutputFileService)
|
14
|
+
expect(subject.source_file_service).to eq(Hydra::Derivatives::RetrieveSourceFileService)
|
13
15
|
end
|
14
16
|
|
15
17
|
it "should let you change the configuration" do
|
@@ -21,6 +23,18 @@ describe "the configuration" do
|
|
21
23
|
|
22
24
|
end
|
23
25
|
|
26
|
+
it "should let you set a custom output file service" do
|
27
|
+
output_file_service = double("MyOutputFileService")
|
28
|
+
subject.output_file_service = output_file_service
|
29
|
+
expect(subject.output_file_service).to eq(output_file_service)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should let you set a custom source file service" do
|
33
|
+
source_file_service = double("MyRetriveSourceFileService")
|
34
|
+
subject.source_file_service = source_file_service
|
35
|
+
expect(subject.source_file_service).to eq(source_file_service)
|
36
|
+
end
|
37
|
+
|
24
38
|
it "should let you reset the configuration" do
|
25
39
|
subject.ffmpeg_path = '/usr/local/ffmpeg-1.0/bin/ffmpeg'
|
26
40
|
subject.reset_config!
|
@@ -8,11 +8,26 @@ describe Hydra::Derivatives do
|
|
8
8
|
end
|
9
9
|
class CustomProcessor < Hydra::Derivatives::Processor
|
10
10
|
end
|
11
|
+
class CustomSourceFileService
|
12
|
+
end
|
13
|
+
class CustomOutputFileService
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
17
|
after(:all) do
|
14
18
|
Object.send(:remove_const, :CustomFile)
|
15
19
|
Object.send(:remove_const, :CustomProcessor)
|
20
|
+
Object.send(:remove_const, :CustomSourceFileService)
|
21
|
+
Object.send(:remove_const, :CustomOutputFileService)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "initialize_processor" do
|
25
|
+
subject{ CustomFile.new.send(:initialize_processor, :content, { thumb: '100x100>' }, processor: Hydra::Derivatives::Video::Processor, source_file_service: CustomSourceFileService, output_file_service: CustomOutputFileService) }
|
26
|
+
it "passes source_file_service and output_file_service options to the processor" do
|
27
|
+
expect(subject.class).to eq(Hydra::Derivatives::Video::Processor)
|
28
|
+
expect(subject.source_file_service).to eq(CustomSourceFileService)
|
29
|
+
expect(subject.output_file_service).to eq(CustomOutputFileService)
|
30
|
+
end
|
16
31
|
end
|
17
32
|
|
18
33
|
context "when using an included processor" do
|
data/spec/units/image_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe Hydra::Derivatives::Image do
|
|
13
13
|
let(:file_name) { 'content_thumb' }
|
14
14
|
|
15
15
|
it "should use the string as the size and the name is autogenerated" do
|
16
|
-
expect(subject).to receive(:create_resized_image).with(
|
16
|
+
expect(subject).to receive(:create_resized_image).with(file_name, "100x100>", 'png')
|
17
17
|
subject.process
|
18
18
|
end
|
19
19
|
end
|
@@ -23,7 +23,7 @@ describe Hydra::Derivatives::Image do
|
|
23
23
|
let(:file_name) { 'thumbnail' }
|
24
24
|
|
25
25
|
it "should use the specified size and name" do
|
26
|
-
expect(subject).to receive(:create_resized_image).with(
|
26
|
+
expect(subject).to receive(:create_resized_image).with(file_name, "200x300>", 'png')
|
27
27
|
subject.process
|
28
28
|
end
|
29
29
|
end
|
@@ -33,7 +33,7 @@ describe Hydra::Derivatives::Image do
|
|
33
33
|
let(:file_name) { 'content_thumb' }
|
34
34
|
|
35
35
|
before do
|
36
|
-
allow(subject).to receive(:create_resized_image).with(
|
36
|
+
allow(subject).to receive(:create_resized_image).with("100x100>", 'png')
|
37
37
|
end
|
38
38
|
|
39
39
|
context 'when set' do
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::Derivatives::Processor do
|
4
|
+
|
5
|
+
let(:object) { "Fake Object" }
|
6
|
+
let(:source_name) { 'content' }
|
7
|
+
let(:directives) { { thumb: "100x100>" } }
|
8
|
+
|
9
|
+
subject { Hydra::Derivatives::Processor.new(object, source_name, directives)}
|
10
|
+
|
11
|
+
describe "source_file" do
|
12
|
+
it "relies on the source_file_service" do
|
13
|
+
expect(subject.source_file_service).to receive(:call).with(object, source_name)
|
14
|
+
subject.source_file
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "output_file_service" do
|
19
|
+
let(:custom_output_file_service) { "fake service" }
|
20
|
+
let(:another_custom_output_file_service) { "another fake service" }
|
21
|
+
|
22
|
+
context "as a global configuration setting" do
|
23
|
+
before do
|
24
|
+
allow(Hydra::Derivatives).to receive(:output_file_service).and_return(custom_output_file_service)
|
25
|
+
end
|
26
|
+
it "utilizes the default output file service" do
|
27
|
+
expect(subject.output_file_service).to eq(custom_output_file_service)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "as an instance level configuration setting" do
|
32
|
+
subject { Hydra::Derivatives::Processor.new(object, source_name, directives, output_file_service: another_custom_output_file_service)}
|
33
|
+
it "accepts a custom output file service as an option" do
|
34
|
+
expect(subject.output_file_service).to eq(another_custom_output_file_service)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "source_file_service" do
|
40
|
+
|
41
|
+
let(:custom_source_file_service) { "fake service" }
|
42
|
+
let(:another_custom_source_file_service) { "another fake service" }
|
43
|
+
|
44
|
+
context "as a global configuration setting" do
|
45
|
+
before do
|
46
|
+
allow(Hydra::Derivatives).to receive(:source_file_service).and_return(custom_source_file_service)
|
47
|
+
end
|
48
|
+
it "utilizes the default source file service" do
|
49
|
+
expect(subject.source_file_service).to eq(custom_source_file_service)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "as an instance level configuration setting" do
|
54
|
+
subject { Hydra::Derivatives::Processor.new(object, source_name, directives, source_file_service: another_custom_source_file_service)}
|
55
|
+
it "accepts a custom source file service as an option" do
|
56
|
+
expect(subject.source_file_service).to eq(another_custom_source_file_service)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -14,42 +14,47 @@ describe "Transcoder" do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
has_attributes :mime_type_from_fits, :flag_as, datastream: :characterization, multiple: false
|
17
|
-
contains '
|
17
|
+
contains 'original_file', class_name: 'ContentDatastream'
|
18
18
|
|
19
19
|
makes_derivatives do |obj|
|
20
20
|
case obj.mime_type_from_fits
|
21
21
|
when 'application/pdf'
|
22
|
-
obj.transform_file :
|
22
|
+
obj.transform_file :original_file, { thumb: '100x100>' }
|
23
23
|
when 'audio/wav'
|
24
|
-
obj.transform_file :
|
24
|
+
obj.transform_file :original_file, { mp3: { format: 'mp3' }, ogg: { format: 'ogg'} }, processor: :audio
|
25
25
|
when 'video/avi'
|
26
|
-
obj.transform_file :
|
26
|
+
obj.transform_file :original_file, { mp4: { format: 'mp4' }, webm: { format: 'webm'}, thumbnail: { format: 'jpg', datastream: 'thumbnail' } }, processor: :video
|
27
27
|
when 'image/png', 'image/jpg'
|
28
|
-
obj.transform_file :
|
28
|
+
obj.transform_file :original_file, { medium: "300x300>", thumb: "100x100>", access: { format: 'jpg', datastream: 'access'} }
|
29
29
|
when 'application/vnd.ms-powerpoint'
|
30
|
-
obj.transform_file :
|
30
|
+
obj.transform_file :original_file, { preservation: { format: 'pptx'}, access: { format: 'pdf' }, thumbnail: { format: 'jpg' } }, processor: 'document'
|
31
31
|
when 'text/rtf'
|
32
|
-
obj.transform_file :
|
32
|
+
obj.transform_file :original_file, { preservation: { format: 'odf' }, access: { format: 'pdf' }, thumbnail: { format: 'jpg' } }, processor: 'document'
|
33
33
|
when 'application/msword'
|
34
|
-
obj.transform_file :
|
34
|
+
obj.transform_file :original_file, { access: { format: 'pdf' }, preservation: { format: 'docx' }, thumbnail: { format: 'jpg' } }, processor: 'document'
|
35
35
|
when 'application/vnd.ms-excel'
|
36
|
-
obj.transform_file :
|
36
|
+
obj.transform_file :original_file, { access: { format: 'pdf' }, preservation: { format: 'xslx' }, thumbnail: { format: 'jpg' } }, processor: 'document'
|
37
37
|
when 'image/tiff'
|
38
|
-
obj.transform_file :
|
38
|
+
obj.transform_file :original_file, {
|
39
39
|
resized: { recipe: :default, resize: "600x600>", datastream: 'resized' },
|
40
40
|
config_lookup: { recipe: :default, datastream: 'config_lookup' },
|
41
41
|
string_recipe: { recipe: '-quiet', datastream: 'string_recipe' },
|
42
42
|
diy: { }
|
43
43
|
}, processor: 'jpeg2k_image'
|
44
|
-
|
45
|
-
|
44
|
+
when 'image/x-adobe-dng'
|
45
|
+
obj.transform_file :original_file,
|
46
|
+
{
|
47
|
+
access: { size: "300x300>", format: "jpg", datastream: "access" },
|
48
|
+
thumb: { size: "100x100>", format: "jpg", datastream: "thumb" }
|
49
|
+
}, processor: :raw_image
|
50
|
+
end
|
46
51
|
end
|
47
52
|
|
48
53
|
makes_derivatives :generate_special_derivatives
|
49
54
|
|
50
55
|
def generate_special_derivatives
|
51
56
|
if flag_as == "special" && mime_type_from_fits == 'image/png'
|
52
|
-
transform_file :
|
57
|
+
transform_file :original_file, { medium: { size: "200x300>", datastream: 'special_ds' } }
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
@@ -64,46 +69,68 @@ describe "Transcoder" do
|
|
64
69
|
let(:attachment) { File.open(File.expand_path('../../fixtures/world.png', __FILE__))}
|
65
70
|
let(:file) do
|
66
71
|
GenericFile.new(mime_type_from_fits: 'image/png').tap do |f|
|
67
|
-
f.
|
72
|
+
f.original_file.content = attachment
|
68
73
|
f.save!
|
69
74
|
end
|
70
75
|
end
|
71
76
|
|
72
77
|
it "should transcode" do
|
73
|
-
expect(file.attached_files.key?('
|
78
|
+
expect(file.attached_files.key?('original_file_medium')).to be_falsey
|
79
|
+
file.create_derivatives
|
80
|
+
expect(file.attached_files['original_file_medium']).to have_content
|
81
|
+
expect(file.attached_files['original_file_medium'].mime_type).to eq('image/png')
|
82
|
+
expect(file.attached_files['original_file_thumb']).to have_content
|
83
|
+
expect(file.attached_files['original_file_thumb'].mime_type).to eq('image/png')
|
84
|
+
expect(file.attached_files['access']).to have_content
|
85
|
+
expect(file.attached_files['access'].mime_type).to eq('image/jpeg')
|
86
|
+
expect(file.attached_files.key?('original_file_text')).to be_falsey
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "with an attached RAW image", unless: $in_travis do
|
91
|
+
let(:attachment) { File.open(File.expand_path('../../fixtures/test.dng', __FILE__))}
|
92
|
+
let(:file) do
|
93
|
+
GenericFile.new(mime_type_from_fits: 'image/x-adobe-dng') do |f|
|
94
|
+
f.original_file.content = attachment
|
95
|
+
f.original_file.mime_type = 'image/x-adobe-dng'
|
96
|
+
f.save!
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should transcode" do
|
101
|
+
expect(file.attached_files.key?('access')).to be_falsey
|
102
|
+
expect(file.attached_files.key?('thumb')).to be_falsey
|
103
|
+
|
74
104
|
file.create_derivatives
|
75
|
-
expect(file.attached_files['content_medium']).to have_content
|
76
|
-
expect(file.attached_files['content_medium'].mime_type).to eq('image/png')
|
77
|
-
expect(file.attached_files['content_thumb']).to have_content
|
78
|
-
expect(file.attached_files['content_thumb'].mime_type).to eq('image/png')
|
79
105
|
expect(file.attached_files['access']).to have_content
|
80
106
|
expect(file.attached_files['access'].mime_type).to eq('image/jpeg')
|
81
|
-
expect(file.attached_files
|
107
|
+
expect(file.attached_files['thumb']).to have_content
|
108
|
+
expect(file.attached_files['thumb'].mime_type).to eq('image/jpeg')
|
82
109
|
end
|
83
110
|
end
|
84
111
|
|
85
112
|
describe "with an attached pdf" do
|
86
113
|
let(:attachment) { File.open(File.expand_path('../../fixtures/test.pdf', __FILE__))}
|
87
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'application/pdf').tap { |t| t.
|
114
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'application/pdf').tap { |t| t.original_file.content = attachment; t.save } }
|
88
115
|
|
89
116
|
it "should transcode" do
|
90
|
-
expect(file.attached_files.key?('
|
117
|
+
expect(file.attached_files.key?('original_file_thumb')).to be_falsey
|
91
118
|
file.create_derivatives
|
92
|
-
expect(file.attached_files['
|
93
|
-
expect(file.attached_files['
|
119
|
+
expect(file.attached_files['original_file_thumb']).to have_content
|
120
|
+
expect(file.attached_files['original_file_thumb'].mime_type).to eq('image/png')
|
94
121
|
end
|
95
122
|
end
|
96
123
|
|
97
124
|
describe "with an attached audio", unless: ENV['TRAVIS'] == 'true' do
|
98
125
|
let(:attachment) { File.open(File.expand_path('../../fixtures/piano_note.wav', __FILE__))}
|
99
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'audio/wav').tap { |t| t.
|
126
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'audio/wav').tap { |t| t.original_file.content = attachment; t.save } }
|
100
127
|
|
101
128
|
it "should transcode" do
|
102
129
|
file.create_derivatives
|
103
|
-
expect(file.attached_files['
|
104
|
-
expect(file.attached_files['
|
105
|
-
expect(file.attached_files['
|
106
|
-
expect(file.attached_files['
|
130
|
+
expect(file.attached_files['original_file_mp3']).to have_content
|
131
|
+
expect(file.attached_files['original_file_mp3'].mime_type).to eq('audio/mpeg')
|
132
|
+
expect(file.attached_files['original_file_ogg']).to have_content
|
133
|
+
expect(file.attached_files['original_file_ogg'].mime_type).to eq('audio/ogg')
|
107
134
|
end
|
108
135
|
end
|
109
136
|
|
@@ -111,8 +138,8 @@ describe "Transcoder" do
|
|
111
138
|
let(:attachment) { File.open(File.expand_path('../../fixtures/piano_note.wav', __FILE__))}
|
112
139
|
let(:file) do
|
113
140
|
GenericFile.new(mime_type_from_fits: 'audio/wav').tap do |t|
|
114
|
-
t.
|
115
|
-
t.
|
141
|
+
t.original_file.content = attachment;
|
142
|
+
t.original_file.mime_type = 'audio/vnd.wav';
|
116
143
|
t.save
|
117
144
|
end
|
118
145
|
end
|
@@ -120,21 +147,21 @@ describe "Transcoder" do
|
|
120
147
|
it "should transcode" do
|
121
148
|
allow_any_instance_of(::Logger).to receive(:warn)
|
122
149
|
file.create_derivatives
|
123
|
-
expect(file.attached_files['
|
124
|
-
expect(file.attached_files['
|
150
|
+
expect(file.attached_files['original_file_mp3']).to have_content
|
151
|
+
expect(file.attached_files['original_file_mp3'].mime_type).to eq('audio/mpeg')
|
125
152
|
end
|
126
153
|
end
|
127
154
|
|
128
155
|
describe "with an attached video", unless: ENV['TRAVIS'] == 'true' do
|
129
156
|
let(:attachment) { File.open(File.expand_path('../../fixtures/countdown.avi', __FILE__))}
|
130
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'video/avi').tap { |t| t.
|
157
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'video/avi').tap { |t| t.original_file.content = attachment; t.save } }
|
131
158
|
|
132
159
|
it "should transcode" do
|
133
160
|
file.create_derivatives
|
134
|
-
expect(file.attached_files['
|
135
|
-
expect(file.attached_files['
|
136
|
-
expect(file.attached_files['
|
137
|
-
expect(file.attached_files['
|
161
|
+
expect(file.attached_files['original_file_mp4']).to have_content
|
162
|
+
expect(file.attached_files['original_file_mp4'].mime_type).to eq('video/mp4')
|
163
|
+
expect(file.attached_files['original_file_webm']).to have_content
|
164
|
+
expect(file.attached_files['original_file_webm'].mime_type).to eq('video/webm')
|
138
165
|
expect(file.attached_files['thumbnail']).to have_content
|
139
166
|
expect(file.attached_files['thumbnail'].mime_type).to eq('image/jpeg')
|
140
167
|
end
|
@@ -155,7 +182,7 @@ describe "Transcoder" do
|
|
155
182
|
|
156
183
|
describe "using callback methods" do
|
157
184
|
let(:attachment) { File.open(File.expand_path('../../fixtures/world.png', __FILE__))}
|
158
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'image/png', flag_as: "special").tap { |t| t.
|
185
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'image/png', flag_as: "special").tap { |t| t.original_file.content = attachment; t.save } }
|
159
186
|
|
160
187
|
it "should transcode" do
|
161
188
|
expect(file.attached_files.key?('special_ds')).to be_falsey
|
@@ -168,71 +195,71 @@ describe "Transcoder" do
|
|
168
195
|
|
169
196
|
describe "with an attached Powerpoint", unless: ENV['TRAVIS'] == 'true' do
|
170
197
|
let(:attachment) { File.open(File.expand_path('../../fixtures/FlashPix.ppt', __FILE__))}
|
171
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'application/vnd.ms-powerpoint').tap { |t| t.
|
198
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'application/vnd.ms-powerpoint').tap { |t| t.original_file.content = attachment; t.save } }
|
172
199
|
|
173
200
|
it "should transcode" do
|
174
201
|
file.create_derivatives
|
175
|
-
expect(file.attached_files['
|
176
|
-
expect(file.attached_files['
|
177
|
-
expect(file.attached_files['
|
178
|
-
expect(file.attached_files['
|
179
|
-
expect(file.attached_files['
|
180
|
-
expect(file.attached_files['
|
202
|
+
expect(file.attached_files['original_file_thumbnail']).to have_content
|
203
|
+
expect(file.attached_files['original_file_thumbnail'].mime_type).to eq('image/jpeg')
|
204
|
+
expect(file.attached_files['original_file_access']).to have_content
|
205
|
+
expect(file.attached_files['original_file_access'].mime_type).to eq('application/pdf')
|
206
|
+
expect(file.attached_files['original_file_preservation']).to have_content
|
207
|
+
expect(file.attached_files['original_file_preservation'].mime_type).to eq('application/vnd.openxmlformats-officedocument.presentationml.presentation')
|
181
208
|
end
|
182
209
|
end
|
183
210
|
|
184
211
|
describe "with an attached rich text format", unless: ENV['TRAVIS'] == 'true' do
|
185
212
|
let(:attachment) { File.open(File.expand_path('../../fixtures/sample.rtf', __FILE__))}
|
186
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'text/rtf').tap { |t| t.
|
213
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'text/rtf').tap { |t| t.original_file.content = attachment; t.save } }
|
187
214
|
|
188
215
|
it "should transcode" do
|
189
216
|
file.create_derivatives
|
190
|
-
expect(file.attached_files['
|
191
|
-
expect(file.attached_files['
|
192
|
-
expect(file.attached_files['
|
193
|
-
expect(file.attached_files['
|
194
|
-
expect(file.attached_files['
|
195
|
-
expect(file.attached_files['
|
217
|
+
expect(file.attached_files['original_file_thumbnail']).to have_content
|
218
|
+
expect(file.attached_files['original_file_thumbnail'].mime_type).to eq('image/jpeg')
|
219
|
+
expect(file.attached_files['original_file_access']).to have_content
|
220
|
+
expect(file.attached_files['original_file_access'].mime_type).to eq('application/pdf')
|
221
|
+
expect(file.attached_files['original_file_preservation']).to have_content
|
222
|
+
expect(file.attached_files['original_file_preservation'].mime_type).to eq('application/vnd.oasis.opendocument.text')
|
196
223
|
end
|
197
224
|
end
|
198
225
|
|
199
226
|
describe "with an attached word doc format", unless: ENV['TRAVIS'] == 'true' do
|
200
227
|
let(:attachment) { File.open(File.expand_path('../../fixtures/test.doc', __FILE__))}
|
201
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'application/msword').tap { |t| t.
|
228
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'application/msword').tap { |t| t.original_file.content = attachment; t.save } }
|
202
229
|
|
203
230
|
it "should transcode" do
|
204
231
|
file.create_derivatives
|
205
|
-
expect(file.attached_files['
|
206
|
-
expect(file.attached_files['
|
207
|
-
expect(file.attached_files['
|
208
|
-
expect(file.attached_files['
|
209
|
-
expect(file.attached_files['
|
210
|
-
expect(file.attached_files['
|
232
|
+
expect(file.attached_files['original_file_thumbnail']).to have_content
|
233
|
+
expect(file.attached_files['original_file_thumbnail'].mime_type).to eq('image/jpeg')
|
234
|
+
expect(file.attached_files['original_file_access']).to have_content
|
235
|
+
expect(file.attached_files['original_file_access'].mime_type).to eq('application/pdf')
|
236
|
+
expect(file.attached_files['original_file_preservation']).to have_content
|
237
|
+
expect(file.attached_files['original_file_preservation'].mime_type).to eq('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
|
211
238
|
end
|
212
239
|
end
|
213
240
|
|
214
241
|
describe "with an attached excel format", unless: ENV['TRAVIS'] == 'true' do
|
215
242
|
let(:attachment) { File.open(File.expand_path('../../fixtures/test.xls', __FILE__))}
|
216
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'application/vnd.ms-excel').tap { |t| t.
|
243
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'application/vnd.ms-excel').tap { |t| t.original_file.content = attachment; t.save } }
|
217
244
|
|
218
245
|
it "should transcode" do
|
219
246
|
file.create_derivatives
|
220
|
-
expect(file.attached_files['
|
221
|
-
expect(file.attached_files['
|
222
|
-
expect(file.attached_files['
|
223
|
-
expect(file.attached_files['
|
224
|
-
expect(file.attached_files['
|
225
|
-
expect(file.attached_files['
|
247
|
+
expect(file.attached_files['original_file_thumbnail']).to have_content
|
248
|
+
expect(file.attached_files['original_file_thumbnail'].mime_type).to eq('image/jpeg')
|
249
|
+
expect(file.attached_files['original_file_access']).to have_content
|
250
|
+
expect(file.attached_files['original_file_access'].mime_type).to eq('application/pdf')
|
251
|
+
expect(file.attached_files['original_file_preservation']).to have_content
|
252
|
+
expect(file.attached_files['original_file_preservation'].mime_type).to eq('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
226
253
|
end
|
227
254
|
end
|
228
255
|
|
229
256
|
describe "with an attached tiff", unless: ENV['TRAVIS'] == 'true' do
|
230
257
|
let(:attachment) { File.open(File.expand_path('../../fixtures/test.tif', __FILE__))}
|
231
|
-
let(:file) { GenericFile.new(mime_type_from_fits: 'image/tiff').tap { |t| t.
|
258
|
+
let(:file) { GenericFile.new(mime_type_from_fits: 'image/tiff').tap { |t| t.original_file.content = attachment; t.save } }
|
232
259
|
it "should transcode" do
|
233
260
|
file.create_derivatives
|
234
|
-
expect(file.attached_files['
|
235
|
-
expect(file.attached_files['
|
261
|
+
expect(file.attached_files['original_file_diy']).to have_content
|
262
|
+
expect(file.attached_files['original_file_diy'].mime_type).to eq('image/jp2')
|
236
263
|
expect(file.attached_files['config_lookup']).to have_content
|
237
264
|
expect(file.attached_files['config_lookup'].mime_type).to eq('image/jp2')
|
238
265
|
expect(file.attached_files['resized']).to have_content
|
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:
|
4
|
+
version: 2.0.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:
|
11
|
+
date: 2015-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -132,30 +132,30 @@ dependencies:
|
|
132
132
|
name: mime-types
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
|
-
- - "
|
135
|
+
- - "<"
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: '
|
137
|
+
version: '3'
|
138
138
|
type: :runtime
|
139
139
|
prerelease: false
|
140
140
|
version_requirements: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
|
-
- - "
|
142
|
+
- - "<"
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: '
|
144
|
+
version: '3'
|
145
145
|
- !ruby/object:Gem::Dependency
|
146
146
|
name: deprecation
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|
148
148
|
requirements:
|
149
|
-
- - "
|
149
|
+
- - ">="
|
150
150
|
- !ruby/object:Gem::Version
|
151
|
-
version: '0
|
151
|
+
version: '0'
|
152
152
|
type: :runtime
|
153
153
|
prerelease: false
|
154
154
|
version_requirements: !ruby/object:Gem::Requirement
|
155
155
|
requirements:
|
156
|
-
- - "
|
156
|
+
- - ">="
|
157
157
|
- !ruby/object:Gem::Version
|
158
|
-
version: '0
|
158
|
+
version: '0'
|
159
159
|
description: Derivative generation plugin for hydra
|
160
160
|
email:
|
161
161
|
- justin@curationexperts.com
|
@@ -185,12 +185,17 @@ files:
|
|
185
185
|
- lib/hydra/derivatives/extract_metadata.rb
|
186
186
|
- lib/hydra/derivatives/ffmpeg.rb
|
187
187
|
- lib/hydra/derivatives/image.rb
|
188
|
+
- lib/hydra/derivatives/io_decorator.rb
|
188
189
|
- lib/hydra/derivatives/jpeg2k_image.rb
|
189
190
|
- lib/hydra/derivatives/logger.rb
|
190
191
|
- lib/hydra/derivatives/processor.rb
|
191
192
|
- lib/hydra/derivatives/railtie.rb
|
193
|
+
- lib/hydra/derivatives/raw_image.rb
|
194
|
+
- lib/hydra/derivatives/services/persist_basic_contained_output_file_service.rb
|
195
|
+
- lib/hydra/derivatives/services/persist_output_file_service.rb
|
196
|
+
- lib/hydra/derivatives/services/retrieve_source_file_service.rb
|
197
|
+
- lib/hydra/derivatives/services/tempfile_service.rb
|
192
198
|
- lib/hydra/derivatives/shell_based_processor.rb
|
193
|
-
- lib/hydra/derivatives/tempfile_service.rb
|
194
199
|
- lib/hydra/derivatives/video.rb
|
195
200
|
- lib/hydra/derivatives/video/config.rb
|
196
201
|
- lib/hydra/derivatives/video/processor.rb
|
@@ -200,6 +205,7 @@ files:
|
|
200
205
|
- spec/fixtures/jpeg2k_config.yml
|
201
206
|
- spec/fixtures/piano_note.wav
|
202
207
|
- spec/fixtures/sample.rtf
|
208
|
+
- spec/fixtures/test.dng
|
203
209
|
- spec/fixtures/test.doc
|
204
210
|
- spec/fixtures/test.docx
|
205
211
|
- spec/fixtures/test.pdf
|
@@ -209,6 +215,8 @@ files:
|
|
209
215
|
- spec/fixtures/test.xlsx
|
210
216
|
- spec/fixtures/world.png
|
211
217
|
- spec/lib/hydra/derivatives/extract_metadata_spec.rb
|
218
|
+
- spec/services/persist_basic_contained_output_file_service_spec.rb
|
219
|
+
- spec/services/retrieve_source_file_service_spec.rb
|
212
220
|
- spec/services/tempfile_service_spec.rb
|
213
221
|
- spec/spec_helper.rb
|
214
222
|
- spec/units/config_spec.rb
|
@@ -217,6 +225,7 @@ files:
|
|
217
225
|
- spec/units/image_spec.rb
|
218
226
|
- spec/units/jpeg2k_spec.rb
|
219
227
|
- spec/units/logger_spec.rb
|
228
|
+
- spec/units/processor_spec.rb
|
220
229
|
- spec/units/shell_based_processor_spec.rb
|
221
230
|
- spec/units/transcoding_spec.rb
|
222
231
|
- spec/units/video_spec.rb
|
@@ -240,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
240
249
|
version: '0'
|
241
250
|
requirements: []
|
242
251
|
rubyforge_project:
|
243
|
-
rubygems_version: 2.5
|
252
|
+
rubygems_version: 2.4.5
|
244
253
|
signing_key:
|
245
254
|
specification_version: 4
|
246
255
|
summary: Derivative generation plugin for hydra
|
@@ -251,6 +260,7 @@ test_files:
|
|
251
260
|
- spec/fixtures/jpeg2k_config.yml
|
252
261
|
- spec/fixtures/piano_note.wav
|
253
262
|
- spec/fixtures/sample.rtf
|
263
|
+
- spec/fixtures/test.dng
|
254
264
|
- spec/fixtures/test.doc
|
255
265
|
- spec/fixtures/test.docx
|
256
266
|
- spec/fixtures/test.pdf
|
@@ -260,6 +270,8 @@ test_files:
|
|
260
270
|
- spec/fixtures/test.xlsx
|
261
271
|
- spec/fixtures/world.png
|
262
272
|
- spec/lib/hydra/derivatives/extract_metadata_spec.rb
|
273
|
+
- spec/services/persist_basic_contained_output_file_service_spec.rb
|
274
|
+
- spec/services/retrieve_source_file_service_spec.rb
|
263
275
|
- spec/services/tempfile_service_spec.rb
|
264
276
|
- spec/spec_helper.rb
|
265
277
|
- spec/units/config_spec.rb
|
@@ -268,7 +280,7 @@ test_files:
|
|
268
280
|
- spec/units/image_spec.rb
|
269
281
|
- spec/units/jpeg2k_spec.rb
|
270
282
|
- spec/units/logger_spec.rb
|
283
|
+
- spec/units/processor_spec.rb
|
271
284
|
- spec/units/shell_based_processor_spec.rb
|
272
285
|
- spec/units/transcoding_spec.rb
|
273
286
|
- spec/units/video_spec.rb
|
274
|
-
has_rdoc:
|