active_encode 0.2 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -0
  3. data/README.md +1 -16
  4. data/active_encode.gemspec +4 -4
  5. data/app/jobs/active_encode/polling_job.rb +4 -4
  6. data/lib/active_encode/callbacks.rb +2 -21
  7. data/lib/active_encode/core.rb +1 -35
  8. data/lib/active_encode/engine_adapters.rb +1 -3
  9. data/lib/active_encode/engine_adapters/elastic_transcoder_adapter.rb +32 -28
  10. data/lib/active_encode/engine_adapters/ffmpeg_adapter.rb +243 -0
  11. data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +64 -97
  12. data/lib/active_encode/engine_adapters/test_adapter.rb +0 -12
  13. data/lib/active_encode/engine_adapters/zencoder_adapter.rb +53 -44
  14. data/lib/active_encode/input.rb +6 -0
  15. data/lib/active_encode/output.rb +7 -0
  16. data/lib/active_encode/persistence.rb +1 -1
  17. data/lib/active_encode/polling.rb +2 -2
  18. data/lib/active_encode/status.rb +0 -3
  19. data/lib/active_encode/technical_metadata.rb +7 -0
  20. data/lib/active_encode/version.rb +1 -1
  21. data/spec/fixtures/ffmpeg/cancelled-id/error.log +0 -0
  22. data/spec/fixtures/ffmpeg/cancelled-id/input_metadata +90 -0
  23. data/spec/fixtures/ffmpeg/cancelled-id/pid +1 -0
  24. data/spec/fixtures/ffmpeg/cancelled-id/progress +11 -0
  25. data/spec/fixtures/ffmpeg/completed-id/error.log +0 -0
  26. data/spec/fixtures/ffmpeg/completed-id/input_metadata +102 -0
  27. data/spec/fixtures/ffmpeg/completed-id/output_metadata-high +90 -0
  28. data/spec/fixtures/ffmpeg/completed-id/output_metadata-low +90 -0
  29. data/spec/fixtures/ffmpeg/completed-id/pid +1 -0
  30. data/spec/fixtures/ffmpeg/completed-id/progress +11 -0
  31. data/spec/fixtures/ffmpeg/completed-id/video-high.mp4 +0 -0
  32. data/spec/fixtures/ffmpeg/completed-id/video-low.mp4 +0 -0
  33. data/spec/fixtures/ffmpeg/failed-id/error.log +1 -0
  34. data/spec/fixtures/ffmpeg/failed-id/input_metadata +90 -0
  35. data/spec/fixtures/ffmpeg/failed-id/pid +1 -0
  36. data/spec/fixtures/ffmpeg/failed-id/progress +11 -0
  37. data/spec/fixtures/ffmpeg/running-id/error.log +0 -0
  38. data/spec/fixtures/ffmpeg/running-id/input_metadata +90 -0
  39. data/spec/fixtures/ffmpeg/running-id/pid +1 -0
  40. data/spec/fixtures/ffmpeg/running-id/progress +11 -0
  41. data/spec/fixtures/fireworks.mp4 +0 -0
  42. data/spec/integration/elastic_transcoder_adapter_spec.rb +21 -12
  43. data/spec/integration/ffmpeg_adapter_spec.rb +120 -0
  44. data/spec/integration/matterhorn_adapter_spec.rb +30 -59
  45. data/spec/integration/zencoder_adapter_spec.rb +242 -22
  46. data/spec/shared_specs/engine_adapter_specs.rb +116 -16
  47. data/spec/units/core_spec.rb +31 -0
  48. data/spec/units/input_spec.rb +25 -0
  49. data/spec/units/output_spec.rb +28 -1
  50. data/spec/units/polling_job_spec.rb +10 -10
  51. metadata +51 -11
  52. data/lib/active_encode/engine_adapters/active_job_adapter.rb +0 -21
  53. data/lib/active_encode/engine_adapters/inline_adapter.rb +0 -47
  54. data/lib/active_encode/engine_adapters/shingoncoder_adapter.rb +0 -63
  55. data/spec/integration/shingoncoder_adapter_spec.rb +0 -170
