active_encode 0.4.1 → 0.8.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.
Files changed (93) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +80 -0
  3. data/.rubocop.yml +9 -70
  4. data/.rubocop_todo.yml +68 -0
  5. data/CODE_OF_CONDUCT.md +36 -0
  6. data/CONTRIBUTING.md +23 -21
  7. data/Gemfile +5 -4
  8. data/LICENSE +11 -199
  9. data/README.md +135 -24
  10. data/SUPPORT.md +5 -0
  11. data/active_encode.gemspec +13 -3
  12. data/app/controllers/active_encode/encode_record_controller.rb +13 -0
  13. data/app/jobs/active_encode/polling_job.rb +1 -1
  14. data/app/models/active_encode/encode_record.rb +1 -0
  15. data/config/routes.rb +4 -0
  16. data/db/migrate/20180822021048_create_active_encode_encode_records.rb +1 -0
  17. data/db/migrate/20190702153755_add_create_options_to_active_encode_encode_records.rb +6 -0
  18. data/db/migrate/20190712174821_add_progress_to_active_encode_encode_records.rb +6 -0
  19. data/lib/active_encode.rb +1 -0
  20. data/lib/active_encode/base.rb +2 -2
  21. data/lib/active_encode/callbacks.rb +1 -0
  22. data/lib/active_encode/core.rb +4 -3
  23. data/lib/active_encode/engine.rb +1 -0
  24. data/lib/active_encode/engine_adapter.rb +1 -0
  25. data/lib/active_encode/engine_adapters.rb +4 -1
  26. data/lib/active_encode/engine_adapters/elastic_transcoder_adapter.rb +116 -38
  27. data/lib/active_encode/engine_adapters/ffmpeg_adapter.rb +141 -87
  28. data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +5 -4
  29. data/lib/active_encode/engine_adapters/media_convert_adapter.rb +372 -0
  30. data/lib/active_encode/engine_adapters/media_convert_output.rb +104 -0
  31. data/lib/active_encode/engine_adapters/pass_through_adapter.rb +239 -0
  32. data/lib/active_encode/engine_adapters/test_adapter.rb +5 -4
  33. data/lib/active_encode/engine_adapters/zencoder_adapter.rb +3 -2
  34. data/lib/active_encode/errors.rb +6 -0
  35. data/lib/active_encode/global_id.rb +2 -1
  36. data/lib/active_encode/input.rb +3 -2
  37. data/lib/active_encode/output.rb +3 -2
  38. data/lib/active_encode/persistence.rb +11 -5
  39. data/lib/active_encode/polling.rb +3 -2
  40. data/lib/active_encode/spec/shared_specs.rb +2 -0
  41. data/{spec/shared_specs/engine_adapter_specs.rb → lib/active_encode/spec/shared_specs/engine_adapter.rb} +37 -38
  42. data/lib/active_encode/status.rb +1 -0
  43. data/lib/active_encode/technical_metadata.rb +3 -2
  44. data/lib/active_encode/version.rb +2 -1
  45. data/lib/file_locator.rb +93 -0
  46. data/spec/controllers/encode_record_controller_spec.rb +53 -0
  47. data/spec/fixtures/ffmpeg/cancelled-id/cancelled +0 -0
  48. data/spec/fixtures/file with space.low.mp4 +0 -0
  49. data/spec/fixtures/file with space.mp4 +0 -0
  50. data/spec/fixtures/fireworks.low.mp4 +0 -0
  51. data/spec/fixtures/media_convert/endpoints.json +1 -0
  52. data/spec/fixtures/media_convert/job_canceled.json +412 -0
  53. data/spec/fixtures/media_convert/job_canceling.json +1 -0
  54. data/spec/fixtures/media_convert/job_completed.json +359 -0
  55. data/spec/fixtures/media_convert/job_completed_detail.json +1 -0
  56. data/spec/fixtures/media_convert/job_completed_detail_query.json +1 -0
  57. data/spec/fixtures/media_convert/job_created.json +408 -0
  58. data/spec/fixtures/media_convert/job_failed.json +406 -0
  59. data/spec/fixtures/media_convert/job_progressing.json +414 -0
  60. data/spec/fixtures/pass_through/cancelled-id/cancelled +0 -0
  61. data/spec/fixtures/pass_through/cancelled-id/input_metadata +90 -0
  62. data/spec/fixtures/pass_through/completed-id/completed +0 -0
  63. data/spec/fixtures/pass_through/completed-id/input_metadata +102 -0
  64. data/spec/fixtures/pass_through/completed-id/output_metadata-high +90 -0
  65. data/spec/fixtures/pass_through/completed-id/output_metadata-low +90 -0
  66. data/spec/fixtures/pass_through/completed-id/video-high.mp4 +0 -0
  67. data/spec/fixtures/pass_through/completed-id/video-low.mp4 +0 -0
  68. data/spec/fixtures/pass_through/failed-id/error.log +1 -0
  69. data/spec/fixtures/pass_through/failed-id/input_metadata +90 -0
  70. data/spec/fixtures/pass_through/running-id/input_metadata +90 -0
  71. data/spec/integration/elastic_transcoder_adapter_spec.rb +63 -29
  72. data/spec/integration/ffmpeg_adapter_spec.rb +96 -24
  73. data/spec/integration/matterhorn_adapter_spec.rb +45 -44
  74. data/spec/integration/media_convert_adapter_spec.rb +126 -0
  75. data/spec/integration/pass_through_adapter_spec.rb +151 -0
  76. data/spec/integration/zencoder_adapter_spec.rb +210 -209
  77. data/spec/rails_helper.rb +1 -0
  78. data/spec/routing/encode_record_controller_routing_spec.rb +10 -0
  79. data/spec/spec_helper.rb +2 -2
  80. data/spec/test_app_templates/lib/generators/test_app_generator.rb +13 -12
  81. data/spec/units/callbacks_spec.rb +3 -2
  82. data/spec/units/core_spec.rb +26 -25
  83. data/spec/units/engine_adapter_spec.rb +1 -0
  84. data/spec/units/file_locator_spec.rb +129 -0
  85. data/spec/units/global_id_spec.rb +12 -11
  86. data/spec/units/input_spec.rb +8 -5
  87. data/spec/units/output_spec.rb +8 -5
  88. data/spec/units/persistence_spec.rb +15 -11
  89. data/spec/units/polling_job_spec.rb +7 -6
  90. data/spec/units/polling_spec.rb +1 -0
  91. data/spec/units/status_spec.rb +3 -3
  92. metadata +184 -18
  93. data/.travis.yml +0 -19
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_support'
2
3
 
