active_encode 0.4.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +80 -0
- data/.rubocop.yml +9 -70
- data/.rubocop_todo.yml +68 -0
- data/CODE_OF_CONDUCT.md +36 -0
- data/CONTRIBUTING.md +23 -21
- data/Gemfile +5 -4
- data/LICENSE +11 -199
- data/README.md +135 -24
- data/SUPPORT.md +5 -0
- data/active_encode.gemspec +13 -3
- data/app/controllers/active_encode/encode_record_controller.rb +13 -0
- data/app/jobs/active_encode/polling_job.rb +1 -1
- data/app/models/active_encode/encode_record.rb +1 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20180822021048_create_active_encode_encode_records.rb +1 -0
- data/db/migrate/20190702153755_add_create_options_to_active_encode_encode_records.rb +6 -0
- data/db/migrate/20190712174821_add_progress_to_active_encode_encode_records.rb +6 -0
- data/lib/active_encode.rb +1 -0
- data/lib/active_encode/base.rb +2 -2
- data/lib/active_encode/callbacks.rb +1 -0
- data/lib/active_encode/core.rb +4 -3
- data/lib/active_encode/engine.rb +1 -0
- data/lib/active_encode/engine_adapter.rb +1 -0
- data/lib/active_encode/engine_adapters.rb +4 -1
- data/lib/active_encode/engine_adapters/elastic_transcoder_adapter.rb +116 -38
- data/lib/active_encode/engine_adapters/ffmpeg_adapter.rb +141 -87
- data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +5 -4
- data/lib/active_encode/engine_adapters/media_convert_adapter.rb +372 -0
- data/lib/active_encode/engine_adapters/media_convert_output.rb +104 -0
- data/lib/active_encode/engine_adapters/pass_through_adapter.rb +239 -0
- data/lib/active_encode/engine_adapters/test_adapter.rb +5 -4
- data/lib/active_encode/engine_adapters/zencoder_adapter.rb +3 -2
- data/lib/active_encode/errors.rb +6 -0
- data/lib/active_encode/global_id.rb +2 -1
- data/lib/active_encode/input.rb +3 -2
- data/lib/active_encode/output.rb +3 -2
- data/lib/active_encode/persistence.rb +11 -5
- data/lib/active_encode/polling.rb +3 -2
- data/lib/active_encode/spec/shared_specs.rb +2 -0
- data/{spec/shared_specs/engine_adapter_specs.rb → lib/active_encode/spec/shared_specs/engine_adapter.rb} +37 -38
- data/lib/active_encode/status.rb +1 -0
- data/lib/active_encode/technical_metadata.rb +3 -2
- data/lib/active_encode/version.rb +2 -1
- data/lib/file_locator.rb +93 -0
- data/spec/controllers/encode_record_controller_spec.rb +53 -0
- data/spec/fixtures/ffmpeg/cancelled-id/cancelled +0 -0
- data/spec/fixtures/file with space.low.mp4 +0 -0
- data/spec/fixtures/file with space.mp4 +0 -0
- data/spec/fixtures/fireworks.low.mp4 +0 -0
- data/spec/fixtures/media_convert/endpoints.json +1 -0
- data/spec/fixtures/media_convert/job_canceled.json +412 -0
- data/spec/fixtures/media_convert/job_canceling.json +1 -0
- data/spec/fixtures/media_convert/job_completed.json +359 -0
- data/spec/fixtures/media_convert/job_completed_detail.json +1 -0
- data/spec/fixtures/media_convert/job_completed_detail_query.json +1 -0
- data/spec/fixtures/media_convert/job_created.json +408 -0
- data/spec/fixtures/media_convert/job_failed.json +406 -0
- data/spec/fixtures/media_convert/job_progressing.json +414 -0
- data/spec/fixtures/pass_through/cancelled-id/cancelled +0 -0
- data/spec/fixtures/pass_through/cancelled-id/input_metadata +90 -0
- data/spec/fixtures/pass_through/completed-id/completed +0 -0
- data/spec/fixtures/pass_through/completed-id/input_metadata +102 -0
- data/spec/fixtures/pass_through/completed-id/output_metadata-high +90 -0
- data/spec/fixtures/pass_through/completed-id/output_metadata-low +90 -0
- data/spec/fixtures/pass_through/completed-id/video-high.mp4 +0 -0
- data/spec/fixtures/pass_through/completed-id/video-low.mp4 +0 -0
- data/spec/fixtures/pass_through/failed-id/error.log +1 -0
- data/spec/fixtures/pass_through/failed-id/input_metadata +90 -0
- data/spec/fixtures/pass_through/running-id/input_metadata +90 -0
- data/spec/integration/elastic_transcoder_adapter_spec.rb +63 -29
- data/spec/integration/ffmpeg_adapter_spec.rb +96 -24
- data/spec/integration/matterhorn_adapter_spec.rb +45 -44
- data/spec/integration/media_convert_adapter_spec.rb +126 -0
- data/spec/integration/pass_through_adapter_spec.rb +151 -0
- data/spec/integration/zencoder_adapter_spec.rb +210 -209
- data/spec/rails_helper.rb +1 -0
- data/spec/routing/encode_record_controller_routing_spec.rb +10 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +13 -12
- data/spec/units/callbacks_spec.rb +3 -2
- data/spec/units/core_spec.rb +26 -25
- data/spec/units/engine_adapter_spec.rb +1 -0
- data/spec/units/file_locator_spec.rb +129 -0
- data/spec/units/global_id_spec.rb +12 -11
- data/spec/units/input_spec.rb +8 -5
- data/spec/units/output_spec.rb +8 -5
- data/spec/units/persistence_spec.rb +15 -11
- data/spec/units/polling_job_spec.rb +7 -6
- data/spec/units/polling_spec.rb +1 -0
- data/spec/units/status_spec.rb +3 -3
- metadata +184 -18
- data/.travis.yml +0 -19
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ActiveEncode
|
3
|
+
module EngineAdapters
|
4
|
+
module MediaConvertOutput
|
5
|
+
class << self
|
6
|
+
AUDIO_SETTINGS = {
|
7
|
+
"AAC" => :aac_settings,
|
8
|
+
"AC3" => :ac3_settings,
|
9
|
+
"AIFF" => :aiff_settings,
|
10
|
+
"EAC3_ATMOS" => :eac_3_atmos_settings,
|
11
|
+
"EAC3" => :eac_3_settings,
|
12
|
+
"MP2" => :mp_2_settings,
|
13
|
+
"MP3" => :mp_3_settings,
|
14
|
+
"OPUS" => :opus_settings,
|
15
|
+
"VORBIS" => :vorbis_settings,
|
16
|
+
"WAV" => :wav_settings
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
VIDEO_SETTINGS = {
|
20
|
+
"AV1" => :av_1_settings,
|
21
|
+
"AVC_INTRA" => :avc_intra_settings,
|
22
|
+
"FRAME_CAPTURE" => :frame_capture_settings,
|
23
|
+
"H_264" => :h264_settings,
|
24
|
+
"H_265" => :h265_settings,
|
25
|
+
"MPEG2" => :mpeg_2_settings,
|
26
|
+
"PRORES" => :prores_settings,
|
27
|
+
"VC3" => :vc_3_settings,
|
28
|
+
"VP8" => :vp_8_settings,
|
29
|
+
"VP9" => :vp_9_settings,
|
30
|
+
"XAVC" => :xavc_settings
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
def tech_metadata(settings, output)
|
34
|
+
url = output.dig('outputFilePaths', 0)
|
35
|
+
{
|
36
|
+
width: output.dig('videoDetails', 'widthInPx'),
|
37
|
+
height: output.dig('videoDetails', 'heightInPx'),
|
38
|
+
frame_rate: extract_video_frame_rate(settings),
|
39
|
+
duration: output['durationInMs'],
|
40
|
+
audio_codec: extract_audio_codec(settings),
|
41
|
+
video_codec: extract_video_codec(settings),
|
42
|
+
audio_bitrate: extract_audio_bitrate(settings),
|
43
|
+
video_bitrate: extract_video_bitrate(settings),
|
44
|
+
url: url,
|
45
|
+
label: File.basename(url),
|
46
|
+
suffix: settings.name_modifier
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def extract_audio_codec(settings)
|
51
|
+
settings.audio_descriptions.first.codec_settings.codec
|
52
|
+
rescue
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def extract_audio_codec_settings(settings)
|
57
|
+
codec_key = AUDIO_SETTINGS[extract_audio_codec(settings)]
|
58
|
+
settings.audio_descriptions.first.codec_settings[codec_key]
|
59
|
+
end
|
60
|
+
|
61
|
+
def extract_video_codec(settings)
|
62
|
+
settings.video_description.codec_settings.codec
|
63
|
+
rescue
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def extract_video_codec_settings(settings)
|
68
|
+
codec_key = VIDEO_SETTINGS[extract_video_codec(settings)]
|
69
|
+
settings.video_description.codec_settings[codec_key]
|
70
|
+
rescue
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def extract_audio_bitrate(settings)
|
75
|
+
codec_settings = extract_audio_codec_settings(settings)
|
76
|
+
return nil if codec_settings.nil?
|
77
|
+
try(codec_settings, :bitrate)
|
78
|
+
end
|
79
|
+
|
80
|
+
def extract_video_bitrate(settings)
|
81
|
+
codec_settings = extract_video_codec_settings(settings)
|
82
|
+
return nil if codec_settings.nil?
|
83
|
+
try(codec_settings, :bitrate) || try(codec_settings, :max_bitrate)
|
84
|
+
end
|
85
|
+
|
86
|
+
def extract_video_frame_rate(settings)
|
87
|
+
codec_settings = extract_video_codec_settings(settings)
|
88
|
+
return nil if codec_settings.nil?
|
89
|
+
(codec_settings.framerate_numerator.to_f / codec_settings.framerate_denominator.to_f).round(2)
|
90
|
+
rescue
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def try(struct, key)
|
97
|
+
struct[key]
|
98
|
+
rescue
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'fileutils'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'shellwords'
|
5
|
+
require 'file_locator'
|
6
|
+
|
7
|
+
# PassThroughAdapter accepts an input file url and a number of derivative urls in the options
|
8
|
+
# E.g. `create(input, outputs: [{ label: 'low', url: 'file:///derivatives/low.mp4' }, { label: 'high', url: 'file:///derivatives/high.mp4' }])`
|
9
|
+
# This adapter mirrors the ffmpeg adapter but differs in a few ways:
|
10
|
+
# 1. It starts by copying the derivative files to the work directory
|
11
|
+
# 2. It runs Mediainfo on the input and output files and skips ffmpeg
|
12
|
+
# 3. All work is done in the create method so it's status is always completed or failed
|
13
|
+
module ActiveEncode
|
14
|
+
module EngineAdapters
|
15
|
+
class PassThroughAdapter
|
16
|
+
WORK_DIR = ENV["ENCODE_WORK_DIR"] || "encodes" # Should read from config
|
17
|
+
MEDIAINFO_PATH = ENV["MEDIAINFO_PATH"] || "mediainfo"
|
18
|
+
|
19
|
+
def create(input_url, options = {})
|
20
|
+
# Decode file uris for ffmpeg (mediainfo works either way)
|
21
|
+
input_url = URI.decode(input_url) if input_url.starts_with? "file:///"
|
22
|
+
|
23
|
+
new_encode = ActiveEncode::Base.new(input_url, options)
|
24
|
+
new_encode.id = SecureRandom.uuid
|
25
|
+
new_encode.current_operations = []
|
26
|
+
new_encode.output = []
|
27
|
+
|
28
|
+
# Create a working directory that holds all output files related to the encode
|
29
|
+
FileUtils.mkdir_p working_path("", new_encode.id)
|
30
|
+
FileUtils.mkdir_p working_path("outputs", new_encode.id)
|
31
|
+
|
32
|
+
# Extract technical metadata from input file
|
33
|
+
`#{MEDIAINFO_PATH} --Output=XML --LogFile=#{working_path("input_metadata", new_encode.id)} #{input_url.shellescape}`
|
34
|
+
new_encode.input = build_input new_encode
|
35
|
+
new_encode.input.id = new_encode.id
|
36
|
+
new_encode.created_at, new_encode.updated_at = get_times new_encode.id
|
37
|
+
|
38
|
+
if new_encode.input.duration.blank?
|
39
|
+
new_encode.state = :failed
|
40
|
+
new_encode.percent_complete = 1
|
41
|
+
|
42
|
+
new_encode.errors = if new_encode.input.file_size.blank?
|
43
|
+
["#{input_url} does not exist or is not accessible"]
|
44
|
+
else
|
45
|
+
["Error inspecting input: #{input_url}"]
|
46
|
+
end
|
47
|
+
|
48
|
+
write_errors new_encode
|
49
|
+
return new_encode
|
50
|
+
end
|
51
|
+
|
52
|
+
# For saving filename to label map used to find the label when building outputs
|
53
|
+
filename_label_hash = {}
|
54
|
+
|
55
|
+
# Copy derivatives to work directory
|
56
|
+
options[:outputs].each do |opt|
|
57
|
+
url = opt[:url]
|
58
|
+
output_path = working_path("outputs/#{sanitize_base opt[:url]}#{File.extname opt[:url]}", new_encode.id)
|
59
|
+
FileUtils.cp FileLocator.new(url).location, output_path
|
60
|
+
filename_label_hash[output_path] = opt[:label]
|
61
|
+
end
|
62
|
+
|
63
|
+
# Write filename-to-label map so we can retrieve them on build_output
|
64
|
+
File.write working_path("filename_label.yml", new_encode.id), filename_label_hash.to_yaml
|
65
|
+
|
66
|
+
new_encode.percent_complete = 1
|
67
|
+
new_encode.state = :running
|
68
|
+
new_encode.errors = []
|
69
|
+
|
70
|
+
new_encode
|
71
|
+
rescue StandardError => e
|
72
|
+
new_encode.state = :failed
|
73
|
+
new_encode.percent_complete = 1
|
74
|
+
new_encode.errors = [e.full_message]
|
75
|
+
write_errors new_encode
|
76
|
+
return new_encode
|
77
|
+
end
|
78
|
+
|
79
|
+
# Return encode object from file system
|
80
|
+
def find(id, opts = {})
|
81
|
+
encode_class = opts[:cast]
|
82
|
+
encode_class ||= ActiveEncode::Base
|
83
|
+
encode = encode_class.new(nil, opts)
|
84
|
+
encode.id = id
|
85
|
+
encode.created_at, encode.updated_at = get_times encode.id
|
86
|
+
encode.input = build_input encode
|
87
|
+
encode.input.id = encode.id
|
88
|
+
encode.output = []
|
89
|
+
encode.current_operations = []
|
90
|
+
|
91
|
+
encode.errors = read_errors(id)
|
92
|
+
if encode.errors.present?
|
93
|
+
encode.state = :failed
|
94
|
+
encode.percent_complete = 1
|
95
|
+
elsif cancelled?(id)
|
96
|
+
encode.state = :cancelled
|
97
|
+
encode.percent_complete = 1
|
98
|
+
elsif completed?(id)
|
99
|
+
encode.state = :completed
|
100
|
+
encode.percent_complete = 100
|
101
|
+
else
|
102
|
+
encode.output = build_outputs encode
|
103
|
+
encode.state = :completed
|
104
|
+
encode.percent_complete = 100
|
105
|
+
end
|
106
|
+
|
107
|
+
encode
|
108
|
+
rescue StandardError => e
|
109
|
+
encode.state = :failed
|
110
|
+
encode.percent_complete = 1
|
111
|
+
encode.errors = [e.full_message]
|
112
|
+
write_errors encode
|
113
|
+
return encode
|
114
|
+
end
|
115
|
+
|
116
|
+
# Cancel ongoing encode using pid file
|
117
|
+
def cancel(id)
|
118
|
+
# Check for errors and if not then create cancelled file else raise CancelError?
|
119
|
+
if running?(id)
|
120
|
+
File.write(working_path("cancelled", id), "")
|
121
|
+
find id
|
122
|
+
else
|
123
|
+
raise CancelError
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def running?(id)
|
130
|
+
!cancelled?(id) || !failed?(id) || !completed?(id)
|
131
|
+
end
|
132
|
+
|
133
|
+
def cancelled?(id)
|
134
|
+
File.exist? working_path("cancelled", id)
|
135
|
+
end
|
136
|
+
|
137
|
+
def failed?(id)
|
138
|
+
read_errors(id).present?
|
139
|
+
end
|
140
|
+
|
141
|
+
def completed?(id)
|
142
|
+
File.exist? working_path("completed", id)
|
143
|
+
end
|
144
|
+
|
145
|
+
def get_times(id)
|
146
|
+
updated_at = if File.file? working_path("completed", id)
|
147
|
+
File.mtime(working_path("completed", id))
|
148
|
+
elsif File.file? working_path("cancelled", id)
|
149
|
+
File.mtime(working_path("cancelled", id))
|
150
|
+
elsif File.file? working_path("error.log", id)
|
151
|
+
File.mtime(working_path("error.log", id))
|
152
|
+
else
|
153
|
+
File.mtime(working_path("input_metadata", id))
|
154
|
+
end
|
155
|
+
|
156
|
+
[File.mtime(working_path("input_metadata", id)), updated_at]
|
157
|
+
end
|
158
|
+
|
159
|
+
def write_errors(encode)
|
160
|
+
File.write(working_path("error.log", encode.id), encode.errors.join("\n"))
|
161
|
+
end
|
162
|
+
|
163
|
+
def read_errors(id)
|
164
|
+
err_path = working_path("error.log", id)
|
165
|
+
error = File.read(err_path) if File.file? err_path
|
166
|
+
if error.present?
|
167
|
+
[error]
|
168
|
+
else
|
169
|
+
[]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def build_input(encode)
|
174
|
+
input = ActiveEncode::Input.new
|
175
|
+
metadata = get_tech_metadata(working_path("input_metadata", encode.id))
|
176
|
+
input.url = metadata[:url]
|
177
|
+
input.assign_tech_metadata(metadata)
|
178
|
+
created_at = File.mtime(working_path("input_metadata", encode.id))
|
179
|
+
input.created_at = created_at
|
180
|
+
input.updated_at = created_at
|
181
|
+
|
182
|
+
input
|
183
|
+
end
|
184
|
+
|
185
|
+
def build_outputs(encode)
|
186
|
+
id = encode.id
|
187
|
+
outputs = []
|
188
|
+
filename_label_hash = YAML.safe_load(File.read(working_path("filename_label.yml", id))) if File.exist?(working_path("filename_label.yml", id))
|
189
|
+
Dir["#{File.absolute_path(working_path('outputs', id))}/*"].each do |file_path|
|
190
|
+
output = ActiveEncode::Output.new
|
191
|
+
output.url = "file://#{file_path}"
|
192
|
+
output.label = filename_label_hash[file_path] if filename_label_hash
|
193
|
+
output.id = "#{encode.input.id}-#{output.label}"
|
194
|
+
output.created_at = encode.created_at
|
195
|
+
output.updated_at = File.mtime file_path
|
196
|
+
|
197
|
+
# Extract technical metadata from output file
|
198
|
+
metadata_path = working_path("output_metadata-#{output.label}", id)
|
199
|
+
`#{MEDIAINFO_PATH} --Output=XML --LogFile=#{metadata_path} #{output.url}` unless File.file? metadata_path
|
200
|
+
output.assign_tech_metadata(get_tech_metadata(metadata_path))
|
201
|
+
|
202
|
+
outputs << output
|
203
|
+
end
|
204
|
+
File.write(working_path("completed", id), "")
|
205
|
+
|
206
|
+
outputs
|
207
|
+
end
|
208
|
+
|
209
|
+
def sanitize_base(input_url)
|
210
|
+
File.basename(input_url, File.extname(input_url)).gsub(/[^0-9A-Za-z.\-]/, '_')
|
211
|
+
end
|
212
|
+
|
213
|
+
def working_path(path, id)
|
214
|
+
File.join(WORK_DIR, id, path)
|
215
|
+
end
|
216
|
+
|
217
|
+
def get_tech_metadata(file_path)
|
218
|
+
doc = Nokogiri::XML File.read(file_path)
|
219
|
+
doc.remove_namespaces!
|
220
|
+
duration = get_xpath_text(doc, '//Duration/text()', :to_f)
|
221
|
+
duration *= 1000 unless duration.nil? # Convert to milliseconds
|
222
|
+
{ url: get_xpath_text(doc, '//media/@ref', :to_s),
|
223
|
+
width: get_xpath_text(doc, '//Width/text()', :to_f),
|
224
|
+
height: get_xpath_text(doc, '//Height/text()', :to_f),
|
225
|
+
frame_rate: get_xpath_text(doc, '//FrameRate/text()', :to_f),
|
226
|
+
duration: duration,
|
227
|
+
file_size: get_xpath_text(doc, '//FileSize/text()', :to_i),
|
228
|
+
audio_codec: get_xpath_text(doc, '//track[@type="Audio"]/CodecID/text()', :to_s),
|
229
|
+
audio_bitrate: get_xpath_text(doc, '//track[@type="Audio"]/BitRate/text()', :to_i),
|
230
|
+
video_codec: get_xpath_text(doc, '//track[@type="Video"]/CodecID/text()', :to_s),
|
231
|
+
video_bitrate: get_xpath_text(doc, '//track[@type="Video"]/BitRate/text()', :to_i) }
|
232
|
+
end
|
233
|
+
|
234
|
+
def get_xpath_text(doc, xpath, cast_method)
|
235
|
+
doc.xpath(xpath).first&.text&.send(cast_method)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ActiveEncode
|
2
3
|
module EngineAdapters
|
3
4
|
class TestAdapter
|
@@ -9,8 +10,8 @@ module ActiveEncode
|
|
9
10
|
new_encode = ActiveEncode::Base.new(input_url, options)
|
10
11
|
new_encode.id = SecureRandom.uuid
|
11
12
|
new_encode.state = :running
|
12
|
-
new_encode.created_at = Time.now
|
13
|
-
new_encode.updated_at = Time.now
|
13
|
+
new_encode.created_at = Time.now.utc
|
14
|
+
new_encode.updated_at = Time.now.utc
|
14
15
|
@encodes[new_encode.id] = new_encode
|
15
16
|
new_encode
|
16
17
|
end
|
@@ -18,14 +19,14 @@ module ActiveEncode
|
|
18
19
|
def find(id, _opts = {})
|
19
20
|
new_encode = @encodes[id]
|
20
21
|
# Update the updated_at time to simulate changes
|
21
|
-
new_encode.updated_at = Time.now
|
22
|
+
new_encode.updated_at = Time.now.utc
|
22
23
|
new_encode
|
23
24
|
end
|
24
25
|
|
25
26
|
def cancel(id)
|
26
27
|
new_encode = @encodes[id]
|
27
28
|
new_encode.state = :cancelled
|
28
|
-
new_encode.updated_at = Time.now
|
29
|
+
new_encode.updated_at = Time.now.utc
|
29
30
|
new_encode
|
30
31
|
end
|
31
32
|
end
|
@@ -1,13 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ActiveEncode
|
2
3
|
module EngineAdapters
|
3
4
|
class ZencoderAdapter
|
4
5
|
# TODO: add a stub for an input helper (supplied by an initializer) that transforms encode.input.url into a zencoder accepted url
|
5
|
-
def create(input_url,
|
6
|
+
def create(input_url, _options = {})
|
6
7
|
response = Zencoder::Job.create(input: input_url.to_s)
|
7
8
|
build_encode(get_job_details(response.body["id"]))
|
8
9
|
end
|
9
10
|
|
10
|
-
def find(id,
|
11
|
+
def find(id, _opts = {})
|
11
12
|
build_encode(get_job_details(id))
|
12
13
|
end
|
13
14
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'globalid'
|
2
3
|
|
3
4
|
module ActiveEncode
|
@@ -9,7 +10,7 @@ module ActiveEncode
|
|
9
10
|
other.is_a?(ActiveEncode::Base) && to_global_id == other.to_global_id
|
10
11
|
end
|
11
12
|
|
12
|
-
def to_global_id(
|
13
|
+
def to_global_id(_options = {})
|
13
14
|
super(app: 'ActiveEncode')
|
14
15
|
end
|
15
16
|
end
|
data/lib/active_encode/input.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ActiveEncode
|
2
3
|
class Input
|
3
4
|
include Status
|
@@ -8,8 +9,8 @@ module ActiveEncode
|
|
8
9
|
|
9
10
|
def valid?
|
10
11
|
id.present? && url.present? &&
|
11
|
-
|
12
|
-
|
12
|
+
created_at.is_a?(Time) && updated_at.is_a?(Time) &&
|
13
|
+
updated_at >= created_at
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
data/lib/active_encode/output.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ActiveEncode
|
2
3
|
class Output
|
3
4
|
include Status
|
@@ -9,8 +10,8 @@ module ActiveEncode
|
|
9
10
|
|
10
11
|
def valid?
|
11
12
|
id.present? && url.present? && label.present? &&
|
12
|
-
|
13
|
-
|
13
|
+
created_at.is_a?(Time) && updated_at.is_a?(Time) &&
|
14
|
+
updated_at >= created_at
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|