active_encode 0.2 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +9 -0
- data/README.md +1 -16
- data/active_encode.gemspec +4 -4
- data/app/jobs/active_encode/polling_job.rb +4 -4
- data/lib/active_encode/callbacks.rb +2 -21
- data/lib/active_encode/core.rb +1 -35
- data/lib/active_encode/engine_adapters.rb +1 -3
- data/lib/active_encode/engine_adapters/elastic_transcoder_adapter.rb +32 -28
- data/lib/active_encode/engine_adapters/ffmpeg_adapter.rb +243 -0
- data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +64 -97
- data/lib/active_encode/engine_adapters/test_adapter.rb +0 -12
- data/lib/active_encode/engine_adapters/zencoder_adapter.rb +53 -44
- data/lib/active_encode/input.rb +6 -0
- data/lib/active_encode/output.rb +7 -0
- data/lib/active_encode/persistence.rb +1 -1
- data/lib/active_encode/polling.rb +2 -2
- data/lib/active_encode/status.rb +0 -3
- data/lib/active_encode/technical_metadata.rb +7 -0
- data/lib/active_encode/version.rb +1 -1
- data/spec/fixtures/ffmpeg/cancelled-id/error.log +0 -0
- data/spec/fixtures/ffmpeg/cancelled-id/input_metadata +90 -0
- data/spec/fixtures/ffmpeg/cancelled-id/pid +1 -0
- data/spec/fixtures/ffmpeg/cancelled-id/progress +11 -0
- data/spec/fixtures/ffmpeg/completed-id/error.log +0 -0
- data/spec/fixtures/ffmpeg/completed-id/input_metadata +102 -0
- data/spec/fixtures/ffmpeg/completed-id/output_metadata-high +90 -0
- data/spec/fixtures/ffmpeg/completed-id/output_metadata-low +90 -0
- data/spec/fixtures/ffmpeg/completed-id/pid +1 -0
- data/spec/fixtures/ffmpeg/completed-id/progress +11 -0
- data/spec/fixtures/ffmpeg/completed-id/video-high.mp4 +0 -0
- data/spec/fixtures/ffmpeg/completed-id/video-low.mp4 +0 -0
- data/spec/fixtures/ffmpeg/failed-id/error.log +1 -0
- data/spec/fixtures/ffmpeg/failed-id/input_metadata +90 -0
- data/spec/fixtures/ffmpeg/failed-id/pid +1 -0
- data/spec/fixtures/ffmpeg/failed-id/progress +11 -0
- data/spec/fixtures/ffmpeg/running-id/error.log +0 -0
- data/spec/fixtures/ffmpeg/running-id/input_metadata +90 -0
- data/spec/fixtures/ffmpeg/running-id/pid +1 -0
- data/spec/fixtures/ffmpeg/running-id/progress +11 -0
- data/spec/fixtures/fireworks.mp4 +0 -0
- data/spec/integration/elastic_transcoder_adapter_spec.rb +21 -12
- data/spec/integration/ffmpeg_adapter_spec.rb +120 -0
- data/spec/integration/matterhorn_adapter_spec.rb +30 -59
- data/spec/integration/zencoder_adapter_spec.rb +242 -22
- data/spec/shared_specs/engine_adapter_specs.rb +116 -16
- data/spec/units/core_spec.rb +31 -0
- data/spec/units/input_spec.rb +25 -0
- data/spec/units/output_spec.rb +28 -1
- data/spec/units/polling_job_spec.rb +10 -10
- metadata +51 -11
- data/lib/active_encode/engine_adapters/active_job_adapter.rb +0 -21
- data/lib/active_encode/engine_adapters/inline_adapter.rb +0 -47
- data/lib/active_encode/engine_adapters/shingoncoder_adapter.rb +0 -63
- data/spec/integration/shingoncoder_adapter_spec.rb +0 -170
@@ -0,0 +1 @@
|
|
1
|
+
99999
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
Some error
|
@@ -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="file:///Bars_512kb.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>24876</FileSize>
|
17
|
+
<Duration>4.928</Duration>
|
18
|
+
<OverallBitRate_Mode>VBR</OverallBitRate_Mode>
|
19
|
+
<OverallBitRate>40383</OverallBitRate>
|
20
|
+
<FrameRate>1.000</FrameRate>
|
21
|
+
<FrameCount>1</FrameCount>
|
22
|
+
<StreamSize>3216</StreamSize>
|
23
|
+
<HeaderSize>3208</HeaderSize>
|
24
|
+
<DataSize>21668</DataSize>
|
25
|
+
<FooterSize>0</FooterSize>
|
26
|
+
<IsStreamable>Yes</IsStreamable>
|
27
|
+
<Title>Bars - http://www.archive.org/details/ColorBarsWTone</Title>
|
28
|
+
<Movie>Bars - http://www.archive.org/details/ColorBarsWTone</Movie>
|
29
|
+
<Recorded_Date>2008</Recorded_Date>
|
30
|
+
<Encoded_Date>UTC 1970-01-01 00:00:00</Encoded_Date>
|
31
|
+
<Tagged_Date>UTC 2008-11-23 18:44:25</Tagged_Date>
|
32
|
+
<Encoded_Application>Lavf51.10.0</Encoded_Application>
|
33
|
+
<Comment>license: http://creativecommons.org/licenses/publicdomain/</Comment>
|
34
|
+
</track>
|
35
|
+
<track type="Video">
|
36
|
+
<StreamOrder>0</StreamOrder>
|
37
|
+
<ID>1</ID>
|
38
|
+
<Format>AVC</Format>
|
39
|
+
<Format_Profile>Baseline</Format_Profile>
|
40
|
+
<Format_Level>1.3</Format_Level>
|
41
|
+
<Format_Settings_CABAC>No</Format_Settings_CABAC>
|
42
|
+
<Format_Settings_RefFrames>1</Format_Settings_RefFrames>
|
43
|
+
<CodecID>avc1</CodecID>
|
44
|
+
<Duration>1.000</Duration>
|
45
|
+
<BitRate>18504</BitRate>
|
46
|
+
<Width>360</Width>
|
47
|
+
<Height>240</Height>
|
48
|
+
<Stored_Width>368</Stored_Width>
|
49
|
+
<Sampled_Width>360</Sampled_Width>
|
50
|
+
<Sampled_Height>240</Sampled_Height>
|
51
|
+
<PixelAspectRatio>1.000</PixelAspectRatio>
|
52
|
+
<DisplayAspectRatio>1.500</DisplayAspectRatio>
|
53
|
+
<Rotation>0.000</Rotation>
|
54
|
+
<FrameRate_Mode>CFR</FrameRate_Mode>
|
55
|
+
<FrameRate>1.000</FrameRate>
|
56
|
+
<FrameRate_Original>0.200</FrameRate_Original>
|
57
|
+
<FrameCount>1</FrameCount>
|
58
|
+
<ColorSpace>YUV</ColorSpace>
|
59
|
+
<ChromaSubsampling>4:2:0</ChromaSubsampling>
|
60
|
+
<BitDepth>8</BitDepth>
|
61
|
+
<ScanType>Progressive</ScanType>
|
62
|
+
<StreamSize>2313</StreamSize>
|
63
|
+
<Encoded_Date>UTC 1970-01-01 00:00:00</Encoded_Date>
|
64
|
+
<Tagged_Date>UTC 1970-01-01 00:00:00</Tagged_Date>
|
65
|
+
</track>
|
66
|
+
<track type="Audio">
|
67
|
+
<StreamOrder>1</StreamOrder>
|
68
|
+
<ID>2</ID>
|
69
|
+
<Format>AAC</Format>
|
70
|
+
<Format_Profile>LC</Format_Profile>
|
71
|
+
<CodecID>mp4a-40-2</CodecID>
|
72
|
+
<Duration>4.928</Duration>
|
73
|
+
<BitRate_Mode>VBR</BitRate_Mode>
|
74
|
+
<BitRate>31407</BitRate>
|
75
|
+
<Channels>2</Channels>
|
76
|
+
<ChannelPositions>Front: L R</ChannelPositions>
|
77
|
+
<ChannelLayout>L R</ChannelLayout>
|
78
|
+
<SamplesPerFrame>1024</SamplesPerFrame>
|
79
|
+
<SamplingRate>48000</SamplingRate>
|
80
|
+
<SamplingCount>236544</SamplingCount>
|
81
|
+
<FrameRate>46.875</FrameRate>
|
82
|
+
<FrameCount>231</FrameCount>
|
83
|
+
<Compression_Mode>Lossy</Compression_Mode>
|
84
|
+
<StreamSize>19347</StreamSize>
|
85
|
+
<StreamSize_Proportion>0.77774</StreamSize_Proportion>
|
86
|
+
<Encoded_Date>UTC 1970-01-01 00:00:00</Encoded_Date>
|
87
|
+
<Tagged_Date>UTC 1970-01-01 00:00:00</Tagged_Date>
|
88
|
+
</track>
|
89
|
+
</media>
|
90
|
+
</MediaInfo>
|
@@ -0,0 +1 @@
|
|
1
|
+
99999
|
File without changes
|
@@ -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="file:///Bars_512kb.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>24876</FileSize>
|
17
|
+
<Duration>4.928</Duration>
|
18
|
+
<OverallBitRate_Mode>VBR</OverallBitRate_Mode>
|
19
|
+
<OverallBitRate>40383</OverallBitRate>
|
20
|
+
<FrameRate>1.000</FrameRate>
|
21
|
+
<FrameCount>1</FrameCount>
|
22
|
+
<StreamSize>3216</StreamSize>
|
23
|
+
<HeaderSize>3208</HeaderSize>
|
24
|
+
<DataSize>21668</DataSize>
|
25
|
+
<FooterSize>0</FooterSize>
|
26
|
+
<IsStreamable>Yes</IsStreamable>
|
27
|
+
<Title>Bars - http://www.archive.org/details/ColorBarsWTone</Title>
|
28
|
+
<Movie>Bars - http://www.archive.org/details/ColorBarsWTone</Movie>
|
29
|
+
<Recorded_Date>2008</Recorded_Date>
|
30
|
+
<Encoded_Date>UTC 1970-01-01 00:00:00</Encoded_Date>
|
31
|
+
<Tagged_Date>UTC 2008-11-23 18:44:25</Tagged_Date>
|
32
|
+
<Encoded_Application>Lavf51.10.0</Encoded_Application>
|
33
|
+
<Comment>license: http://creativecommons.org/licenses/publicdomain/</Comment>
|
34
|
+
</track>
|
35
|
+
<track type="Video">
|
36
|
+
<StreamOrder>0</StreamOrder>
|
37
|
+
<ID>1</ID>
|
38
|
+
<Format>AVC</Format>
|
39
|
+
<Format_Profile>Baseline</Format_Profile>
|
40
|
+
<Format_Level>1.3</Format_Level>
|
41
|
+
<Format_Settings_CABAC>No</Format_Settings_CABAC>
|
42
|
+
<Format_Settings_RefFrames>1</Format_Settings_RefFrames>
|
43
|
+
<CodecID>avc1</CodecID>
|
44
|
+
<Duration>1.000</Duration>
|
45
|
+
<BitRate>18504</BitRate>
|
46
|
+
<Width>360</Width>
|
47
|
+
<Height>240</Height>
|
48
|
+
<Stored_Width>368</Stored_Width>
|
49
|
+
<Sampled_Width>360</Sampled_Width>
|
50
|
+
<Sampled_Height>240</Sampled_Height>
|
51
|
+
<PixelAspectRatio>1.000</PixelAspectRatio>
|
52
|
+
<DisplayAspectRatio>1.500</DisplayAspectRatio>
|
53
|
+
<Rotation>0.000</Rotation>
|
54
|
+
<FrameRate_Mode>CFR</FrameRate_Mode>
|
55
|
+
<FrameRate>1.000</FrameRate>
|
56
|
+
<FrameRate_Original>0.200</FrameRate_Original>
|
57
|
+
<FrameCount>1</FrameCount>
|
58
|
+
<ColorSpace>YUV</ColorSpace>
|
59
|
+
<ChromaSubsampling>4:2:0</ChromaSubsampling>
|
60
|
+
<BitDepth>8</BitDepth>
|
61
|
+
<ScanType>Progressive</ScanType>
|
62
|
+
<StreamSize>2313</StreamSize>
|
63
|
+
<Encoded_Date>UTC 1970-01-01 00:00:00</Encoded_Date>
|
64
|
+
<Tagged_Date>UTC 1970-01-01 00:00:00</Tagged_Date>
|
65
|
+
</track>
|
66
|
+
<track type="Audio">
|
67
|
+
<StreamOrder>1</StreamOrder>
|
68
|
+
<ID>2</ID>
|
69
|
+
<Format>AAC</Format>
|
70
|
+
<Format_Profile>LC</Format_Profile>
|
71
|
+
<CodecID>mp4a-40-2</CodecID>
|
72
|
+
<Duration>4.928</Duration>
|
73
|
+
<BitRate_Mode>VBR</BitRate_Mode>
|
74
|
+
<BitRate>31407</BitRate>
|
75
|
+
<Channels>2</Channels>
|
76
|
+
<ChannelPositions>Front: L R</ChannelPositions>
|
77
|
+
<ChannelLayout>L R</ChannelLayout>
|
78
|
+
<SamplesPerFrame>1024</SamplesPerFrame>
|
79
|
+
<SamplingRate>48000</SamplingRate>
|
80
|
+
<SamplingCount>236544</SamplingCount>
|
81
|
+
<FrameRate>46.875</FrameRate>
|
82
|
+
<FrameCount>231</FrameCount>
|
83
|
+
<Compression_Mode>Lossy</Compression_Mode>
|
84
|
+
<StreamSize>19347</StreamSize>
|
85
|
+
<StreamSize_Proportion>0.77774</StreamSize_Proportion>
|
86
|
+
<Encoded_Date>UTC 1970-01-01 00:00:00</Encoded_Date>
|
87
|
+
<Tagged_Date>UTC 1970-01-01 00:00:00</Tagged_Date>
|
88
|
+
</track>
|
89
|
+
</media>
|
90
|
+
</MediaInfo>
|
@@ -0,0 +1 @@
|
|
1
|
+
99999
|
Binary file
|
@@ -90,38 +90,47 @@ describe ActiveEncode::EngineAdapters::ElasticTranscoderAdapter do
|
|
90
90
|
ActiveEncode::Base.find('failed-id')
|
91
91
|
end
|
92
92
|
|
93
|
-
let(:completed_output) { [{id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a",
|
94
|
-
let(:completed_tech_metadata) { {:width=>1280, :height=>720, :
|
93
|
+
let(:completed_output) { [{ id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a", label: "hls0400k", :width=>400, :height=>224, :frame_rate=>25, :file_size=>6901104, :duration=>117353 }] }
|
94
|
+
let(:completed_tech_metadata) { { :width=>1280, :height=>720, :frame_rate=>25, :file_size=>21069678, :duration=>117312 } }
|
95
95
|
let(:failed_tech_metadata) { {} }
|
96
96
|
|
97
97
|
it_behaves_like "an ActiveEncode::EngineAdapter"
|
98
98
|
|
99
99
|
describe "#create" do
|
100
|
-
let(:create_output) { [{id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a",
|
100
|
+
let(:create_output) { [{ id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a", label: "hls0400k" }] }
|
101
101
|
|
102
102
|
subject { created_job }
|
103
103
|
|
104
104
|
it { is_expected.to be_running }
|
105
|
-
its(:output) { is_expected.to eq create_output }
|
106
105
|
its(:current_operations) { is_expected.to be_empty }
|
106
|
+
|
107
|
+
it 'output has technical metadata' do
|
108
|
+
subject.output.each do |output|
|
109
|
+
expected_output = create_output.find {|expected_out| expected_out[:id] == output.id }
|
110
|
+
expect(output.as_json.symbolize_keys).to include expected_output
|
111
|
+
end
|
112
|
+
end
|
107
113
|
end
|
108
114
|
|
109
115
|
describe "#find" do
|
110
116
|
context "a running encode" do
|
111
|
-
let(:running_output) { [{id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a",
|
112
|
-
let(:running_tech_metadata) { {:width=>1280, :height=>720, :
|
117
|
+
let(:running_output) { [{ id: "2", url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a", label: "hls0400k" }] }
|
118
|
+
let(:running_tech_metadata) { {:width=>1280, :height=>720, :frame_rate=>25, :file_size=>21069678, :duration=>117312} }
|
113
119
|
|
114
120
|
subject { running_job }
|
115
121
|
|
116
|
-
its(:output) { is_expected.to eq running_output }
|
117
122
|
its(:current_operations) { is_expected.to be_empty }
|
118
|
-
its(:tech_metadata) { is_expected.to eq running_tech_metadata }
|
119
|
-
end
|
120
123
|
|
121
|
-
|
122
|
-
|
124
|
+
it 'input has technical metadata' do
|
125
|
+
expect(subject.input.as_json.symbolize_keys).to include running_tech_metadata
|
126
|
+
end
|
123
127
|
|
124
|
-
|
128
|
+
it 'output has technical metadata' do
|
129
|
+
subject.output.each do |output|
|
130
|
+
expected_output = running_output.find {|expected_out| expected_out[:id] == output.id }
|
131
|
+
expect(output.as_json.symbolize_keys).to include expected_output
|
132
|
+
end
|
133
|
+
end
|
125
134
|
end
|
126
135
|
end
|
127
136
|
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shared_specs/engine_adapter_specs'
|
3
|
+
|
4
|
+
describe ActiveEncode::EngineAdapters::FfmpegAdapter do
|
5
|
+
around(:example) do |example|
|
6
|
+
ActiveEncode::Base.engine_adapter = :ffmpeg
|
7
|
+
|
8
|
+
Dir.mktmpdir do |dir|
|
9
|
+
@dir = dir
|
10
|
+
example.run
|
11
|
+
end
|
12
|
+
|
13
|
+
ActiveEncode::Base.engine_adapter = :test
|
14
|
+
end
|
15
|
+
|
16
|
+
let!(:work_dir) { stub_const "ActiveEncode::EngineAdapters::FfmpegAdapter::WORK_DIR", @dir }
|
17
|
+
let(:file) { "file://#{File.absolute_path "spec/fixtures/fireworks.mp4"}" }
|
18
|
+
let(:created_job) do
|
19
|
+
ActiveEncode::Base.create(file, { outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: "mp4"}, { label: "high", ffmpeg_opt: "-s 1280x720", extension: "mp4"}] })
|
20
|
+
end
|
21
|
+
let(:running_job) do
|
22
|
+
allow(Process).to receive(:getpgid).and_return 8888
|
23
|
+
find_encode "running-id"
|
24
|
+
end
|
25
|
+
let(:canceled_job) do
|
26
|
+
find_encode 'cancelled-id'
|
27
|
+
end
|
28
|
+
let(:cancelling_job) do
|
29
|
+
allow(Process).to receive(:kill).and_return(nil)
|
30
|
+
find_encode 'running-id'
|
31
|
+
end
|
32
|
+
let(:completed_job) { find_encode "completed-id" }
|
33
|
+
let(:failed_job) { find_encode 'failed-id' }
|
34
|
+
let(:completed_tech_metadata) { {:audio_bitrate => 171030,
|
35
|
+
:audio_codec => 'mp4a-40-2',
|
36
|
+
:duration => 6.315,
|
37
|
+
:file_size => 199160,
|
38
|
+
:frame_rate => 23.719,
|
39
|
+
:height => 110.0,
|
40
|
+
:id => "99999",
|
41
|
+
:url => "/home/pdinh/Downloads/videoshort.mp4",
|
42
|
+
:video_bitrate => 74477,
|
43
|
+
:video_codec => 'avc1',
|
44
|
+
:width => 200.0
|
45
|
+
} }
|
46
|
+
let(:completed_output) { [{ id: "99999" }] }
|
47
|
+
let(:failed_tech_metadata) { { } }
|
48
|
+
|
49
|
+
it_behaves_like "an ActiveEncode::EngineAdapter"
|
50
|
+
|
51
|
+
def find_encode id
|
52
|
+
# Precreate ffmpeg output directory and files
|
53
|
+
FileUtils.copy_entry "spec/fixtures/ffmpeg/#{id}", "#{work_dir}/#{id}"
|
54
|
+
|
55
|
+
# Simulate that progress is modified later than other files
|
56
|
+
sleep 0.1
|
57
|
+
FileUtils.touch "#{work_dir}/#{id}/progress"
|
58
|
+
FileUtils.touch Dir.glob("#{work_dir}/#{id}/*.mp4")
|
59
|
+
|
60
|
+
# # Stub out system calls
|
61
|
+
allow_any_instance_of(ActiveEncode::EngineAdapters::FfmpegAdapter).to receive(:`).and_return(1234)
|
62
|
+
|
63
|
+
ActiveEncode::Base.find(id)
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#create" do
|
67
|
+
subject { created_job }
|
68
|
+
|
69
|
+
it "creates a directory whose name is the encode id" do
|
70
|
+
expect(File).to exist("#{work_dir}/#{subject.id}")
|
71
|
+
end
|
72
|
+
|
73
|
+
context "input file exists" do
|
74
|
+
it "has the input technical metadata in a file" do
|
75
|
+
expect(File.read("#{work_dir}/#{subject.id}/input_metadata")).not_to be_empty
|
76
|
+
end
|
77
|
+
|
78
|
+
it "has the pid in a file" do
|
79
|
+
expect(File.read("#{work_dir}/#{subject.id}/pid")).not_to be_empty
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "input file doesn't exist" do
|
84
|
+
let(:missing_file) { "file:///a_bogus_file.mp4" }
|
85
|
+
let(:missing_job) { ActiveEncode::Base.create(missing_file, { outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]}) }
|
86
|
+
|
87
|
+
it "returns the encode with correct error" do
|
88
|
+
expect(missing_job.errors).to include("#{missing_file} does not exist or is not accessible")
|
89
|
+
expect(missing_job.percent_complete).to be 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "input file is not media" do
|
94
|
+
let(:nonmedia_file) { "file://#{File.absolute_path "spec/integration/ffmpeg_adapter_spec.rb"}" }
|
95
|
+
let(:nonmedia_job) { ActiveEncode::Base.create(nonmedia_file, { outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]}) }
|
96
|
+
|
97
|
+
it "returns the encode with correct error" do
|
98
|
+
expect(nonmedia_job.errors).to include("Error inspecting input: #{nonmedia_file}")
|
99
|
+
expect(nonmedia_job.percent_complete).to be 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#find" do
|
105
|
+
subject { running_job }
|
106
|
+
|
107
|
+
it "has a progress file" do
|
108
|
+
expect(File).to exist("#{work_dir}/#{subject.id}/progress")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#cancel!" do
|
113
|
+
subject { running_job }
|
114
|
+
|
115
|
+
it "stops a running process" do
|
116
|
+
expect(Process).to receive(:kill).with('SIGTERM', running_job.input.id.to_i)
|
117
|
+
running_job.cancel!
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -30,9 +30,9 @@ describe ActiveEncode::EngineAdapters::MatterhornAdapter do
|
|
30
30
|
let(:completed_job) { ActiveEncode::Base.find('completed-id') }
|
31
31
|
let(:failed_job) { ActiveEncode::Base.find('failed-id') }
|
32
32
|
|
33
|
-
let(:completed_output) { [{ id: "track-7",
|
33
|
+
let(:completed_output) { [{ id: "track-7", checksum: "77de9765545ef63d2c21f7557ead6176", duration: 6337, audio_codec: "AAC", audio_bitrate: 76502.0, video_codec: "AVC", video_bitrate: 2000000.0, frame_rate: 30.0, width: 1308, height: 720, url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/b09c765f-b64e-4725-a863-736af66b688c/videoshort.mp4", label: "quality-high" }, { id: "track-8", checksum: "10e13cf51bf8a973011eec6a17ea47ff", duration: 6337, audio_codec: "AAC", audio_bitrate: 76502.0, video_codec: "AVC", video_bitrate: 500000.0, frame_rate: 30.0, width: 654, height: 360, url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/8d5cd8a9-ad0e-484a-96f0-05e26a84a8f0/videoshort.mp4", label: "quality-low" }, { id: "track-9", checksum: "f2b16a2606dc76cb53c7017f0e166204", duration: 6337, audio_codec: "AAC", audio_bitrate: 76502.0, video_codec: "AVC", video_bitrate: 1000000.0, frame_rate: 30.0, width: 872, height: 480, url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/0f81d426-0e26-4496-8f58-c675c86e6f4e/videoshort.mp4", label: "quality-medium" }] }
|
34
34
|
let(:completed_tech_metadata) { { } }
|
35
|
-
let(:failed_tech_metadata) { {
|
35
|
+
let(:failed_tech_metadata) { { checksum: "7ae24368ccb7a6c6422a14ff73f33c9a", duration: 6314, audio_codec: "AAC", audio_bitrate: 171030.0, video_codec: "AVC", video_bitrate: 74477.0, frame_rate: 23.719, width: 200, height: 110 } }
|
36
36
|
let(:failed_errors) { "org.opencastproject.workflow.api.WorkflowOperationException: org.opencastproject.workflow.api.WorkflowOperationException: One of the encoding jobs did not complete successfully" }
|
37
37
|
|
38
38
|
# Enforce generic behavior
|
@@ -52,7 +52,21 @@ describe ActiveEncode::EngineAdapters::MatterhornAdapter do
|
|
52
52
|
its(:options) { is_expected.to include(preset: 'full') }
|
53
53
|
its(:output) { is_expected.to be_empty }
|
54
54
|
its(:current_operations) { is_expected.to include("Hold for workflow selection") }
|
55
|
-
|
55
|
+
|
56
|
+
context 'input' do
|
57
|
+
subject { running_job.input }
|
58
|
+
|
59
|
+
its(:width) { is_expected.to be_blank }
|
60
|
+
its(:height) { is_expected.to be_blank }
|
61
|
+
its(:frame_rate) { is_expected.to be_blank }
|
62
|
+
its(:duration) { is_expected.to be_blank }
|
63
|
+
its(:file_size) { is_expected.to be_blank }
|
64
|
+
its(:checksum) { is_expected.to be_blank }
|
65
|
+
its(:audio_codec) { is_expected.to be_blank }
|
66
|
+
its(:video_codec) { is_expected.to be_blank }
|
67
|
+
its(:audio_bitrate) { is_expected.to be_blank }
|
68
|
+
its(:video_bitrate) { is_expected.to be_blank }
|
69
|
+
end
|
56
70
|
end
|
57
71
|
context "a cancelled encode" do
|
58
72
|
subject { canceled_job }
|
@@ -86,48 +100,6 @@ describe ActiveEncode::EngineAdapters::MatterhornAdapter do
|
|
86
100
|
it { is_expected.to be_cancelled }
|
87
101
|
end
|
88
102
|
|
89
|
-
describe "#purge!" do
|
90
|
-
context "when encode is running" do
|
91
|
-
before do
|
92
|
-
allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/stop_running_response.xml')))
|
93
|
-
allow(Rubyhorn.client).to receive(:delete_track).and_return('http://localhost:8080/services/job/1234.xml')
|
94
|
-
allow(Rubyhorn.client).to receive(:get).with('/services/job/1234.xml').and_return(File.open('spec/fixtures/matterhorn/delete_track_response.xml'), File.open('spec/fixtures/matterhorn/delete_track_response.xml'), File.open('spec/fixtures/matterhorn/delete_track_response.xml'))
|
95
|
-
end
|
96
|
-
let(:encode) { ActiveEncode::Base.create(file) }
|
97
|
-
subject { encode.purge! }
|
98
|
-
it { is_expected.to be_a ActiveEncode::Base }
|
99
|
-
its(:id) { is_expected.to eq 'stopped-running-id' }
|
100
|
-
it { is_expected.to be_cancelled }
|
101
|
-
its(:output) { is_expected.to be_empty }
|
102
|
-
end
|
103
|
-
|
104
|
-
context "when encode is cancelled" do
|
105
|
-
before do
|
106
|
-
allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
|
107
|
-
# allow(Rubyhorn.client).to receive(:get_stopped_workflow).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
|
108
|
-
end
|
109
|
-
let(:encode) { ActiveEncode::Base.create(file).cancel! }
|
110
|
-
subject { encode.purge! }
|
111
|
-
it { is_expected.to be_a ActiveEncode::Base }
|
112
|
-
its(:id) { is_expected.to eq 'cancelled-id' }
|
113
|
-
it { is_expected.to be_cancelled }
|
114
|
-
its(:output) { is_expected.to be_empty }
|
115
|
-
end
|
116
|
-
context "when encode is completed" do
|
117
|
-
before do
|
118
|
-
allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/stop_completed_response.xml')))
|
119
|
-
allow(Rubyhorn.client).to receive(:delete_track).and_return('http://localhost:8080/services/job/1234.xml')
|
120
|
-
allow(Rubyhorn.client).to receive(:get).with('/services/job/1234.xml').and_return(File.open('spec/fixtures/matterhorn/delete_track_response.xml'), File.open('spec/fixtures/matterhorn/delete_track_response.xml'), File.open('spec/fixtures/matterhorn/delete_track_response.xml'))
|
121
|
-
end
|
122
|
-
let(:encode) { ActiveEncode::Base.create(file).cancel! }
|
123
|
-
subject { encode.purge! }
|
124
|
-
it { is_expected.to be_a ActiveEncode::Base }
|
125
|
-
its(:id) { is_expected.to eq 'stop-completed-id' }
|
126
|
-
it { is_expected.to be_cancelled }
|
127
|
-
its(:output) { is_expected.to be_empty }
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
103
|
describe "reload" do
|
132
104
|
before do
|
133
105
|
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')))
|
@@ -139,21 +111,20 @@ describe ActiveEncode::EngineAdapters::MatterhornAdapter do
|
|
139
111
|
its(:options) { is_expected.to include(preset: 'full') }
|
140
112
|
its(:current_operations) { is_expected.to include("Hold for workflow selection") }
|
141
113
|
its(:percent_complete) { is_expected.to eq 0.43478260869565216 }
|
142
|
-
its(:tech_metadata) { is_expected.to be_empty }
|
143
|
-
end
|
144
114
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
115
|
+
context 'input' do
|
116
|
+
subject { running_job.reload.input }
|
117
|
+
|
118
|
+
its(:width) { is_expected.to be_blank }
|
119
|
+
its(:height) { is_expected.to be_blank }
|
120
|
+
its(:frame_rate) { is_expected.to be_blank }
|
121
|
+
its(:duration) { is_expected.to be_blank }
|
122
|
+
its(:file_size) { is_expected.to be_blank }
|
123
|
+
its(:checksum) { is_expected.to be_blank }
|
124
|
+
its(:audio_codec) { is_expected.to be_blank }
|
125
|
+
its(:video_codec) { is_expected.to be_blank }
|
126
|
+
its(:audio_bitrate) { is_expected.to be_blank }
|
127
|
+
its(:video_bitrate) { is_expected.to be_blank }
|
157
128
|
end
|
158
129
|
end
|
159
130
|
end
|