@@ -0,0 +1 @@
1
+ 99999
@@ -0,0 +1,11 @@
1
+ frame=150
2
+ fps=0.0
3
+ stream_0_0_q=-1.0
4
+ bitrate= 158.9kbits/s
5
+ total_size=125403
6
+ out_time_ms=6314667
7
+ out_time=00:00:06.314667
8
+ dup_frames=1
9
+ drop_frames=0
10
+ speed=43.1x
11
+ progress=end
@@ -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
@@ -0,0 +1,11 @@
1
+ frame=56
2
+ fps=0.0
3
+ stream_0_0_q=0.0
4
+ bitrate= 0.1kbits/s
5
+ total_size=52
6
+ out_time_ms=3459773
7
+ out_time=00:00:03.459773
8
+ dup_frames=0
9
+ drop_frames=0
10
+ speed= 6.8x
11
+ progress=continue
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
@@ -0,0 +1,11 @@
1
+ frame=56
2
+ fps=0.0
3
+ stream_0_0_q=0.0
4
+ bitrate= 0.1kbits/s
5
+ total_size=52
6
+ out_time_ms=3459773
7
+ out_time=00:00:03.459773
8
+ dup_frames=0
9
+ drop_frames=0
10
+ speed= 6.8x
11
+ progress=continue
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", hls_url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a.m3u8", label: "hls0400k", :width=>400, :height=>224, :video_framerate=>"25", :file_size=>6901104, :duration=>"117353", :segment_duration=> "2.0"}] }
94
- let(:completed_tech_metadata) { {:width=>1280, :height=>720, :video_framerate=>"25", :file_size=>21069678, :duration=>"117312"} }
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", hls_url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a.m3u8", label: "hls0400k", segment_duration: "2.0"}] }
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", hls_url: "elastic-transcoder-samples/output/hls/hls0400k/e8fe80f5b7063b12d567b90c0bdf6322116bba11ac458fe9d62921644159fe4a.m3u8", label: "hls0400k", :segment_duration=>"2.0"}] }
112
- let(:running_tech_metadata) { {:width=>1280, :height=>720, :video_framerate=>"25", :file_size=>21069678, :duration=>"117312"} }
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
- context "a canceled encode" do
122
- subject { canceled_job }
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
- its(:updated_at) { is_expected.to be_nil }
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", mime_type: "video/mp4", checksum: "77de9765545ef63d2c21f7557ead6176", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "2000000.0", video_framerate: "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", mime_type: "video/mp4", checksum: "10e13cf51bf8a973011eec6a17ea47ff", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "500000.0", video_framerate: "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", mime_type: "video/mp4", checksum: "f2b16a2606dc76cb53c7017f0e166204", duration: "6337", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "76502.0", video_codec: "AVC", video_bitrate: "1000000.0", video_framerate: "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" }] }
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) { { mime_type: "video/mp4", checksum: "7ae24368ccb7a6c6422a14ff73f33c9a", duration: "6314", audio_codec: "AAC", audio_channels: "2", audio_bitrate: "171030.0", video_codec: "AVC", video_bitrate: "74477.0", video_framerate: "23.719", width: "200", height: "110" } }
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
- its(:tech_metadata) { is_expected.to be_empty }
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
- describe "remove_output" do
146
- before do
147
- allow(Rubyhorn.client).to receive(:instance_xml).with('completed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/completed_response.xml')))
148
- allow(Rubyhorn.client).to receive(:delete_track).and_return('http://localhost:8080/services/job/1234.xml')
149
- 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'))
150
- end
151
- let(:encode) { ActiveEncode::Base.find('completed-id') }
152
- subject { encode.remove_output! 'track-7' }
153
- it { is_expected.to be_a Hash }
154
- it 'removes the output' do
155
- encode.remove_output!('track-7')
156
- expect(ActiveEncode::Base.find(encode.id).output.find { |o| o[:id] == 'track-7' }).to be_nil
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