active_encode 0.8.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +26 -17
- data/.rubocop.yml +7 -3
- data/.rubocop_todo.yml +8 -1
- data/CONTRIBUTING.md +42 -12
- data/Gemfile +11 -11
- data/README.md +64 -10
- data/active_encode.gemspec +2 -4
- data/app/controllers/active_encode/encode_record_controller.rb +1 -1
- data/app/jobs/active_encode/polling_job.rb +1 -1
- data/app/models/active_encode/encode_record.rb +1 -1
- data/guides/media_convert_adapter.md +208 -0
- data/lib/active_encode/base.rb +1 -1
- data/lib/active_encode/core.rb +14 -14
- data/lib/active_encode/engine_adapter.rb +13 -13
- data/lib/active_encode/engine_adapters/elastic_transcoder_adapter.rb +158 -158
- data/lib/active_encode/engine_adapters/ffmpeg_adapter.rb +14 -3
- data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +204 -202
- data/lib/active_encode/engine_adapters/media_convert_adapter.rb +435 -203
- data/lib/active_encode/engine_adapters/media_convert_output.rb +67 -5
- data/lib/active_encode/engine_adapters/pass_through_adapter.rb +3 -3
- data/lib/active_encode/engine_adapters/zencoder_adapter.rb +114 -114
- data/lib/active_encode/errors.rb +1 -1
- data/lib/active_encode/persistence.rb +19 -19
- data/lib/active_encode/version.rb +1 -1
- data/lib/file_locator.rb +6 -6
- data/spec/fixtures/ffmpeg/cancelled-id/exit_status.code +1 -0
- data/spec/fixtures/ffmpeg/completed-id/exit_status.code +1 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/error.log +3 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/exit_status.code +1 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/input_metadata +102 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/output_metadata-high +90 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/output_metadata-low +90 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/pid +1 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/progress +11 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/video-high.mp4 +0 -0
- data/spec/fixtures/ffmpeg/completed-with-warnings-id/video-low.mp4 +0 -0
- data/spec/fixtures/ffmpeg/failed-id/exit_status.code +1 -0
- data/spec/fixtures/media_convert/job_completed_empty_detail.json +1 -0
- data/spec/integration/ffmpeg_adapter_spec.rb +50 -1
- data/spec/integration/matterhorn_adapter_spec.rb +1 -2
- data/spec/integration/media_convert_adapter_spec.rb +144 -0
- data/spec/integration/pass_through_adapter_spec.rb +2 -2
- data/spec/integration/zencoder_adapter_spec.rb +3 -3
- data/spec/units/core_spec.rb +1 -1
- data/spec/units/file_locator_spec.rb +3 -3
- data/spec/units/status_spec.rb +1 -1
- metadata +52 -19
@@ -0,0 +1,90 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<MediaInfo
|
3
|
+
xmlns="https://mediaarea.net/mediainfo"
|
4
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
5
|
+
xsi:schemaLocation="https://mediaarea.net/mediainfo https://mediaarea.net/mediainfo/mediainfo_2_0.xsd"
|
6
|
+
version="2.0">
|
7
|
+
<creatingLibrary version="18.05" url="https://mediaarea.net/MediaInfo">MediaInfoLib</creatingLibrary>
|
8
|
+
<media ref="spec/fixtures/ffmpeg/completed-id/low.mp4">
|
9
|
+
<track type="General">
|
10
|
+
<VideoCount>1</VideoCount>
|
11
|
+
<AudioCount>1</AudioCount>
|
12
|
+
<FileExtension>mp4</FileExtension>
|
13
|
+
<Format>MPEG-4</Format>
|
14
|
+
<Format_Profile>Base Media</Format_Profile>
|
15
|
+
<CodecID>isom</CodecID>
|
16
|
+
<FileSize>125403</FileSize>
|
17
|
+
<Duration>6.336</Duration>
|
18
|
+
<OverallBitRate>158337</OverallBitRate>
|
19
|
+
<FrameRate>24.000</FrameRate>
|
20
|
+
<FrameCount>150</FrameCount>
|
21
|
+
<StreamSize>5648</StreamSize>
|
22
|
+
<HeaderSize>40</HeaderSize>
|
23
|
+
<DataSize>119763</DataSize>
|
24
|
+
<FooterSize>5600</FooterSize>
|
25
|
+
<IsStreamable>No</IsStreamable>
|
26
|
+
<File_Modified_Date>UTC 2018-09-07 17:36:26</File_Modified_Date>
|
27
|
+
<File_Modified_Date_Local>2018-09-07 13:36:26</File_Modified_Date_Local>
|
28
|
+
<Encoded_Application>Lavf58.12.100</Encoded_Application>
|
29
|
+
</track>
|
30
|
+
<track type="Video">
|
31
|
+
<StreamOrder>0</StreamOrder>
|
32
|
+
<ID>1</ID>
|
33
|
+
<Format>AVC</Format>
|
34
|
+
<Format_Profile>High</Format_Profile>
|
35
|
+
<Format_Level>1.1</Format_Level>
|
36
|
+
<Format_Settings_CABAC>Yes</Format_Settings_CABAC>
|
37
|
+
<Format_Settings_RefFrames>4</Format_Settings_RefFrames>
|
38
|
+
<CodecID>avc1</CodecID>
|
39
|
+
<Duration>6.250</Duration>
|
40
|
+
<BitRate>79302</BitRate>
|
41
|
+
<Width>200</Width>
|
42
|
+
<Height>110</Height>
|
43
|
+
<Stored_Width>208</Stored_Width>
|
44
|
+
<Stored_Height>112</Stored_Height>
|
45
|
+
<Sampled_Width>200</Sampled_Width>
|
46
|
+
<Sampled_Height>110</Sampled_Height>
|
47
|
+
<PixelAspectRatio>1.000</PixelAspectRatio>
|
48
|
+
<DisplayAspectRatio>1.818</DisplayAspectRatio>
|
49
|
+
<Rotation>0.000</Rotation>
|
50
|
+
<FrameRate_Mode>CFR</FrameRate_Mode>
|
51
|
+
<FrameRate_Mode_Original>VFR</FrameRate_Mode_Original>
|
52
|
+
<FrameRate>24.000</FrameRate>
|
53
|
+
<FrameCount>150</FrameCount>
|
54
|
+
<ColorSpace>YUV</ColorSpace>
|
55
|
+
<ChromaSubsampling>4:2:0</ChromaSubsampling>
|
56
|
+
<BitDepth>8</BitDepth>
|
57
|
+
<ScanType>Progressive</ScanType>
|
58
|
+
<StreamSize>61955</StreamSize>
|
59
|
+
<Encoded_Library>x264 - core 152 r2854 e9a5903</Encoded_Library>
|
60
|
+
<Encoded_Library_Name>x264</Encoded_Library_Name>
|
61
|
+
<Encoded_Library_Version>core 152 r2854 e9a5903</Encoded_Library_Version>
|
62
|
+
<Encoded_Library_Settings>cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=3 / lookahead_threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=24 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=23.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00</Encoded_Library_Settings>
|
63
|
+
</track>
|
64
|
+
<track type="Audio">
|
65
|
+
<StreamOrder>1</StreamOrder>
|
66
|
+
<ID>2</ID>
|
67
|
+
<Format>AAC</Format>
|
68
|
+
<Format_Profile>LC</Format_Profile>
|
69
|
+
<Format_Settings_SBR>No (Explicit)</Format_Settings_SBR>
|
70
|
+
<CodecID>mp4a-40-2</CodecID>
|
71
|
+
<Duration>6.336</Duration>
|
72
|
+
<BitRate_Mode>CBR</BitRate_Mode>
|
73
|
+
<BitRate>72000</BitRate>
|
74
|
+
<Channels>2</Channels>
|
75
|
+
<Channels_Original>1</Channels_Original>
|
76
|
+
<ChannelPositions>Front: C</ChannelPositions>
|
77
|
+
<ChannelLayout>C</ChannelLayout>
|
78
|
+
<SamplesPerFrame>1024</SamplesPerFrame>
|
79
|
+
<SamplingRate>48000</SamplingRate>
|
80
|
+
<SamplingCount>304128</SamplingCount>
|
81
|
+
<FrameRate>46.875</FrameRate>
|
82
|
+
<FrameCount>297</FrameCount>
|
83
|
+
<Compression_Mode>Lossy</Compression_Mode>
|
84
|
+
<StreamSize>57800</StreamSize>
|
85
|
+
<StreamSize_Proportion>0.46091</StreamSize_Proportion>
|
86
|
+
<Default>Yes</Default>
|
87
|
+
<AlternateGroup>1</AlternateGroup>
|
88
|
+
</track>
|
89
|
+
</media>
|
90
|
+
</MediaInfo>
|
@@ -0,0 +1,90 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<MediaInfo
|
3
|
+
xmlns="https://mediaarea.net/mediainfo"
|
4
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
5
|
+
xsi:schemaLocation="https://mediaarea.net/mediainfo https://mediaarea.net/mediainfo/mediainfo_2_0.xsd"
|
6
|
+
version="2.0">
|
7
|
+
<creatingLibrary version="18.05" url="https://mediaarea.net/MediaInfo">MediaInfoLib</creatingLibrary>
|
8
|
+
<media ref="spec/fixtures/ffmpeg/completed-id/low.mp4">
|
9
|
+
<track type="General">
|
10
|
+
<VideoCount>1</VideoCount>
|
11
|
+
<AudioCount>1</AudioCount>
|
12
|
+
<FileExtension>mp4</FileExtension>
|
13
|
+
<Format>MPEG-4</Format>
|
14
|
+
<Format_Profile>Base Media</Format_Profile>
|
15
|
+
<CodecID>isom</CodecID>
|
16
|
+
<FileSize>125403</FileSize>
|
17
|
+
<Duration>6.336</Duration>
|
18
|
+
<OverallBitRate>158337</OverallBitRate>
|
19
|
+
<FrameRate>24.000</FrameRate>
|
20
|
+
<FrameCount>150</FrameCount>
|
21
|
+
<StreamSize>5648</StreamSize>
|
22
|
+
<HeaderSize>40</HeaderSize>
|
23
|
+
<DataSize>119763</DataSize>
|
24
|
+
<FooterSize>5600</FooterSize>
|
25
|
+
<IsStreamable>No</IsStreamable>
|
26
|
+
<File_Modified_Date>UTC 2018-09-07 17:36:26</File_Modified_Date>
|
27
|
+
<File_Modified_Date_Local>2018-09-07 13:36:26</File_Modified_Date_Local>
|
28
|
+
<Encoded_Application>Lavf58.12.100</Encoded_Application>
|
29
|
+
</track>
|
30
|
+
<track type="Video">
|
31
|
+
<StreamOrder>0</StreamOrder>
|
32
|
+
<ID>1</ID>
|
33
|
+
<Format>AVC</Format>
|
34
|
+
<Format_Profile>High</Format_Profile>
|
35
|
+
<Format_Level>1.1</Format_Level>
|
36
|
+
<Format_Settings_CABAC>Yes</Format_Settings_CABAC>
|
37
|
+
<Format_Settings_RefFrames>4</Format_Settings_RefFrames>
|
38
|
+
<CodecID>avc1</CodecID>
|
39
|
+
<Duration>6.250</Duration>
|
40
|
+
<BitRate>79302</BitRate>
|
41
|
+
<Width>200</Width>
|
42
|
+
<Height>110</Height>
|
43
|
+
<Stored_Width>208</Stored_Width>
|
44
|
+
<Stored_Height>112</Stored_Height>
|
45
|
+
<Sampled_Width>200</Sampled_Width>
|
46
|
+
<Sampled_Height>110</Sampled_Height>
|
47
|
+
<PixelAspectRatio>1.000</PixelAspectRatio>
|
48
|
+
<DisplayAspectRatio>1.818</DisplayAspectRatio>
|
49
|
+
<Rotation>0.000</Rotation>
|
50
|
+
<FrameRate_Mode>CFR</FrameRate_Mode>
|
51
|
+
<FrameRate_Mode_Original>VFR</FrameRate_Mode_Original>
|
52
|
+
<FrameRate>24.000</FrameRate>
|
53
|
+
<FrameCount>150</FrameCount>
|
54
|
+
<ColorSpace>YUV</ColorSpace>
|
55
|
+
<ChromaSubsampling>4:2:0</ChromaSubsampling>
|
56
|
+
<BitDepth>8</BitDepth>
|
57
|
+
<ScanType>Progressive</ScanType>
|
58
|
+
<StreamSize>61955</StreamSize>
|
59
|
+
<Encoded_Library>x264 - core 152 r2854 e9a5903</Encoded_Library>
|
60
|
+
<Encoded_Library_Name>x264</Encoded_Library_Name>
|
61
|
+
<Encoded_Library_Version>core 152 r2854 e9a5903</Encoded_Library_Version>
|
62
|
+
<Encoded_Library_Settings>cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=3 / lookahead_threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=24 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=23.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00</Encoded_Library_Settings>
|
63
|
+
</track>
|
64
|
+
<track type="Audio">
|
65
|
+
<StreamOrder>1</StreamOrder>
|
66
|
+
<ID>2</ID>
|
67
|
+
<Format>AAC</Format>
|
68
|
+
<Format_Profile>LC</Format_Profile>
|
69
|
+
<Format_Settings_SBR>No (Explicit)</Format_Settings_SBR>
|
70
|
+
<CodecID>mp4a-40-2</CodecID>
|
71
|
+
<Duration>6.336</Duration>
|
72
|
+
<BitRate_Mode>CBR</BitRate_Mode>
|
73
|
+
<BitRate>72000</BitRate>
|
74
|
+
<Channels>2</Channels>
|
75
|
+
<Channels_Original>1</Channels_Original>
|
76
|
+
<ChannelPositions>Front: C</ChannelPositions>
|
77
|
+
<ChannelLayout>C</ChannelLayout>
|
78
|
+
<SamplesPerFrame>1024</SamplesPerFrame>
|
79
|
+
<SamplingRate>48000</SamplingRate>
|
80
|
+
<SamplingCount>304128</SamplingCount>
|
81
|
+
<FrameRate>46.875</FrameRate>
|
82
|
+
<FrameCount>297</FrameCount>
|
83
|
+
<Compression_Mode>Lossy</Compression_Mode>
|
84
|
+
<StreamSize>57800</StreamSize>
|
85
|
+
<StreamSize_Proportion>0.46091</StreamSize_Proportion>
|
86
|
+
<Default>Yes</Default>
|
87
|
+
<AlternateGroup>1</AlternateGroup>
|
88
|
+
</track>
|
89
|
+
</media>
|
90
|
+
</MediaInfo>
|
@@ -0,0 +1 @@
|
|
1
|
+
99999
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
-22
|
@@ -0,0 +1 @@
|
|
1
|
+
{"results":[],"statistics":{"records_matched":1.0,"records_scanned":13.0,"bytes_scanned":10750.0},"status":"Complete"}
|
@@ -37,6 +37,7 @@ describe ActiveEncode::EngineAdapters::FfmpegAdapter do
|
|
37
37
|
encode
|
38
38
|
end
|
39
39
|
let(:completed_job) { find_encode "completed-id" }
|
40
|
+
let(:completed_with_warnings_job) { find_encode "completed-with-warnings-id" }
|
40
41
|
let(:failed_job) { find_encode 'failed-id' }
|
41
42
|
let(:completed_tech_metadata) do
|
42
43
|
{
|
@@ -129,7 +130,7 @@ describe ActiveEncode::EngineAdapters::FfmpegAdapter do
|
|
129
130
|
end
|
130
131
|
|
131
132
|
context 'when uri encoded' do
|
132
|
-
let(:file_with_space) { URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file with space.mp4').to_s) }
|
133
|
+
let(:file_with_space) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file with space.mp4').to_s) }
|
133
134
|
|
134
135
|
it "does not have errors" do
|
135
136
|
sleep 2
|
@@ -164,6 +165,54 @@ describe ActiveEncode::EngineAdapters::FfmpegAdapter do
|
|
164
165
|
it "has a progress file" do
|
165
166
|
expect(File).to exist("#{work_dir}/#{subject.id}/progress")
|
166
167
|
end
|
168
|
+
|
169
|
+
it "does not have an exit code file" do
|
170
|
+
expect(File).not_to exist("#{work_dir}/#{subject.id}/exit_status.code")
|
171
|
+
end
|
172
|
+
|
173
|
+
context "completed job" do
|
174
|
+
subject { completed_job }
|
175
|
+
|
176
|
+
it { is_expected.to be_completed }
|
177
|
+
it "has an exit code of 0" do
|
178
|
+
expect(File).to exist("#{work_dir}/#{subject.id}/exit_status.code")
|
179
|
+
expect(File.read("#{work_dir}/#{subject.id}/exit_status.code").to_i).to eq 0
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context "completed with warnings job" do
|
184
|
+
subject { completed_with_warnings_job }
|
185
|
+
|
186
|
+
it { is_expected.to be_completed }
|
187
|
+
it "has an exit code of 0" do
|
188
|
+
expect(File).to exist("#{work_dir}/#{subject.id}/exit_status.code")
|
189
|
+
expect(File.read("#{work_dir}/#{subject.id}/exit_status.code").to_i).to eq 0
|
190
|
+
end
|
191
|
+
it "has warnings in the error log" do
|
192
|
+
expect(File).to exist("#{work_dir}/#{subject.id}/error.log")
|
193
|
+
expect(File.read("#{work_dir}/#{subject.id}/error.log")).not_to be_empty
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context "cancelled job" do
|
198
|
+
subject { canceled_job }
|
199
|
+
|
200
|
+
it { is_expected.to be_cancelled }
|
201
|
+
it "has an exit code of 143" do
|
202
|
+
expect(File).to exist("#{work_dir}/#{subject.id}/exit_status.code")
|
203
|
+
expect(File.read("#{work_dir}/#{subject.id}/exit_status.code").to_i).to eq 143
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "failed job" do
|
208
|
+
subject { failed_job }
|
209
|
+
|
210
|
+
it { is_expected.to be_failed }
|
211
|
+
it "has an exit code of -22" do
|
212
|
+
expect(File).to exist("#{work_dir}/#{subject.id}/exit_status.code")
|
213
|
+
expect(File.read("#{work_dir}/#{subject.id}/exit_status.code").to_i).to eq(-22)
|
214
|
+
end
|
215
|
+
end
|
167
216
|
end
|
168
217
|
|
169
218
|
describe "#cancel!" do
|
@@ -102,12 +102,11 @@ describe ActiveEncode::EngineAdapters::MatterhornAdapter do
|
|
102
102
|
end
|
103
103
|
|
104
104
|
describe "reload" do
|
105
|
+
subject { running_job.reload }
|
105
106
|
before do
|
106
107
|
expect(Rubyhorn.client).to receive(:instance_xml).twice.with('running-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/running_response.xml')))
|
107
108
|
end
|
108
109
|
|
109
|
-
subject { running_job.reload }
|
110
|
-
|
111
110
|
it { expect(subject.output).to be_empty }
|
112
111
|
it { expect(subject.options).to include(preset: 'full') }
|
113
112
|
it { expect(subject.current_operations).to include("Hold for workflow selection") }
|
@@ -87,6 +87,16 @@ describe ActiveEncode::EngineAdapters::MediaConvertAdapter do
|
|
87
87
|
ActiveEncode::Base.find(job_id)
|
88
88
|
end
|
89
89
|
|
90
|
+
let(:recent_completed_job_without_results) do
|
91
|
+
job_response = reconstitute_response("media_convert/job_completed.json")
|
92
|
+
job_response["job"]["timing"]["finish_time"] = 5.minutes.ago
|
93
|
+
mediaconvert.stub_responses(:get_job, job_response)
|
94
|
+
cloudwatch_logs.stub_responses(:start_query, reconstitute_response("media_convert/job_completed_detail_query.json"))
|
95
|
+
cloudwatch_logs.stub_responses(:get_query_results, reconstitute_response("media_convert/job_completed_empty_detail.json"))
|
96
|
+
|
97
|
+
ActiveEncode::Base.find(job_id)
|
98
|
+
end
|
99
|
+
|
90
100
|
let(:failed_job) do
|
91
101
|
mediaconvert.stub_responses(:get_job, reconstitute_response("media_convert/job_failed.json"))
|
92
102
|
|
@@ -113,6 +123,102 @@ describe ActiveEncode::EngineAdapters::MediaConvertAdapter do
|
|
113
123
|
|
114
124
|
it_behaves_like "an ActiveEncode::EngineAdapter"
|
115
125
|
|
126
|
+
describe "output location specification" do
|
127
|
+
let(:operations) { mediaconvert.api_requests(exclude_presign: true) }
|
128
|
+
before do
|
129
|
+
mediaconvert.stub_responses(:create_job, reconstitute_response("media_convert/job_created.json"))
|
130
|
+
end
|
131
|
+
|
132
|
+
it "can use output_bucket and output_prefix" do
|
133
|
+
ActiveEncode::Base.create(
|
134
|
+
"s3://input-bucket/test_files/source_file.mp4",
|
135
|
+
output_prefix: "active-encode-test/output",
|
136
|
+
outputs: [],
|
137
|
+
use_original_url: true
|
138
|
+
)
|
139
|
+
create_job_operation = operations.find { |o| o[:operation_name] == :create_job }
|
140
|
+
expect(create_job_operation).to be_present
|
141
|
+
|
142
|
+
destination = create_job_operation.dig(:params, :settings, :output_groups, 0,
|
143
|
+
:output_group_settings, :hls_group_settings, :destination)
|
144
|
+
|
145
|
+
expect(destination).to eq("s3://output-bucket/active-encode-test/output")
|
146
|
+
end
|
147
|
+
|
148
|
+
it "can use destination arg" do
|
149
|
+
ActiveEncode::Base.create(
|
150
|
+
"s3://input-bucket/test_files/source_file.mp4",
|
151
|
+
destination: "s3://alternate-output-bucket/my-path/output",
|
152
|
+
outputs: [],
|
153
|
+
use_original_url: true
|
154
|
+
)
|
155
|
+
create_job_operation = operations.find { |o| o[:operation_name] == :create_job }
|
156
|
+
expect(create_job_operation).to be_present
|
157
|
+
|
158
|
+
destination = create_job_operation.dig(:params, :settings, :output_groups, 0,
|
159
|
+
:output_group_settings, :hls_group_settings, :destination)
|
160
|
+
|
161
|
+
expect(destination).to eq("s3://alternate-output-bucket/my-path/output")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "output_group_destination_settings" do
|
166
|
+
let(:operations) { mediaconvert.api_requests(exclude_presign: true) }
|
167
|
+
before do
|
168
|
+
mediaconvert.stub_responses(:create_job, reconstitute_response("media_convert/job_created.json"))
|
169
|
+
end
|
170
|
+
|
171
|
+
it "are sent to MediaConvert" do
|
172
|
+
ActiveEncode::Base.create(
|
173
|
+
"s3://input-bucket/test_files/source_file.mp4",
|
174
|
+
destination: "s3://alternate-output-bucket/my-path/output",
|
175
|
+
outputs: [],
|
176
|
+
use_original_url: true,
|
177
|
+
output_group_destination_settings: {
|
178
|
+
s3_settings: {
|
179
|
+
access_control: {
|
180
|
+
canned_acl: "PUBLIC_READ"
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
)
|
185
|
+
|
186
|
+
create_job_operation = operations.find { |o| o[:operation_name] == :create_job }
|
187
|
+
expect(create_job_operation).to be_present
|
188
|
+
|
189
|
+
destination_settings = create_job_operation.dig(:params, :settings, :output_groups, 0,
|
190
|
+
:output_group_settings, :hls_group_settings, :destination_settings)
|
191
|
+
expect(destination_settings).to eq({ s3_settings: { access_control: { canned_acl: "PUBLIC_READ" } } })
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "queue" do
|
196
|
+
let(:operations) { mediaconvert.api_requests(exclude_presign: true) }
|
197
|
+
|
198
|
+
it "uses the default queue" do
|
199
|
+
mediaconvert.stub_responses(:create_job, reconstitute_response("media_convert/job_created.json"))
|
200
|
+
ActiveEncode::Base.create(
|
201
|
+
"s3://input-bucket/test_files/source_file.mp4",
|
202
|
+
output_prefix: "active-encode-test/output",
|
203
|
+
outputs: [],
|
204
|
+
use_original_url: true
|
205
|
+
)
|
206
|
+
expect(operations).to include(include(operation_name: :create_job, params: include(queue: 'Default')))
|
207
|
+
end
|
208
|
+
|
209
|
+
it "uses a specific queue" do
|
210
|
+
mediaconvert.stub_responses(:create_job, reconstitute_response("media_convert/job_created.json"))
|
211
|
+
ActiveEncode::Base.engine_adapter.queue = 'test-queue'
|
212
|
+
ActiveEncode::Base.create(
|
213
|
+
"s3://input-bucket/test_files/source_file.mp4",
|
214
|
+
output_prefix: "active-encode-test/output",
|
215
|
+
outputs: [],
|
216
|
+
use_original_url: true
|
217
|
+
)
|
218
|
+
expect(operations).to include(include(operation_name: :create_job, params: include(queue: 'test-queue')))
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
116
222
|
describe "output" do
|
117
223
|
it "contains all expected outputs" do
|
118
224
|
completed_output.each do |expected_output|
|
@@ -122,5 +228,43 @@ describe ActiveEncode::EngineAdapters::MediaConvertAdapter do
|
|
122
228
|
end
|
123
229
|
end
|
124
230
|
end
|
231
|
+
|
232
|
+
it "has no logging entries but finished within the last 10 minutes" do
|
233
|
+
expect(recent_completed_job_without_results.state).to eq(:running)
|
234
|
+
end
|
235
|
+
|
236
|
+
it "finished more than 10 minutes ago but has no logging entries" do
|
237
|
+
mediaconvert.stub_responses(:get_job, reconstitute_response("media_convert/job_completed.json"))
|
238
|
+
cloudwatch_logs.stub_responses(:start_query, reconstitute_response("media_convert/job_completed_detail_query.json"))
|
239
|
+
cloudwatch_logs.stub_responses(:get_query_results, reconstitute_response("media_convert/job_completed_empty_detail.json"))
|
240
|
+
|
241
|
+
expect { ActiveEncode::Base.find(job_id) }.to raise_error do |error|
|
242
|
+
expect(error).to be_a(ActiveEncode::EngineAdapters::MediaConvertAdapter::ResultsNotAvailable)
|
243
|
+
expect(error.encode).to be_a(ActiveEncode::Base)
|
244
|
+
expect(error.encode.state).to eq(:completed)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe "direct_output_lookup" do
|
250
|
+
before do
|
251
|
+
ActiveEncode::Base.engine_adapter.direct_output_lookup = true
|
252
|
+
end
|
253
|
+
|
254
|
+
it "contains all expected outputs" do
|
255
|
+
completed_output.each do |expected_output|
|
256
|
+
found_output = completed_job.output.find { |output| output.id == expected_output[:id] }
|
257
|
+
expected_output.each_pair do |key, value|
|
258
|
+
expect(found_output.send(key)).to eq(value)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
it "does not make cloudwatch queries" do
|
264
|
+
expect(cloudwatch_logs).not_to receive(:start_query)
|
265
|
+
expect(cloudwatch_logs).not_to receive(:get_query_results)
|
266
|
+
|
267
|
+
completed_job
|
268
|
+
end
|
125
269
|
end
|
126
270
|
end
|
@@ -124,8 +124,8 @@ describe ActiveEncode::EngineAdapters::PassThroughAdapter do
|
|
124
124
|
end
|
125
125
|
|
126
126
|
context 'when uri encoded' do
|
127
|
-
let(:file_with_space) { URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file with space.mp4').to_s) }
|
128
|
-
let(:file_with_space_derivative) { URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file with space.low.mp4').to_s) }
|
127
|
+
let(:file_with_space) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file with space.mp4').to_s) }
|
128
|
+
let(:file_with_space_derivative) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file with space.low.mp4').to_s) }
|
129
129
|
|
130
130
|
it "does not have errors" do
|
131
131
|
expect(find_space_job.errors).to be_empty
|
@@ -20,12 +20,12 @@ describe ActiveEncode::EngineAdapters::ZencoderAdapter do
|
|
20
20
|
let(:file) { "file://#{File.absolute_path('spec/fixtures/Bars_512kb.mp4')}" }
|
21
21
|
|
22
22
|
describe "#create" do
|
23
|
+
subject { ActiveEncode::Base.create(file) }
|
23
24
|
before do
|
24
25
|
allow(Zencoder::Job).to receive(:details).and_return(details_response)
|
25
26
|
allow(Zencoder::Job).to receive(:progress).and_return(progress_response)
|
26
27
|
end
|
27
28
|
|
28
|
-
subject { ActiveEncode::Base.create(file) }
|
29
29
|
let(:details_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_create.json'))) }
|
30
30
|
let(:progress_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_create.json'))) }
|
31
31
|
let(:create_output) { [{ id: "511404522", url: "https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150610/c09b61e4d130ddf923f0653418a80b9c/399ae101c3f99b4f318635e78a4e587a.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=GY/9LMkQAiDOrMQwS5BkmOE200s%3D&Expires=1434033527", label: nil }] }
|
@@ -302,13 +302,13 @@ describe ActiveEncode::EngineAdapters::ZencoderAdapter do
|
|
302
302
|
end
|
303
303
|
|
304
304
|
describe "#cancel!" do
|
305
|
+
subject { encode.cancel! }
|
305
306
|
before do
|
306
307
|
allow(Zencoder::Job).to receive(:cancel).and_return(cancel_response)
|
307
308
|
allow(Zencoder::Job).to receive(:details).and_return(details_response)
|
308
309
|
allow(Zencoder::Job).to receive(:progress).and_return(progress_response)
|
309
310
|
end
|
310
311
|
|
311
|
-
subject { encode.cancel! }
|
312
312
|
let(:cancel_response) { Zencoder::Response.new(code: 200) } # TODO: check that this is the correct response code for a successful cancel
|
313
313
|
let(:details_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_cancelled.json'))) }
|
314
314
|
let(:progress_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_cancelled.json'))) }
|
@@ -320,12 +320,12 @@ describe ActiveEncode::EngineAdapters::ZencoderAdapter do
|
|
320
320
|
end
|
321
321
|
|
322
322
|
describe "reload" do
|
323
|
+
subject { ActiveEncode::Base.find('166019107').reload }
|
323
324
|
before do
|
324
325
|
allow(Zencoder::Job).to receive(:details).and_return(details_response)
|
325
326
|
allow(Zencoder::Job).to receive(:progress).and_return(progress_response)
|
326
327
|
end
|
327
328
|
|
328
|
-
subject { ActiveEncode::Base.find('166019107').reload }
|
329
329
|
let(:details_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_running.json'))) }
|
330
330
|
let(:progress_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_running.json'))) }
|
331
331
|
# let(:reload_output) { [{ id: "510582971", url: "https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150609/48a6907086c012f68b9ca43461280515/1726d7ec3e24f2171bd07b2abb807b6c.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=vSvlxU94wlQLEbpG3Zs8ibp4MoY%3D&Expires=1433953106", label: nil }] }
|
data/spec/units/core_spec.rb
CHANGED
@@ -128,6 +128,7 @@ describe ActiveEncode::Core do
|
|
128
128
|
end
|
129
129
|
|
130
130
|
describe '#new' do
|
131
|
+
subject { encode.options }
|
131
132
|
before do
|
132
133
|
class DefaultOptionsEncode < ActiveEncode::Base
|
133
134
|
def self.default_options(_input_url)
|
@@ -139,7 +140,6 @@ describe ActiveEncode::Core do
|
|
139
140
|
Object.send(:remove_const, :DefaultOptionsEncode)
|
140
141
|
end
|
141
142
|
|
142
|
-
subject { encode.options }
|
143
143
|
let(:encode_class) { DefaultOptionsEncode }
|
144
144
|
let(:default_options) { { preset: 'video' } }
|
145
145
|
let(:options) { { output: [{ label: 'high', ffmpeg_opt: "640x480" }] } }
|
@@ -41,7 +41,7 @@ describe FileLocator, type: :service do
|
|
41
41
|
describe "Local file" do
|
42
42
|
let(:path) { "/path/to/file.mp4" }
|
43
43
|
let(:source) { "file://#{path}" }
|
44
|
-
let(:locator) {
|
44
|
+
let(:locator) { described_class.new(source) }
|
45
45
|
|
46
46
|
it "returns the correct uri" do
|
47
47
|
expect(locator.uri).to eq Addressable::URI.parse(source)
|
@@ -76,7 +76,7 @@ describe FileLocator, type: :service do
|
|
76
76
|
let(:bucket) { "mybucket" }
|
77
77
|
let(:key) { "mykey.mp4" }
|
78
78
|
let(:source) { "s3://#{bucket}/#{key}" }
|
79
|
-
let(:locator) {
|
79
|
+
let(:locator) { described_class.new(source) }
|
80
80
|
|
81
81
|
it "returns the correct uri" do
|
82
82
|
expect(locator.uri).to eq Addressable::URI.parse(source)
|
@@ -102,7 +102,7 @@ describe FileLocator, type: :service do
|
|
102
102
|
describe "Other file" do
|
103
103
|
let(:path) { "/path/to/file.mp4" }
|
104
104
|
let(:source) { "bogus://#{path}" }
|
105
|
-
let(:locator) {
|
105
|
+
let(:locator) { described_class.new(source) }
|
106
106
|
|
107
107
|
it "returns the correct uri" do
|
108
108
|
expect(locator.uri).to eq Addressable::URI.parse(source)
|
data/spec/units/status_spec.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe ActiveEncode::Status do
|
5
|
+
subject { encode_class.new(nil) }
|
5
6
|
before do
|
6
7
|
class CustomEncode < ActiveEncode::Base
|
7
8
|
end
|
@@ -10,7 +11,6 @@ describe ActiveEncode::Status do
|
|
10
11
|
Object.send(:remove_const, :CustomEncode)
|
11
12
|
end
|
12
13
|
|
13
|
-
subject { encode_class.new(nil) }
|
14
14
|
let(:encode_class) { ActiveEncode::Base }
|
15
15
|
|
16
16
|
describe 'attributes' do
|