active_encode 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +16 -0
- data/.rubocop.yml +76 -0
- data/.travis.yml +10 -0
- data/Gemfile +11 -0
- data/LICENSE +202 -0
- data/README.md +106 -0
- data/Rakefile +38 -0
- data/active_encode.gemspec +28 -0
- data/lib/active_encode.rb +2 -0
- data/lib/active_encode/base.rb +16 -0
- data/lib/active_encode/callbacks.rb +69 -0
- data/lib/active_encode/core.rb +79 -0
- data/lib/active_encode/engine_adapter.rb +51 -0
- data/lib/active_encode/engine_adapters.rb +27 -0
- data/lib/active_encode/engine_adapters/active_job_adapter.rb +23 -0
- data/lib/active_encode/engine_adapters/inline_adapter.rb +42 -0
- data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +312 -0
- data/lib/active_encode/engine_adapters/shingoncoder_adapter.rb +56 -0
- data/lib/active_encode/engine_adapters/test_adapter.rb +38 -0
- data/lib/active_encode/engine_adapters/zencoder_adapter.rb +143 -0
- data/lib/active_encode/status.rb +38 -0
- data/lib/active_encode/technical_metadata.rb +11 -0
- data/lib/active_encode/version.rb +3 -0
- data/spec/fixtures/Bars_512kb.mp4 +0 -0
- data/spec/fixtures/matterhorn/cancelled_response.xml +323 -0
- data/spec/fixtures/matterhorn/completed_response.xml +4 -0
- data/spec/fixtures/matterhorn/create_response.xml +300 -0
- data/spec/fixtures/matterhorn/delete_track_response.xml +2 -0
- data/spec/fixtures/matterhorn/failed_response.xml +4 -0
- data/spec/fixtures/matterhorn/purged_response.xml +342 -0
- data/spec/fixtures/matterhorn/running_response.xml +1 -0
- data/spec/fixtures/matterhorn/stop_completed_response.xml +228 -0
- data/spec/fixtures/matterhorn/stop_running_response.xml +339 -0
- data/spec/fixtures/zencoder/job_create.json +1 -0
- data/spec/fixtures/zencoder/job_details_cancelled.json +1 -0
- data/spec/fixtures/zencoder/job_details_completed.json +1 -0
- data/spec/fixtures/zencoder/job_details_create.json +1 -0
- data/spec/fixtures/zencoder/job_details_failed.json +73 -0
- data/spec/fixtures/zencoder/job_details_running.json +1 -0
- data/spec/fixtures/zencoder/job_progress_cancelled.json +13 -0
- data/spec/fixtures/zencoder/job_progress_completed.json +13 -0
- data/spec/fixtures/zencoder/job_progress_create.json +1 -0
- data/spec/fixtures/zencoder/job_progress_failed.json +13 -0
- data/spec/fixtures/zencoder/job_progress_running.json +1 -0
- data/spec/integration/matterhorn_adapter_spec.rb +186 -0
- data/spec/integration/shingoncoder_adapter_spec.rb +152 -0
- data/spec/integration/zencoder_adapter_spec.rb +152 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/units/callbacks_spec.rb +66 -0
- data/spec/units/engine_adapter_spec.rb +78 -0
- data/spec/units/status_spec.rb +62 -0
- metadata +210 -0
@@ -0,0 +1 @@
|
|
1
|
+
{"id":166208299,"outputs":[{"id":511404522,"label":null,"url":"https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150610/c09b61e4d130ddf923f0653418a80b9c/399ae101c3f99b4f318635e78a4e587a.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=GY/9LMkQAiDOrMQwS5BkmOE200s%3D&Expires=1434033527"}],"test":true}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"job":{"created_at":"2015-06-08T20:43:23Z","finished_at":"2015-06-08T20:43:26Z","id":165866551,"pass_through":null,"privacy":true,"state":"cancelled","submitted_at":"2015-06-08T20:43:23Z","test":true,"updated_at":"2015-06-08T20:43:26Z","input_media_file":{"audio_bitrate_in_kbps":null,"audio_codec":null,"audio_sample_rate":null,"audio_tracks":null,"channels":null,"created_at":"2015-06-08T20:43:23Z","duration_in_ms":null,"error_class":null,"error_message":null,"file_size_bytes":null,"finished_at":"2015-06-08T20:43:26Z","format":null,"frame_rate":null,"height":null,"id":165837500,"md5_checksum":null,"privacy":true,"state":"cancelled","test":true,"updated_at":"2015-06-08T20:43:26Z","video_bitrate_in_kbps":null,"video_codec":null,"width":null,"total_bitrate_in_kbps":null,"url":"https://archive.org/download/LuckyStr1948_2/LuckyStr1948_2_512kb.mp4"},"output_media_files":[{"audio_bitrate_in_kbps":null,"audio_codec":null,"audio_sample_rate":null,"channels":null,"created_at":"2015-06-08T20:43:23Z","duration_in_ms":null,"error_class":null,"error_message":null,"file_size_bytes":null,"finished_at":"2015-06-08T20:43:26Z","format":null,"fragment_duration_in_ms":null,"frame_rate":null,"height":null,"id":509953091,"md5_checksum":null,"privacy":true,"rfc_6381_audio_codec":null,"rfc_6381_video_codec":null,"state":"cancelled","test":true,"updated_at":"2015-06-08T20:43:26Z","video_bitrate_in_kbps":null,"video_codec":null,"width":null,"label":null,"total_bitrate_in_kbps":null,"url":"https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150608/e652f8ae3c190bf8313689f6edb59d8a/30c0d19a6b96f79fc3ca48d222231e7a.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=IzDANlucJSKF5RGwk3S6ekN2pvU%3D&Expires=1433882606"}],"thumbnails":[]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"job":{"created_at":"2015-06-08T18:13:53Z","finished_at":"2015-06-08T18:14:06Z","id":165839139,"pass_through":null,"privacy":true,"state":"finished","submitted_at":"2015-06-08T18:13:53Z","test":true,"updated_at":"2015-06-08T18:14:06Z","input_media_file":{"audio_bitrate_in_kbps":52,"audio_codec":"aac","audio_sample_rate":44100,"audio_tracks":null,"channels":"2","created_at":"2015-06-08T18:13:53Z","duration_in_ms":57992,"error_class":null,"error_message":null,"file_size_bytes":4292486,"finished_at":"2015-06-08T18:13:59Z","format":"mpeg4","frame_rate":29.97,"height":240,"id":165810088,"md5_checksum":null,"privacy":true,"state":"finished","test":true,"updated_at":"2015-06-08T18:14:06Z","video_bitrate_in_kbps":535,"video_codec":"h264","width":320,"total_bitrate_in_kbps":587,"url":"https://archive.org/download/LuckyStr1948_2/LuckyStr1948_2_512kb.mp4"},"output_media_files":[{"audio_bitrate_in_kbps":53,"audio_codec":"aac","audio_sample_rate":44100,"channels":"2","created_at":"2015-06-08T18:13:53Z","duration_in_ms":5000,"error_class":null,"error_message":null,"file_size_bytes":382606,"finished_at":"2015-06-08T18:14:06Z","format":"mpeg4","fragment_duration_in_ms":null,"frame_rate":29.97,"height":240,"id":509856876,"md5_checksum":null,"privacy":true,"rfc_6381_audio_codec":"mp4a.40.2","rfc_6381_video_codec":"avc1.42000d","state":"finished","test":true,"updated_at":"2015-06-08T18:14:06Z","video_bitrate_in_kbps":549,"video_codec":"h264","width":320,"label":null,"total_bitrate_in_kbps":602,"url":"https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150608/ebbe865f8ef1b960d7c2bb0663b88a12/0f1948dcb2fd701fba30ff21908fe460.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=1LgIyl/el9E7zeyPxzd/%2BNwez6Y%3D&Expires=1433873646"}],"thumbnails":[]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"job":{"created_at":"2015-06-10T14:38:47Z","finished_at":null,"id":166208299,"pass_through":null,"privacy":true,"state":"waiting","submitted_at":"2015-06-10T14:38:47Z","test":true,"updated_at":"2015-06-10T14:38:47Z","input_media_file":{"audio_bitrate_in_kbps":null,"audio_codec":null,"audio_sample_rate":null,"audio_tracks":null,"channels":null,"created_at":"2015-06-10T14:38:47Z","duration_in_ms":null,"error_class":null,"error_message":null,"file_size_bytes":null,"finished_at":null,"format":null,"frame_rate":null,"height":null,"id":166179248,"md5_checksum":null,"privacy":true,"state":"assigning","test":true,"updated_at":"2015-06-10T14:38:00Z","video_bitrate_in_kbps":null,"video_codec":null,"width":null,"total_bitrate_in_kbps":null,"url":"https://archive.org/download/LuckyStr1948_2/LuckyStr1948_2_512kb.mp4"},"output_media_files":[{"audio_bitrate_in_kbps":null,"audio_codec":null,"audio_sample_rate":null,"channels":null,"created_at":"2015-06-10T14:38:47Z","duration_in_ms":null,"error_class":null,"error_message":null,"file_size_bytes":null,"finished_at":null,"format":null,"fragment_duration_in_ms":null,"frame_rate":null,"height":null,"id":511404522,"md5_checksum":null,"privacy":true,"rfc_6381_audio_codec":null,"rfc_6381_video_codec":null,"state":"waiting","test":true,"updated_at":"2015-06-10T14:38:47Z","video_bitrate_in_kbps":null,"video_codec":null,"width":null,"label":null,"total_bitrate_in_kbps":null,"url":"https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150610/c09b61e4d130ddf923f0653418a80b9c/399ae101c3f99b4f318635e78a4e587a.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=GY/9LMkQAiDOrMQwS5BkmOE200s%3D&Expires=1434033527"}],"thumbnails":[]}}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
{
|
2
|
+
"job": {
|
3
|
+
"created_at": "2015-06-09T20:52:57Z",
|
4
|
+
"finished_at": "2015-06-09T20:53:00Z",
|
5
|
+
"id": 166079902,
|
6
|
+
"pass_through": null,
|
7
|
+
"privacy": true,
|
8
|
+
"state": "failed",
|
9
|
+
"submitted_at": "2015-06-09T20:52:57Z",
|
10
|
+
"test": true,
|
11
|
+
"updated_at": "2015-06-09T20:53:00Z",
|
12
|
+
"input_media_file": {
|
13
|
+
"audio_bitrate_in_kbps": null,
|
14
|
+
"audio_codec": null,
|
15
|
+
"audio_sample_rate": null,
|
16
|
+
"audio_tracks": null,
|
17
|
+
"channels": null,
|
18
|
+
"created_at": "2015-06-09T20:52:57Z",
|
19
|
+
"duration_in_ms": null,
|
20
|
+
"error_class": "NoMediaError",
|
21
|
+
"error_message": "The file is an XML file, and doesn't contain audio or video tracks.",
|
22
|
+
"file_size_bytes": 20958,
|
23
|
+
"finished_at": "2015-06-09T20:53:00Z",
|
24
|
+
"format": null,
|
25
|
+
"frame_rate": null,
|
26
|
+
"height": null,
|
27
|
+
"id": 166050851,
|
28
|
+
"md5_checksum": null,
|
29
|
+
"privacy": true,
|
30
|
+
"state": "failed",
|
31
|
+
"test": true,
|
32
|
+
"updated_at": "2015-06-09T20:53:00Z",
|
33
|
+
"video_bitrate_in_kbps": null,
|
34
|
+
"video_codec": null,
|
35
|
+
"width": null,
|
36
|
+
"total_bitrate_in_kbps": null,
|
37
|
+
"url": "s3://zencoder-customer-ingest/uploads/2015-06-09/240330/187007/682c2d90-0eea-11e5-84c9-f158f44c3d50.xml"
|
38
|
+
},
|
39
|
+
"output_media_files": [
|
40
|
+
{
|
41
|
+
"audio_bitrate_in_kbps": null,
|
42
|
+
"audio_codec": null,
|
43
|
+
"audio_sample_rate": null,
|
44
|
+
"channels": null,
|
45
|
+
"created_at": "2015-06-09T20:52:58Z",
|
46
|
+
"duration_in_ms": null,
|
47
|
+
"error_class": null,
|
48
|
+
"error_message": null,
|
49
|
+
"file_size_bytes": null,
|
50
|
+
"finished_at": "2015-06-09T20:53:00Z",
|
51
|
+
"format": null,
|
52
|
+
"fragment_duration_in_ms": null,
|
53
|
+
"frame_rate": null,
|
54
|
+
"height": null,
|
55
|
+
"id": 510825144,
|
56
|
+
"md5_checksum": null,
|
57
|
+
"privacy": true,
|
58
|
+
"rfc_6381_audio_codec": null,
|
59
|
+
"rfc_6381_video_codec": null,
|
60
|
+
"state": "no_input",
|
61
|
+
"test": true,
|
62
|
+
"updated_at": "2015-06-09T20:53:00Z",
|
63
|
+
"video_bitrate_in_kbps": null,
|
64
|
+
"video_codec": null,
|
65
|
+
"width": null,
|
66
|
+
"label": null,
|
67
|
+
"total_bitrate_in_kbps": null,
|
68
|
+
"url": "https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150609/05ffd07679b503a7e4271fbbcb1e6c88/b5d45b56d60ca8e18682df8eaa82911d.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=WtWGTqMggZUc0GRgJoKAEf5OZP0%3D&Expires=1433969580"
|
69
|
+
}
|
70
|
+
],
|
71
|
+
"thumbnails": []
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"job":{"created_at":"2015-06-09T16:18:26Z", "finished_at":null, "id":166019107, "pass_through":null, "privacy":true, "state":"processing", "submitted_at":"2015-06-09T16:18:26Z", "test":true, "updated_at":"2015-06-09T16:18:28Z", "input_media_file":{"audio_bitrate_in_kbps":52, "audio_codec":"aac", "audio_sample_rate":44100, "audio_tracks":null, "channels":"2", "created_at":"2015-06-09T16:18:26Z", "duration_in_ms":57992, "error_class":null, "error_message":null, "file_size_bytes":4292486, "finished_at":"2015-06-09T16:18:32Z", "format":"mpeg4", "frame_rate":29.97, "height":240, "id":165990056, "md5_checksum":null, "privacy":true, "state":"finished", "test":true, "updated_at":"2015-06-09T16:18:32Z", "video_bitrate_in_kbps":535, "video_codec":"h264", "width":320, "total_bitrate_in_kbps":587, "url":"https://archive.org/download/LuckyStr1948_2/LuckyStr1948_2_512kb.mp4"}, "output_media_files":[{"audio_bitrate_in_kbps":null, "audio_codec":null, "audio_sample_rate":null, "channels":null, "created_at":"2015-06-09T16:18:26Z", "duration_in_ms":null, "error_class":null, "error_message":null, "file_size_bytes":null, "finished_at":null, "format":null, "fragment_duration_in_ms":null, "frame_rate":null, "height":null, "id":510582971, "md5_checksum":null, "privacy":true, "rfc_6381_audio_codec":null, "rfc_6381_video_codec":null, "state":"ready", "test":true, "updated_at":"2015-06-09T16:18:32Z", "video_bitrate_in_kbps":null, "video_codec":null, "width":null, "label":null, "total_bitrate_in_kbps":null, "url":"https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150609/48a6907086c012f68b9ca43461280515/1726d7ec3e24f2171bd07b2abb807b6c.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=vSvlxU94wlQLEbpG3Zs8ibp4MoY%3D&Expires=1433953106"}], "thumbnails":[]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"state":"waiting", "input":{"state":"queued", "id":166179248}, "outputs":[{"state":"waiting", "id":511404522}]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"state":"processing", "progress":30.0, "input":{"state":"finished", "id":165990056}, "outputs":[{"state":"processing", "id":510582971}]}
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rubyhorn'
|
3
|
+
|
4
|
+
describe ActiveEncode::EngineAdapters::MatterhornAdapter do
|
5
|
+
before(:all) do
|
6
|
+
Rubyhorn.init(environment: 'test')
|
7
|
+
ActiveEncode::Base.engine_adapter = :matterhorn
|
8
|
+
end
|
9
|
+
after(:all) do
|
10
|
+
ActiveEncode::Base.engine_adapter = :inline
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
# Stub out all Matterhorn interactions
|
15
|
+
allow(Rubyhorn).to receive(:client).and_return(double("Rubyhorn::MatterhornClient"))
|
16
|
+
allow(Rubyhorn.client).to receive(:addMediaPackageWithUrl).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/create_response.xml')))
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:file) { "file://#{File.absolute_path('spec/fixtures/Bars_512kb.mp4')}" }
|
20
|
+
|
21
|
+
describe "#create" do
|
22
|
+
subject { ActiveEncode::Base.create(file) }
|
23
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
24
|
+
its(:id) { is_expected.not_to be_empty }
|
25
|
+
it { is_expected.to be_running }
|
26
|
+
its(:output) { is_expected.to be_empty }
|
27
|
+
its(:options) { is_expected.to include(preset: 'full') }
|
28
|
+
its(:current_operations) { is_expected.to be_empty }
|
29
|
+
its(:percent_complete) { is_expected.to eq 0 }
|
30
|
+
its(:errors) { is_expected.to be_empty }
|
31
|
+
its(:tech_metadata) { is_expected.to be_empty }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#find" do
|
35
|
+
context "a running encode" do
|
36
|
+
before do
|
37
|
+
allow(Rubyhorn.client).to receive(:instance_xml).with('running-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/running_response.xml')))
|
38
|
+
end
|
39
|
+
|
40
|
+
subject { ActiveEncode::Base.find('running-id') }
|
41
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
42
|
+
its(:id) { is_expected.to eq 'running-id' }
|
43
|
+
it { is_expected.to be_running }
|
44
|
+
its(:output) { is_expected.to be_empty }
|
45
|
+
its(:options) { is_expected.to include(preset: 'full') }
|
46
|
+
its(:current_operations) { is_expected.to include("Hold for workflow selection") }
|
47
|
+
its(:percent_complete) { is_expected.to eq 0.43478260869565216 }
|
48
|
+
its(:errors) { is_expected.to be_empty }
|
49
|
+
its(:tech_metadata) { is_expected.to be_empty }
|
50
|
+
end
|
51
|
+
context "a cancelled encode" do
|
52
|
+
before do
|
53
|
+
allow(Rubyhorn.client).to receive(:instance_xml).with('cancelled-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
|
54
|
+
end
|
55
|
+
|
56
|
+
subject { ActiveEncode::Base.find('cancelled-id') }
|
57
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
58
|
+
its(:id) { is_expected.to eq 'cancelled-id' }
|
59
|
+
it { is_expected.to be_cancelled }
|
60
|
+
its(:options) { is_expected.to include(preset: 'full') }
|
61
|
+
its(:current_operations) { is_expected.to include("Tagging dublin core catalogs for publishing") }
|
62
|
+
its(:percent_complete) { is_expected.to eq 1.7391304347826086 }
|
63
|
+
its(:errors) { is_expected.to be_empty }
|
64
|
+
its(:tech_metadata) { is_expected.to be_empty }
|
65
|
+
end
|
66
|
+
context "a completed encode" do
|
67
|
+
before do
|
68
|
+
allow(Rubyhorn.client).to receive(:instance_xml).with('completed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/completed_response.xml')))
|
69
|
+
end
|
70
|
+
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" }] }
|
71
|
+
|
72
|
+
subject { ActiveEncode::Base.find('completed-id') }
|
73
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
74
|
+
its(:id) { is_expected.to eq 'completed-id' }
|
75
|
+
it { is_expected.to be_completed }
|
76
|
+
its(:output) { is_expected.to eq completed_output }
|
77
|
+
its(:options) { is_expected.to include(preset: 'avalon') }
|
78
|
+
its(:current_operations) { is_expected.to include("Cleaning up") }
|
79
|
+
its(:percent_complete) { is_expected.to eq 100 }
|
80
|
+
its(:errors) { is_expected.to be_empty }
|
81
|
+
its(:tech_metadata) { is_expected.to be_empty }
|
82
|
+
end
|
83
|
+
context "a failed encode" do
|
84
|
+
before do
|
85
|
+
allow(Rubyhorn.client).to receive(:instance_xml).with('failed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/failed_response.xml')))
|
86
|
+
end
|
87
|
+
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" } }
|
88
|
+
let(:failed_errors) { "org.opencastproject.workflow.api.WorkflowOperationException: org.opencastproject.workflow.api.WorkflowOperationException: One of the encoding jobs did not complete successfully" }
|
89
|
+
|
90
|
+
subject { ActiveEncode::Base.find('failed-id') }
|
91
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
92
|
+
its(:id) { is_expected.to eq 'failed-id' }
|
93
|
+
it { is_expected.to be_failed }
|
94
|
+
its(:options) { is_expected.to include(preset: 'error') }
|
95
|
+
its(:current_operations) { is_expected.to include("Cleaning up after failure") }
|
96
|
+
its(:percent_complete) { is_expected.to eq 56.666666666666664 }
|
97
|
+
its(:errors) { is_expected.to include failed_errors }
|
98
|
+
its(:tech_metadata) { is_expected.to include failed_tech_metadata }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#cancel!" do
|
103
|
+
before do
|
104
|
+
allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
|
105
|
+
end
|
106
|
+
let(:encode) { ActiveEncode::Base.create(file) }
|
107
|
+
subject { encode.cancel! }
|
108
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
109
|
+
its(:id) { is_expected.to eq 'cancelled-id' }
|
110
|
+
it { is_expected.to be_cancelled }
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "#purge!" do
|
114
|
+
context "when encode is running" do
|
115
|
+
before do
|
116
|
+
allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/stop_running_response.xml')))
|
117
|
+
allow(Rubyhorn.client).to receive(:delete_track).and_return('http://localhost:8080/services/job/1234.xml')
|
118
|
+
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'))
|
119
|
+
end
|
120
|
+
let(:encode) { ActiveEncode::Base.create(file) }
|
121
|
+
subject { encode.purge! }
|
122
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
123
|
+
its(:id) { is_expected.to eq 'stopped-running-id' }
|
124
|
+
it { is_expected.to be_cancelled }
|
125
|
+
its(:output) { is_expected.to be_empty }
|
126
|
+
end
|
127
|
+
|
128
|
+
context "when encode is cancelled" do
|
129
|
+
before do
|
130
|
+
allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
|
131
|
+
# allow(Rubyhorn.client).to receive(:get_stopped_workflow).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
|
132
|
+
end
|
133
|
+
let(:encode) { ActiveEncode::Base.create(file).cancel! }
|
134
|
+
subject { encode.purge! }
|
135
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
136
|
+
its(:id) { is_expected.to eq 'cancelled-id' }
|
137
|
+
it { is_expected.to be_cancelled }
|
138
|
+
its(:output) { is_expected.to be_empty }
|
139
|
+
end
|
140
|
+
context "when encode is completed" do
|
141
|
+
before do
|
142
|
+
allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/stop_completed_response.xml')))
|
143
|
+
allow(Rubyhorn.client).to receive(:delete_track).and_return('http://localhost:8080/services/job/1234.xml')
|
144
|
+
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'))
|
145
|
+
end
|
146
|
+
let(:encode) { ActiveEncode::Base.create(file).cancel! }
|
147
|
+
subject { encode.purge! }
|
148
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
149
|
+
its(:id) { is_expected.to eq 'stop-completed-id' }
|
150
|
+
it { is_expected.to be_cancelled }
|
151
|
+
its(:output) { is_expected.to be_empty }
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "reload" do
|
156
|
+
before do
|
157
|
+
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')))
|
158
|
+
end
|
159
|
+
|
160
|
+
subject { ActiveEncode::Base.find('running-id').reload }
|
161
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
162
|
+
its(:id) { is_expected.to eq 'running-id' }
|
163
|
+
it { is_expected.to be_running }
|
164
|
+
its(:output) { is_expected.to be_empty }
|
165
|
+
its(:options) { is_expected.to include(preset: 'full') }
|
166
|
+
its(:current_operations) { is_expected.to include("Hold for workflow selection") }
|
167
|
+
its(:percent_complete) { is_expected.to eq 0.43478260869565216 }
|
168
|
+
its(:errors) { is_expected.to be_empty }
|
169
|
+
its(:tech_metadata) { is_expected.to be_empty }
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "remove_output" do
|
173
|
+
before do
|
174
|
+
allow(Rubyhorn.client).to receive(:instance_xml).with('completed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/completed_response.xml')))
|
175
|
+
allow(Rubyhorn.client).to receive(:delete_track).and_return('http://localhost:8080/services/job/1234.xml')
|
176
|
+
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'))
|
177
|
+
end
|
178
|
+
let(:encode) { ActiveEncode::Base.find('completed-id') }
|
179
|
+
subject { encode.remove_output! 'track-7' }
|
180
|
+
it { is_expected.to be_a Hash }
|
181
|
+
it 'removes the output' do
|
182
|
+
encode.remove_output!('track-7')
|
183
|
+
expect(ActiveEncode::Base.find(encode.id).output.find { |o| o[:id] == 'track-7' }).to be_nil
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shingoncoder'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
describe ActiveEncode::EngineAdapters::ShingoncoderAdapter do
|
6
|
+
before(:all) do
|
7
|
+
ActiveEncode::Base.engine_adapter = :shingoncoder
|
8
|
+
end
|
9
|
+
after(:all) do
|
10
|
+
ActiveEncode::Base.engine_adapter = :inline
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:create_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_create.json'))) }
|
14
|
+
|
15
|
+
before do
|
16
|
+
allow(Shingoncoder::Job).to receive(:create).and_return(create_response)
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:file) { "file://#{File.absolute_path('spec/fixtures/Bars_512kb.mp4')}" }
|
20
|
+
|
21
|
+
describe "#create" do
|
22
|
+
before do
|
23
|
+
allow(Shingoncoder::Job).to receive(:details).and_return(details_response)
|
24
|
+
allow(Shingoncoder::Job).to receive(:progress).and_return(progress_response)
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:details_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_create.json'))) }
|
28
|
+
let(:progress_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_create.json'))) }
|
29
|
+
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 }] }
|
30
|
+
|
31
|
+
subject { ActiveEncode::Base.create(file) }
|
32
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
33
|
+
its(:id) { is_expected.not_to be_empty }
|
34
|
+
it { is_expected.to be_running }
|
35
|
+
its(:output) { is_expected.to eq create_output }
|
36
|
+
its(:current_operations) { is_expected.to be_empty }
|
37
|
+
its(:percent_complete) { is_expected.to eq 0 }
|
38
|
+
its(:errors) { is_expected.to be_empty }
|
39
|
+
its(:tech_metadata) { is_expected.to be_empty }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#find" do
|
43
|
+
before do
|
44
|
+
allow(Shingoncoder::Job).to receive(:details).and_return(details_response)
|
45
|
+
allow(Shingoncoder::Job).to receive(:progress).and_return(progress_response)
|
46
|
+
end
|
47
|
+
|
48
|
+
context "a running encode" do
|
49
|
+
let(:details_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_running.json'))) }
|
50
|
+
let(:progress_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_running.json'))) }
|
51
|
+
let(:running_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 }] }
|
52
|
+
let(:running_tech_metadata) { { audio_bitrate: "52", audio_codec: "aac", audio_channels: "2", duration: "57992", mime_type: "mpeg4", video_framerate: "29.97", height: "240", video_bitrate: "535", video_codec: "h264", width: "320" } }
|
53
|
+
|
54
|
+
subject { ActiveEncode::Base.find('166019107') }
|
55
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
56
|
+
its(:id) { is_expected.to eq '166019107' }
|
57
|
+
it { is_expected.to be_running }
|
58
|
+
its(:output) { is_expected.to eq running_output }
|
59
|
+
its(:current_operations) { is_expected.to be_empty }
|
60
|
+
its(:percent_complete) { is_expected.to eq 30.0 }
|
61
|
+
its(:errors) { is_expected.to be_empty }
|
62
|
+
its(:tech_metadata) { is_expected.to eq running_tech_metadata }
|
63
|
+
end
|
64
|
+
|
65
|
+
context "a cancelled encode" do
|
66
|
+
let(:details_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_cancelled.json'))) }
|
67
|
+
let(:progress_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_cancelled.json'))) }
|
68
|
+
|
69
|
+
subject { ActiveEncode::Base.find('165866551') }
|
70
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
71
|
+
its(:id) { is_expected.to eq '165866551' }
|
72
|
+
it { is_expected.to be_cancelled }
|
73
|
+
its(:current_operations) { is_expected.to be_empty }
|
74
|
+
its(:percent_complete) { is_expected.to eq 0 }
|
75
|
+
its(:errors) { is_expected.to be_empty }
|
76
|
+
its(:tech_metadata) { is_expected.to be_empty }
|
77
|
+
end
|
78
|
+
|
79
|
+
context "a completed encode" do
|
80
|
+
let(:details_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_completed.json'))) }
|
81
|
+
let(:progress_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_completed.json'))) }
|
82
|
+
let(:completed_output) { { id: "509856876", audio_bitrate: "53", audio_codec: "aac", audio_channels: "2", duration: "5000", mime_type: "mpeg4", video_framerate: "29.97", height: "240", video_bitrate: "549", video_codec: "h264", width: "320", url: "https://zencoder-temp-storage-us-east-1.s3.amazonaws.com/o/20150608/ebbe865f8ef1b960d7c2bb0663b88a12/0f1948dcb2fd701fba30ff21908fe460.mp4?AWSAccessKeyId=AKIAI456JQ76GBU7FECA&Signature=1LgIyl/el9E7zeyPxzd/%2BNwez6Y%3D&Expires=1433873646", label: nil } }
|
83
|
+
let(:completed_tech_metadata) { { audio_bitrate: "52", audio_codec: "aac", audio_channels: "2", duration: "57992", mime_type: "mpeg4", video_framerate: "29.97", height: "240", video_bitrate: "535", video_codec: "h264", width: "320" } }
|
84
|
+
|
85
|
+
subject { ActiveEncode::Base.find('165839139') }
|
86
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
87
|
+
its(:id) { is_expected.to eq '165839139' }
|
88
|
+
it { is_expected.to be_completed }
|
89
|
+
its(:output) { is_expected.to include completed_output }
|
90
|
+
its(:current_operations) { is_expected.to be_empty }
|
91
|
+
its(:percent_complete) { is_expected.to eq 100 }
|
92
|
+
its(:errors) { is_expected.to be_empty }
|
93
|
+
its(:tech_metadata) { is_expected.to eq completed_tech_metadata }
|
94
|
+
end
|
95
|
+
|
96
|
+
context "a failed encode" do
|
97
|
+
let(:details_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_failed.json'))) }
|
98
|
+
let(:progress_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_failed.json'))) }
|
99
|
+
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" } }
|
100
|
+
let(:failed_errors) { "The file is an XML file, and doesn't contain audio or video tracks." }
|
101
|
+
|
102
|
+
subject { ActiveEncode::Base.find('166079902') }
|
103
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
104
|
+
its(:id) { is_expected.to eq '166079902' }
|
105
|
+
it { is_expected.to be_failed }
|
106
|
+
its(:current_operations) { is_expected.to be_empty }
|
107
|
+
its(:percent_complete) { is_expected.to eq 0 }
|
108
|
+
its(:errors) { is_expected.to include failed_errors }
|
109
|
+
its(:tech_metadata) { is_expected.to be_empty }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "#cancel!" do
|
114
|
+
before do
|
115
|
+
allow(Shingoncoder::Job).to receive(:cancel).and_return(cancel_response)
|
116
|
+
allow(Shingoncoder::Job).to receive(:details).and_return(details_response)
|
117
|
+
allow(Shingoncoder::Job).to receive(:progress).and_return(progress_response)
|
118
|
+
end
|
119
|
+
|
120
|
+
let(:cancel_response) { Shingoncoder::Response.new(code: 200) } # TODO: check that this is the correct response code for a successful cancel
|
121
|
+
let(:details_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_cancelled.json'))) }
|
122
|
+
let(:progress_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_cancelled.json'))) }
|
123
|
+
|
124
|
+
let(:encode) { ActiveEncode::Base.create(file) }
|
125
|
+
subject { encode.cancel! }
|
126
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
127
|
+
its(:id) { is_expected.to eq '165866551' }
|
128
|
+
it { is_expected.to be_cancelled }
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "reload" do
|
132
|
+
before do
|
133
|
+
allow(Shingoncoder::Job).to receive(:details).and_return(details_response)
|
134
|
+
allow(Shingoncoder::Job).to receive(:progress).and_return(progress_response)
|
135
|
+
end
|
136
|
+
|
137
|
+
let(:details_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_running.json'))) }
|
138
|
+
let(:progress_response) { Shingoncoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_progress_running.json'))) }
|
139
|
+
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 }] }
|
140
|
+
let(:reload_tech_metadata) { { audio_bitrate: "52", audio_codec: "aac", audio_channels: "2", duration: "57992", mime_type: "mpeg4", video_framerate: "29.97", height: "240", video_bitrate: "535", video_codec: "h264", width: "320" } }
|
141
|
+
|
142
|
+
subject { ActiveEncode::Base.find('166019107').reload }
|
143
|
+
it { is_expected.to be_a ActiveEncode::Base }
|
144
|
+
its(:id) { is_expected.to eq '166019107' }
|
145
|
+
it { is_expected.to be_running }
|
146
|
+
its(:output) { is_expected.to eq reload_output }
|
147
|
+
its(:current_operations) { is_expected.to be_empty }
|
148
|
+
its(:percent_complete) { is_expected.to eq 30.0 }
|
149
|
+
its(:errors) { is_expected.to be_empty }
|
150
|
+
its(:tech_metadata) { is_expected.to eq reload_tech_metadata }
|
151
|
+
end
|
152
|
+
end
|