3
4
  module ActiveEncode
@@ -9,8 +10,10 @@ module ActiveEncode
9
10
  persist(persistence_model_attributes(encode))
10
11
  end
11
12
 
12
- after_create do |encode|
13
- persist(persistence_model_attributes(encode))
13
+ around_create do |encode, block|
14
+ create_options = encode.options
15
+ encode = block.call
16
+ persist(persistence_model_attributes(encode, create_options))
14
17
  end
15
18
 
16
19
  after_cancel do |encode|
@@ -29,8 +32,8 @@ module ActiveEncode
29
32
  model.update(encode_attributes) # Don't fail if persisting doesn't succeed?
30
33
  end
31
34
 
32
- def persistence_model_attributes(encode)
33
- {
35
+ def persistence_model_attributes(encode, create_options = nil)
36
+ attributes = {
34
37
  global_id: encode.to_global_id.to_s,
35
38
  state: encode.state,
36
39
  adapter: encode.class.engine_adapter.class.name,
@@ -38,8 +41,11 @@ module ActiveEncode
38
41
  # Need to ensure that these values come through or else validations will fail
39
42
  created_at: encode.created_at,
40
43
  updated_at: encode.updated_at,
41
- raw_object: encode.to_json
44
+ raw_object: encode.to_json,
45
+ progress: encode.percent_complete
42
46
  }
47
+ attributes[:create_options] = create_options.to_json if create_options.present?
48
+ attributes
43
49
  end
44
50
  end
45
51
  end
@@ -1,4 +1,5 @@
1
- require 'active_support'
1
+ # frozen_string_literal: true
2
+ require 'active_support/core_ext/integer/time'
2
3
  require 'active_model/callbacks'
3
4
 
4
5
  module ActiveEncode
@@ -8,7 +9,7 @@ module ActiveEncode
8
9
  POLLING_WAIT_TIME = 10.seconds.freeze
9
10
 
10
11
  CALLBACKS = [
11
- :after_status_update, :after_failed, :after_cancelled, :after_completed
12
+ :after_status_update, :after_failed, :after_cancelled, :after_completed
12
13
  ].freeze
13
14
 
14
15
  included do
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require 'active_encode/spec/shared_specs/engine_adapter.rb'
@@ -21,13 +21,13 @@ RSpec.shared_examples 'an ActiveEncode::EngineAdapter' do |*_flags|
21
21
  it 'returns an ActiveEncode::Base object' do
22
22
  expect(subject.class).to be ActiveEncode::Base
23
23
  end
24
- its(:id) { is_expected.not_to be_empty }
24
+ it { expect(subject.id).to be_present }
25
25
  it { is_expected.to be_running }
26
- its(:current_operations) { is_expected.to be_empty }
27
- its(:percent_complete) { is_expected.to be < 100 }
28
- its(:errors) { is_expected.to be_empty }
29
- its(:created_at) { is_expected.to be_kind_of Time }
30
- its(:updated_at) { is_expected.to be_kind_of Time }
26
+ it { expect(subject.current_operations).to be_empty }
27
+ it { expect(subject.percent_complete).to be < 100 }
28
+ it { expect(subject.errors).to be_empty }
29
+ it { expect(subject.created_at).to be_kind_of Time }
30
+ it { expect(subject.updated_at).to be_kind_of Time }
31
31
 
32
32
  it 'input is a valid ActiveEncode::Input object' do
33
33
  expect(subject.input).to be_a ActiveEncode::Input
@@ -50,12 +50,12 @@ RSpec.shared_examples 'an ActiveEncode::EngineAdapter' do |*_flags|
50
50
  it 'returns an ActiveEncode::Base object' do
51
51
  expect(subject.class).to be ActiveEncode::Base
52
52
  end
53
- its(:id) { is_expected.to eq 'running-id' }
53
+ it { expect(subject.id).to be_present }
54
54
  it { is_expected.to be_running }
55
- its(:percent_complete) { is_expected.to be > 0 }
56
- its(:errors) { is_expected.to be_empty }
57
- its(:created_at) { is_expected.to be_kind_of Time }
58
- its(:updated_at) { is_expected.to be > subject.created_at }
55
+ it { expect(subject.percent_complete).to be_positive }
56
+ it { expect(subject.errors).to be_empty }
57
+ it { expect(subject.created_at).to be_kind_of Time }
58
+ it { expect(subject.updated_at).to be >= subject.created_at }
59
59
 
60
60
  it 'input is a valid ActiveEncode::Input object' do
61
61
  expect(subject.input).to be_a ActiveEncode::Input
@@ -77,12 +77,12 @@ RSpec.shared_examples 'an ActiveEncode::EngineAdapter' do |*_flags|
77
77
  it 'returns an ActiveEncode::Base object' do
78
78
  expect(subject.class).to be ActiveEncode::Base
79
79
  end
80
- its(:id) { is_expected.to eq 'cancelled-id' }
80
+ it { expect(subject.id).to be_present }
81
81
  it { is_expected.to be_cancelled }
82
- its(:percent_complete) { is_expected.to be > 0 }
83
- its(:errors) { is_expected.to be_empty }
84
- its(:created_at) { is_expected.to be_kind_of Time }
85
- its(:updated_at) { is_expected.to be >= subject.created_at }
82
+ it { expect(subject.percent_complete).to be_positive }
83
+ it { expect(subject.errors).to be_empty }
84
+ it { expect(subject.created_at).to be_kind_of Time }
85
+ it { expect(subject.updated_at).to be >= subject.created_at }
86
86
 
87
87
  it 'input is a valid ActiveEncode::Input object' do
88
88
  expect(subject.input).to be_a ActiveEncode::Input
@@ -104,12 +104,12 @@ RSpec.shared_examples 'an ActiveEncode::EngineAdapter' do |*_flags|
104
104
  it 'returns an ActiveEncode::Base object' do
105
105
  expect(subject.class).to be ActiveEncode::Base
106
106
  end
107
- its(:id) { is_expected.to eq 'completed-id' }
107
+ it { expect(subject.id).to be_present }
108
108
  it { is_expected.to be_completed }
109
- its(:percent_complete) { is_expected.to eq 100 }
110
- its(:errors) { is_expected.to be_empty }
111
- its(:created_at) { is_expected.to be_kind_of Time }
112
- its(:updated_at) { is_expected.to be > subject.created_at }
109
+ it { expect(subject.percent_complete).to eq 100 }
110
+ it { expect(subject.errors).to be_empty }
111
+ it { expect(subject.created_at).to be_kind_of Time }
112
+ it { expect(subject.updated_at).to be > subject.created_at }
113
113
 
114
114
  it 'input is a valid ActiveEncode::Input object' do
115
115
  expect(subject.input).to be_a ActiveEncode::Input
@@ -130,7 +130,7 @@ RSpec.shared_examples 'an ActiveEncode::EngineAdapter' do |*_flags|
130
130
 
131
131
  it 'output has technical metadata' do
132
132
  subject.output.each do |output|
133
- expected_output = completed_output.find {|expected_out| expected_out[:id] == output.id }
133
+ expected_output = completed_output.find { |expected_out| expected_out[:id] == output.id }
134
134
  expect(output.as_json.symbolize_keys).to include expected_output
135
135
  end
136
136
  end
@@ -142,12 +142,12 @@ RSpec.shared_examples 'an ActiveEncode::EngineAdapter' do |*_flags|
142
142
  it 'returns an ActiveEncode::Base object' do
143
143
  expect(subject.class).to be ActiveEncode::Base
144
144
  end
145
- its(:id) { is_expected.to eq 'failed-id' }
145
+ it { expect(subject.id).to be_present }
146
146
  it { is_expected.to be_failed }
147
- its(:percent_complete) { is_expected.to be > 0 }
148
- its(:errors) { is_expected.not_to be_empty }
149
- its(:created_at) { is_expected.to be_kind_of Time }
150
- its(:updated_at) { is_expected.to be > subject.created_at }
147
+ it { expect(subject.percent_complete).to be_positive }
148
+ it { expect(subject.errors).not_to be_empty }
149
+ it { expect(subject.created_at).to be_kind_of Time }
150
+ it { expect(subject.updated_at).to be > subject.created_at }
151
151
 
152
152
  it 'input is a valid ActiveEncode::Input object' do
153
153
  expect(subject.input).to be_a ActiveEncode::Input
@@ -174,12 +174,12 @@ RSpec.shared_examples 'an ActiveEncode::EngineAdapter' do |*_flags|
174
174
  it 'returns an ActiveEncode::Base object' do
175
175
  expect(subject.class).to be ActiveEncode::Base
176
176
  end
177
- its(:id) { is_expected.to eq cancelling_job.id }
177
+ it { expect(subject.id).to eq cancelling_job.id }
178
178
  it { is_expected.to be_cancelled }
179
- its(:percent_complete) { is_expected.to be > 0 }
180
- its(:errors) { is_expected.to be_empty }
181
- its(:created_at) { is_expected.to be_kind_of Time }
182
- its(:updated_at) { is_expected.to be >= subject.created_at }
179
+ it { expect(subject.percent_complete).to be_positive }
180
+ it { expect(subject.errors).to be_empty }
181
+ it { expect(subject.created_at).to be_kind_of Time }
182
+ it { expect(subject.updated_at).to be >= subject.created_at }
183
183
 
184
184
  it 'input is a valid ActiveEncode::Input object' do
185
185
  expect(subject.input).to be_a ActiveEncode::Input
@@ -201,12 +201,11 @@ RSpec.shared_examples 'an ActiveEncode::EngineAdapter' do |*_flags|
201
201
  it 'returns an ActiveEncode::Base object' do
202
202
  expect(subject.class).to be ActiveEncode::Base
203
203
  end
204
- its(:id) { is_expected.to eq 'running-id' }
205
- it { is_expected.to be_running }
206
- its(:percent_complete) { is_expected.to be > 0 }
207
- its(:errors) { is_expected.to be_empty }
208
- its(:created_at) { is_expected.to be_kind_of Time }
209
- its(:updated_at) { is_expected.to be > subject.created_at }
204
+ it { expect(subject.id).to be_present }
205
+ it { expect(subject.percent_complete).to be_positive }
206
+ it { expect(subject.errors).to be_empty }
207
+ it { expect(subject.created_at).to be_kind_of Time }
208
+ it { expect(subject.updated_at).to be >= subject.created_at }
210
209
 
211
210
  it 'input is a valid ActiveEncode::Input object' do
212
211
  expect(subject.input).to be_a ActiveEncode::Input
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_support'
2
3
 
3
4
  module ActiveEncode
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_support'
2
3
 
3
4
  module ActiveEncode
@@ -23,10 +24,10 @@ module ActiveEncode
23
24
  attr_accessor :video_bitrate
24
25
  end
25
26
 
26
- def assign_tech_metadata metadata
27
+ def assign_tech_metadata(metadata)
27
28
  [:width, :height, :frame_rate, :duration, :file_size, :checksum,
28
29
  :audio_codec, :video_codec, :audio_bitrate, :video_bitrate].each do |field|
29
- self.send("#{field}=", metadata[field]) if metadata.has_key?(field)
30
+ send("#{field}=", metadata[field]) if metadata.key?(field)
30
31
  end
31
32
  end
32
33
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveEncode
2
- VERSION = '0.4.1'.freeze
3
+ VERSION = '0.8.0'
3
4
  end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+ require 'addressable/uri'
3
+ require 'aws-sdk-s3'
4
+
5
+ class FileLocator
6
+ attr_reader :source
7
+
8
+ class S3File
9
+ attr_reader :bucket, :key
10
+
11
+ def initialize(uri)
12
+ uri = Addressable::URI.parse(uri)
13
+ @bucket = URI.decode(uri.host)
14
+ @key = URI.decode(uri.path).sub(%r{^/*(.+)/*$}, '\1')
15
+ end
16
+
17
+ def object
18
+ @object ||= Aws::S3::Object.new(bucket_name: bucket, key: key)
19
+ end
20
+ end
21
+
22
+ def initialize(source)
23
+ @source = source
24
+ end
25
+
26
+ def uri
27
+ if @uri.nil?
28
+ if source.is_a? File
29
+ @uri = Addressable::URI.parse("file://#{URI.encode(File.expand_path(source))}")
30
+ else
31
+ encoded_source = source
32
+ begin
33
+ @uri = Addressable::URI.parse(encoded_source)
34
+ rescue URI::InvalidURIError
35
+ if encoded_source == source
36
+ encoded_source = URI.encode(encoded_source)
37
+ retry
38
+ else
39
+ raise
40
+ end
41
+ end
42
+
43
+ @uri = Addressable::URI.parse("file://#{URI.encode(File.expand_path(source))}") if @uri.scheme.nil?
44
+ end
45
+ end
46
+ @uri
47
+ end
48
+
49
+ def location
50
+ case uri.scheme
51
+ when 's3'
52
+ S3File.new(uri).object.presigned_url(:get)
53
+ when 'file'
54
+ URI.decode(uri.path)
55
+ else
56
+ @uri.to_s
57
+ end
58
+ end
59
+
60
+ def exist?
61
+ case uri.scheme
62
+ when 's3'
63
+ S3File.new(uri).object.exists?
64
+ when 'file'
65
+ File.exist?(location)
66
+ else
67
+ false
68
+ end
69
+ end
70
+ alias exists? exist?
71
+
72
+ def reader
73
+ case uri.scheme
74
+ when 's3'
75
+ S3File.new(uri).object.get.body
76
+ when 'file'
77
+ File.open(location, 'r')
78
+ else
79
+ Kernel.open(uri.to_s, 'r')
80
+ end
81
+ end
82
+
83
+ def attachment
84
+ case uri.scheme
85
+ when 's3'
86
+ uri
87
+ when 'file'
88
+ File.open(location, 'r')
89
+ else
90
+ location
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ require 'rails_helper'
3
+
4
+ describe ActiveEncode::EncodeRecordController, type: :controller, db_clean: true do
5
+ routes { ActiveEncode::Engine.routes }
6
+
7
+ let(:encode_record) { ActiveEncode::EncodeRecord.create(id: 1, global_id: "app://ActiveEncode/Encode/1", state: "running", adapter: "ffmpeg", title: "Test", raw_object: raw_object, progress: 100) }
8
+ let(:raw_object) do
9
+ "{\"input\":{\"url\":\"file:///Users/cjcolvar/Documents/Code/samvera/active_encode/spec/fixtures/fireworks.mp4\",\"width\":960.0,\"height\":540.0,\"frame_rate\":29.671,\"duration\":6024,\"file_size\":1629578,\"audio_codec\":\"mp4a-40-2\",\"video_codec\":\"avc1\",\"audio_bitrate\":69737,\"video_bitrate\":2092780,\"created_at\":\"2018-12-17T16:54:50.401-05:00\",\"updated_at\":\"2018-12-17T16:54:50.401-05:00\",\"id\":\"8156\"},\"options\":{},\"id\":\"35efa965-ec51-409d-9495-2ae9669adbcc\",\"output\":[{\"url\":\"file:///Users/cjcolvar/Documents/Code/samvera/active_encode/.internal_test_app/encodes/35efa965-ec51-409d-9495-2ae9669adbcc/outputs/fireworks-low.mp4\",\"label\":\"low\",\"id\":\"8156-low\",\"created_at\":\"2018-12-17T16:54:50.401-05:00\",\"updated_at\":\"2018-12-17T16:54:59.169-05:00\",\"width\":640.0,\"height\":480.0,\"frame_rate\":29.671,\"duration\":6038,\"file_size\":905987,\"audio_codec\":\"mp4a-40-2\",\"video_codec\":\"avc1\",\"audio_bitrate\":72000,\"video_bitrate\":1126859},{\"url\":\"file:///Users/cjcolvar/Documents/Code/samvera/active_encode/.internal_test_app/encodes/35efa965-ec51-409d-9495-2ae9669adbcc/outputs/fireworks-high.mp4\",\"label\":\"high\",\"id\":\"8156-high\",\"created_at\":\"2018-12-17T16:54:50.401-05:00\",\"updated_at\":\"2018-12-17T16:54:59.169-05:00\",\"width\":1280.0,\"height\":720.0,\"frame_rate\":29.671,\"duration\":6038,\"file_size\":2102027,\"audio_codec\":\"mp4a-40-2\",\"video_codec\":\"avc1\",\"audio_bitrate\":72000,\"video_bitrate\":2721866}],\"state\":\"completed\",\"errors\":[],\"created_at\":\"2018-12-17T16:54:50.401-05:00\",\"updated_at\":\"2018-12-17T16:54:59.169-05:00\",\"current_operations\":[],\"percent_complete\":100,\"global_id\":{\"uri\":\"gid://ActiveEncode/Encode/35efa965-ec51-409d-9495-2ae9669adbcc\"}}"
10
+ end
11
+
12
+ before do
13
+ encode_record
14
+ end
15
+
16
+ describe 'GET show' do
17
+ before do
18
+ get :show, params: { id: record_id }
19
+ end
20
+
21
+ context 'when record exists' do
22
+ let(:record_id) { 1 }
23
+
24
+ it "responds with a 200 status code" do
25
+ expect(response.status).to eq 200
26
+ end
27
+
28
+ it "responds with JSON" do
29
+ expect(response.content_type).to include "application/json"
30
+ end
31
+
32
+ it "returns the encode record's raw json object" do
33
+ expect(response.body).to eq raw_object
34
+ end
35
+ end
36
+
37
+ context 'when record does not exist' do
38
+ let(:record_id) { "non-existant" }
39
+
40
+ it "responds with a 404 status code" do
41
+ expect(response.status).to eq 404
42
+ end
43
+
44
+ it "responds with JSON" do
45
+ expect(response.content_type).to include "application/json"
46
+ end
47
+
48
+ it "returns the encode record's raw json object" do
49
+ expect(response.body).to eq "{\"message\":\"Couldn't find ActiveEncode::EncodeRecord with 'id'=#{record_id}\"}"
50
+ end
51
+ end
52
+ end
53
+ end
File without changes
Binary file
Binary file
@@ -0,0 +1 @@
1
+ {"endpoints":[{"url":"https://stub.mediaconvert.us-east-1.amazonaws.com"}]}
@@ -0,0 +1,412 @@
1
+ {
2
+ "job": {
3
+ "acceleration_settings": {
4
+ "mode": "DISABLED"
5
+ },
6
+ "acceleration_status": "NOT_APPLICABLE",
7
+ "arn": "arn:aws:mediaconvert:us-east-1:123456789012:jobs/1625859001514-vvqfwj",
8
+ "created_at": "2021-07-09T14:30:01.000-05:00",
9
+ "id": "1625859001514-vvqfwj",
10
+ "messages": {
11
+ "info": [
12
+
13
+ ],
14
+ "warning": [
15
+
16
+ ]
17
+ },
18
+ "priority": 0,
19
+ "queue": "arn:aws:mediaconvert:us-east-1:123456789012:queues/Default",
20
+ "role": "arn:aws:iam::123456789012:role/service-role/MediaConvert_Default_Role",
21
+ "settings": {
22
+ "inputs": [
23
+ {
24
+ "audio_selectors": {
25
+ "Audio Selector 1": {
26
+ "default_selection": "DEFAULT"
27
+ }
28
+ },
29
+ "file_input": "s3://input-bucket/test_files/source_file.mp4",
30
+ "timecode_source": "ZEROBASED",
31
+ "video_selector": {
32
+ }
33
+ }
34
+ ],
35
+ "output_groups": [
36
+ {
37
+ "output_group_settings": {
38
+ "hls_group_settings": {
39
+ "destination": "s3://output-bucket/active-encode-test/output",
40
+ "min_segment_length": 0,
41
+ "segment_control": "SEGMENTED_FILES",
42
+ "segment_length": 10
43
+ },
44
+ "type": "HLS_GROUP_SETTINGS"
45
+ },
46
+ "outputs": [
47
+ {
48
+ "audio_descriptions": [
49
+ {
50
+ "audio_type": 0,
51
+ "audio_type_control": "FOLLOW_INPUT",
52
+ "codec_settings": {
53
+ "aac_settings": {
54
+ "audio_description_broadcaster_mix": "NORMAL",
55
+ "bitrate": 128000,
56
+ "codec_profile": "LC",
57
+ "coding_mode": "CODING_MODE_2_0",
58
+ "rate_control_mode": "CBR",
59
+ "raw_format": "NONE",
60
+ "sample_rate": 48000,
61
+ "specification": "MPEG4"
62
+ },
63
+ "codec": "AAC"
64
+ },
65
+ "language_code_control": "FOLLOW_INPUT"
66
+ }
67
+ ],
68
+ "container_settings": {
69
+ "container": "M3U8",
70
+ "m3u_8_settings": {
71
+ "audio_frames_per_pes": 4,
72
+ "audio_pids": [
73
+ 482,
74
+ 483,
75
+ 484,
76
+ 485,
77
+ 486,
78
+ 487,
79
+ 488,
80
+ 489,
81
+ 490,
82
+ 491,
83
+ 492,
84
+ 493,
85
+ 494,
86
+ 495,
87
+ 496,
88
+ 497,
89
+ 498
90
+ ],
91
+ "pat_interval": 0,
92
+ "pcr_control": "PCR_EVERY_PES_PACKET",
93
+ "pmt_interval": 0,
94
+ "pmt_pid": 480,
95
+ "private_metadata_pid": 503,
96
+ "program_number": 1,
97
+ "scte_35_pid": 500,
98
+ "timed_metadata_pid": 502,
99
+ "video_pid": 481
100
+ }
101
+ },
102
+ "name_modifier": "-1080",
103
+ "preset": "System-Avc_16x9_1080p_29_97fps_8500kbps",
104
+ "video_description": {
105
+ "afd_signaling": "NONE",
106
+ "anti_alias": "ENABLED",
107
+ "codec_settings": {
108
+ "codec": "H_264",
109
+ "h264_settings": {
110
+ "adaptive_quantization": "HIGH",
111
+ "bitrate": 8500000,
112
+ "codec_level": "LEVEL_4",
113
+ "codec_profile": "HIGH",
114
+ "entropy_encoding": "CABAC",
115
+ "field_encoding": "PAFF",
116
+ "flicker_adaptive_quantization": "DISABLED",
117
+ "framerate_control": "SPECIFIED",
118
+ "framerate_conversion_algorithm": "DUPLICATE_DROP",
119
+ "framerate_denominator": 1001,
120
+ "framerate_numerator": 30000,
121
+ "gop_b_reference": "DISABLED",
122
+ "gop_closed_cadence": 1,
123
+ "gop_size": 90.0,
124
+ "gop_size_units": "FRAMES",
125
+ "hrd_buffer_initial_fill_percentage": 90,
126
+ "hrd_buffer_size": 12750000,
127
+ "interlace_mode": "PROGRESSIVE",
128
+ "min_i_interval": 0,
129
+ "number_b_frames_between_reference_frames": 1,
130
+ "number_reference_frames": 3,
131
+ "par_control": "SPECIFIED",
132
+ "par_denominator": 1,
133
+ "par_numerator": 1,
134
+ "quality_tuning_level": "MULTI_PASS_HQ",
135
+ "rate_control_mode": "CBR",
136
+ "repeat_pps": "DISABLED",
137
+ "scene_change_detect": "ENABLED",
138
+ "slices": 1,
139
+ "slow_pal": "DISABLED",
140
+ "spatial_adaptive_quantization": "ENABLED",
141
+ "syntax": "DEFAULT",
142
+ "telecine": "NONE",
143
+ "temporal_adaptive_quantization": "ENABLED",
144
+ "unregistered_sei_timecode": "DISABLED"
145
+ }
146
+ },
147
+ "color_metadata": "INSERT",
148
+ "drop_frame_timecode": "ENABLED",
149
+ "height": 1080,
150
+ "respond_to_afd": "NONE",
151
+ "scaling_behavior": "DEFAULT",
152
+ "sharpness": 50,
153
+ "timecode_insertion": "DISABLED",
154
+ "video_preprocessors": {
155
+ "deinterlacer": {
156
+ "algorithm": "INTERPOLATE",
157
+ "control": "NORMAL",
158
+ "mode": "DEINTERLACE"
159
+ }
160
+ },
161
+ "width": 1920
162
+ }
163
+ },
164
+ {
165
+ "audio_descriptions": [
166
+ {
167
+ "audio_type": 0,
168
+ "audio_type_control": "FOLLOW_INPUT",
169
+ "codec_settings": {
170
+ "aac_settings": {
171
+ "audio_description_broadcaster_mix": "NORMAL",
172
+ "bitrate": 96000,
173
+ "codec_profile": "HEV1",
174
+ "coding_mode": "CODING_MODE_2_0",
175
+ "rate_control_mode": "CBR",
176
+ "raw_format": "NONE",
177
+ "sample_rate": 48000,
178
+ "specification": "MPEG4"
179
+ },
180
+ "codec": "AAC"
181
+ },
182
+ "language_code_control": "FOLLOW_INPUT"
183
+ }
184
+ ],
185
+ "container_settings": {
186
+ "container": "M3U8",
187
+ "m3u_8_settings": {
188
+ "audio_frames_per_pes": 4,
189
+ "audio_pids": [
190
+ 482,
191
+ 483,
192
+ 484,
193
+ 485,
194
+ 486,
195
+ 487,
196
+ 488,
197
+ 489,
198
+ 490,
199
+ 491,
200
+ 492,
201
+ 493,
202
+ 494,
203
+ 495,
204
+ 496,
205
+ 497,
206
+ 498
207
+ ],
208
+ "pat_interval": 0,
209
+ "pcr_control": "PCR_EVERY_PES_PACKET",
210
+ "pmt_interval": 0,
211
+ "pmt_pid": 480,
212
+ "private_metadata_pid": 503,
213
+ "program_number": 1,
214
+ "scte_35_pid": 500,
215
+ "timed_metadata_pid": 502,
216
+ "video_pid": 481
217
+ }
218
+ },
219
+ "name_modifier": "-720",
220
+ "preset": "System-Avc_16x9_720p_29_97fps_5000kbps",
221
+ "video_description": {
222
+ "afd_signaling": "NONE",
223
+ "anti_alias": "ENABLED",
224
+ "codec_settings": {
225
+ "codec": "H_264",
226
+ "h264_settings": {
227
+ "adaptive_quantization": "HIGH",
228
+ "bitrate": 5000000,
229
+ "codec_level": "LEVEL_3_1",
230
+ "codec_profile": "MAIN",
231
+ "entropy_encoding": "CABAC",
232
+ "field_encoding": "PAFF",
233
+ "flicker_adaptive_quantization": "DISABLED",
234
+ "framerate_control": "SPECIFIED",
235
+ "framerate_conversion_algorithm": "DUPLICATE_DROP",
236
+ "framerate_denominator": 1001,
237
+ "framerate_numerator": 30000,
238
+ "gop_b_reference": "DISABLED",
239
+ "gop_closed_cadence": 1,
240
+ "gop_size": 90.0,
241
+ "gop_size_units": "FRAMES",
242
+ "hrd_buffer_initial_fill_percentage": 90,
243
+ "hrd_buffer_size": 7500000,
244
+ "interlace_mode": "PROGRESSIVE",
245
+ "min_i_interval": 0,
246
+ "number_b_frames_between_reference_frames": 1,
247
+ "number_reference_frames": 3,
248
+ "par_control": "SPECIFIED",
249
+ "par_denominator": 1,
250
+ "par_numerator": 1,
251
+ "quality_tuning_level": "MULTI_PASS_HQ",
252
+ "rate_control_mode": "CBR",
253
+ "repeat_pps": "DISABLED",
254
+ "scene_change_detect": "ENABLED",
255
+ "slices": 1,
256
+ "slow_pal": "DISABLED",
257
+ "spatial_adaptive_quantization": "ENABLED",
258
+ "syntax": "DEFAULT",
259
+ "telecine": "NONE",
260
+ "temporal_adaptive_quantization": "ENABLED",
261
+ "unregistered_sei_timecode": "DISABLED"
262
+ }
263
+ },
264
+ "color_metadata": "INSERT",
265
+ "drop_frame_timecode": "ENABLED",
266
+ "height": 720,
267
+ "respond_to_afd": "NONE",
268
+ "scaling_behavior": "DEFAULT",
269
+ "sharpness": 50,
270
+ "timecode_insertion": "DISABLED",
271
+ "video_preprocessors": {
272
+ "deinterlacer": {
273
+ "algorithm": "INTERPOLATE",
274
+ "control": "NORMAL",
275
+ "mode": "DEINTERLACE"
276
+ }
277
+ },
278
+ "width": 1280
279
+ }
280
+ },
281
+ {
282
+ "audio_descriptions": [
283
+ {
284
+ "audio_type": 0,
285
+ "audio_type_control": "FOLLOW_INPUT",
286
+ "codec_settings": {
287
+ "aac_settings": {
288
+ "audio_description_broadcaster_mix": "NORMAL",
289
+ "bitrate": 96000,
290
+ "codec_profile": "HEV1",
291
+ "coding_mode": "CODING_MODE_2_0",
292
+ "rate_control_mode": "CBR",
293
+ "raw_format": "NONE",
294
+ "sample_rate": 48000,
295
+ "specification": "MPEG4"
296
+ },
297
+ "codec": "AAC"
298
+ },
299
+ "language_code_control": "FOLLOW_INPUT"
300
+ }
301
+ ],
302
+ "container_settings": {
303
+ "container": "M3U8",
304
+ "m3u_8_settings": {
305
+ "audio_frames_per_pes": 4,
306
+ "audio_pids": [
307
+ 482,
308
+ 483,
309
+ 484,
310
+ 485,
311
+ 486,
312
+ 487,
313
+ 488,
314
+ 489,
315
+ 490,
316
+ 491,
317
+ 492,
318
+ 493,
319
+ 494,
320
+ 495,
321
+ 496,
322
+ 497,
323
+ 498
324
+ ],
325
+ "pat_interval": 0,
326
+ "pcr_control": "PCR_EVERY_PES_PACKET",
327
+ "pmt_interval": 0,
328
+ "pmt_pid": 480,
329
+ "private_metadata_pid": 503,
330
+ "program_number": 1,
331
+ "scte_35_pid": 500,
332
+ "timed_metadata_pid": 502,
333
+ "video_pid": 481
334
+ }
335
+ },
336
+ "name_modifier": "-540",
337
+ "preset": "System-Avc_16x9_540p_29_97fps_3500kbps",
338
+ "video_description": {
339
+ "afd_signaling": "NONE",
340
+ "anti_alias": "ENABLED",
341
+ "codec_settings": {
342
+ "codec": "H_264",
343
+ "h264_settings": {
344
+ "adaptive_quantization": "HIGH",
345
+ "bitrate": 3500000,
346
+ "codec_level": "LEVEL_3_1",
347
+ "codec_profile": "MAIN",
348
+ "entropy_encoding": "CABAC",
349
+ "field_encoding": "PAFF",
350
+ "flicker_adaptive_quantization": "DISABLED",
351
+ "framerate_control": "SPECIFIED",
352
+ "framerate_conversion_algorithm": "DUPLICATE_DROP",
353
+ "framerate_denominator": 1001,
354
+ "framerate_numerator": 30000,
355
+ "gop_b_reference": "DISABLED",
356
+ "gop_closed_cadence": 1,
357
+ "gop_size": 90.0,
358
+ "gop_size_units": "FRAMES",
359
+ "hrd_buffer_initial_fill_percentage": 90,
360
+ "hrd_buffer_size": 5250000,
361
+ "interlace_mode": "PROGRESSIVE",
362
+ "min_i_interval": 0,
363
+ "number_b_frames_between_reference_frames": 3,
364
+ "number_reference_frames": 3,
365
+ "par_control": "SPECIFIED",
366
+ "par_denominator": 1,
367
+ "par_numerator": 1,
368
+ "quality_tuning_level": "MULTI_PASS_HQ",
369
+ "rate_control_mode": "CBR",
370
+ "repeat_pps": "DISABLED",
371
+ "scene_change_detect": "ENABLED",
372
+ "slices": 1,
373
+ "slow_pal": "DISABLED",
374
+ "spatial_adaptive_quantization": "ENABLED",
375
+ "syntax": "DEFAULT",
376
+ "telecine": "NONE",
377
+ "temporal_adaptive_quantization": "ENABLED",
378
+ "unregistered_sei_timecode": "DISABLED"
379
+ }
380
+ },
381
+ "color_metadata": "INSERT",
382
+ "drop_frame_timecode": "ENABLED",
383
+ "height": 540,
384
+ "respond_to_afd": "NONE",
385
+ "scaling_behavior": "DEFAULT",
386
+ "sharpness": 50,
387
+ "timecode_insertion": "DISABLED",
388
+ "video_preprocessors": {
389
+ "deinterlacer": {
390
+ "algorithm": "INTERPOLATE",
391
+ "control": "NORMAL",
392
+ "mode": "DEINTERLACE"
393
+ }
394
+ },
395
+ "width": 960
396
+ }
397
+ }
398
+ ]
399
+ }
400
+ ]
401
+ },
402
+ "status": "CANCELED",
403
+ "status_update_interval": "SECONDS_60",
404
+ "timing": {
405
+ "finish_time": "2021-07-09T14:30:22.000-05:00",
406
+ "start_time": "2021-07-09T14:30:04.000-05:00",
407
+ "submit_time": "2021-07-09T14:30:01.000-05:00"
408
+ },
409
+ "user_metadata": {
410
+ }
411
+ }
412
+ }