Skip to content

Commit

Permalink
Merge pull request #159 from projecthydra/encode_class
Browse files Browse the repository at this point in the history
Allow implementer to configure encode class
  • Loading branch information
cjcolvar committed Apr 27, 2017
2 parents 0b472b3 + d6292fc commit fdabd9a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 17 deletions.
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -92,10 +92,22 @@ Hydra::Derivatives::Processors::Video::Processor.config.jpeg.codec = '-vcodec mj
### Configuration for Audio/Video Processing with ActiveEncode

```ruby
# Set the transcoding engine
ActiveEncode::Base.engine_adapter = :elastic_transcoder

# Sleep time (in seconds) to poll for status of encoding job
Hydra::Derivatives.active_encode_poll_time = 10

# If you want to use a different class for the source file service
Hydra::Derivatives::ActiveEncodeDerivatives.source_file_service = MyCustomSourceFileService

# If you want to use a different class for the output file service
Hydra::Derivatives::ActiveEncodeDerivatives.output_file_service = MyCustomOutputFileService
```

Note: Please don't confuse these methods with the similar methods in the parent class:
`Hydra::Derivatives.source_file_service` and `Hydra::Derivatives.output_file_service`

For additional documentation on using ActiveEncode, see:
* [Using Amazon Elastic Transcoder](doc/amazon_elastic_transcoder.md)

Expand Down
15 changes: 8 additions & 7 deletions doc/amazon_elastic_transcoder.md
Expand Up @@ -30,15 +30,8 @@ In an initializer file such as `config/initializers/active_encode.rb`, make sure
```ruby
# Use Amazon's Elastic Transcoder
ActiveEncode::Base.engine_adapter = :elastic_transcoder

# If you want to use a different source file or output file service than the defaults
# Hydra::Derivatives::ActiveEncodeDerivatives.source_file_service = MyCustomSourceFileService
# Hydra::Derivatives::ActiveEncodeDerivatives.output_file_service = MyCustomOutputFileService
```

Note: Please don't confuse these methods with the similar methods in the parent class:
`Hydra::Derivatives.source_file_service` and `Hydra::Derivatives.output_file_service`

## How to create derivatives (Multiple derivatives per Elastic Transcoder job)

```ruby
Expand Down Expand Up @@ -107,3 +100,11 @@ video_record.source_file_name = 'sample_data.mp4'
Hydra::Derivatives::ActiveEncodeDerivatives.create(video_record, source: :source_file_name, outputs: [low_res_video])
```

## How to pass in a custom encode class

If you don't want to use the default encode class `::ActiveEncode::Base`, you can pass in `encode_class`:

```ruby
Hydra::Derivatives::ActiveEncodeDerivatives.create(video_record, encode_class: MyCustomEncode, source: :source_file_name, outputs: [low_res_video])
```

11 changes: 7 additions & 4 deletions lib/hydra/derivatives/processors/active_encode.rb
Expand Up @@ -11,12 +11,15 @@ def initialize(status, source_path, errors = [])

class ActiveEncode < Processor
class_attribute :timeout
attr_accessor :encode_class

def initialize(source_path, directives, opts = {})
super
@encode_class = opts.delete(:encode_class) || ::ActiveEncode::Base
end

# TODO: Instead of hard-coding ActiveEncode::Base,
# pass in or configure the class so that a user can
# override it with a sub-class of AE::Base.
def process
encode = ::ActiveEncode::Base.create(source_path, directives)
encode = encode_class.create(source_path, directives)
timeout ? wait_for_encode_with_timeout(encode) : wait_for_encode(encode)
encode.output.each do |output|
output_file_service.call(output, directives)
Expand Down
11 changes: 10 additions & 1 deletion lib/hydra/derivatives/runners/active_encode_derivatives.rb
Expand Up @@ -3,16 +3,25 @@ class ActiveEncodeDerivatives < Runner
# @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
# @param [Hash] options options to pass to the encoder
# @option options [Symbol] :source a method that can be called on the object to retrieve the source file's name
# @option options [Symbol] :encode_class class name of the encode object (usually a subclass of ::ActiveEncode::Base)
# @options options [Array] :outputs a list of desired outputs
def self.create(object_or_filename, options)
processor_opts = processor_options(options)
source_file(object_or_filename, options) do |file_name|
transform_directives(options.delete(:outputs)).each do |instructions|
processor = processor_class.new(file_name, instructions, output_file_service: output_file_service)
processor = processor_class.new(file_name, instructions, processor_opts)
processor.process
end
end
end

def self.processor_options(options)
opts = { output_file_service: output_file_service }
encode_class = options.delete(:encode_class)
opts = opts.merge(encode_class: encode_class) if encode_class
opts
end

# Use the source service configured for this class or default to the remote file service
def self.source_file_service
@source_file_service || RemoteSourceFile
Expand Down
25 changes: 24 additions & 1 deletion spec/processors/active_encode_spec.rb
Expand Up @@ -6,7 +6,8 @@
let(:file_path) { File.join(fixture_path, 'videoshort.mp4') }
let(:directives) { { url: '12345/derivative' } }
let(:output_file_service) { Hydra::Derivatives::PersistExternalFileOutputFileService }
let(:processor) { described_class.new(file_path, directives, output_file_service: output_file_service) }
let(:options) { { output_file_service: output_file_service } }
let(:processor) { described_class.new(file_path, directives, options) }

describe '#process' do
subject { processor.process }
Expand All @@ -31,6 +32,28 @@
enc
end

context 'with a custom encode class' do
before do
class TestEncode < ::ActiveEncode::Base; end

# For this spec we don't care what happens with output,
# so stub it out to speed up the spec.
allow(output_file_service).to receive(:call)
end

after { Object.send(:remove_const, :TestEncode) }

let(:completed_status) { true }
let(:state) { :completed }
let(:options) { { encode_class: TestEncode,
output_file_service: output_file_service } }

it 'uses the configured encode class' do
expect(TestEncode).to receive(:create).and_return(encode_double)
subject
end
end

context 'when the encoding failed' do
let(:state) { :failed }
let(:failed_status) { true }
Expand Down
25 changes: 21 additions & 4 deletions spec/runners/active_encode_derivatives_spec.rb
@@ -1,11 +1,15 @@
require 'spec_helper'

class TestVideo < ActiveFedora::Base
attr_accessor :remote_file_name
end

describe Hydra::Derivatives::ActiveEncodeDerivatives do
context '.create' do
before do
class TestVideo < ActiveFedora::Base
attr_accessor :remote_file_name
end
end

after { Object.send(:remove_const, :TestVideo) }

let(:file_path) { 'some/path/to/my_video.mp4' }
let(:video_record) { TestVideo.new(remote_file_name: file_path) }
let(:options) { { source: :remote_file_name, outputs: [low_res_video] } }
Expand All @@ -17,5 +21,18 @@ class TestVideo < ActiveFedora::Base
expect(processor).to receive(:process)
described_class.create(video_record, options)
end

context 'with a custom encode class' do
before { class TestEncode < ::ActiveEncode::Base; end }
after { Object.send(:remove_const, :TestEncode) }

let(:options) { { encode_class: TestEncode, source: :remote_file_name, outputs: [low_res_video] } }

it 'calls the processor with the right arguments' do
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)
expect(processor).to receive(:process)
described_class.create(video_record, options)
end
end
end
end

0 comments on commit fdabd9a

Please sign in to comment.