active-encode 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +16 -0
  4. data/.travis.yml +10 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE +202 -0
  7. data/README.md +106 -0
  8. data/Rakefile +34 -0
  9. data/active-encode.gemspec +29 -0
  10. data/lib/active-encode.rb +1 -0
  11. data/lib/active_encode.rb +2 -0
  12. data/lib/active_encode/base.rb +16 -0
  13. data/lib/active_encode/callbacks.rb +69 -0
  14. data/lib/active_encode/core.rb +81 -0
  15. data/lib/active_encode/engine_adapter.rb +52 -0
  16. data/lib/active_encode/engine_adapters.rb +26 -0
  17. data/lib/active_encode/engine_adapters/active_job_adapter.rb +23 -0
  18. data/lib/active_encode/engine_adapters/inline_adapter.rb +42 -0
  19. data/lib/active_encode/engine_adapters/matterhorn_adapter.rb +290 -0
  20. data/lib/active_encode/engine_adapters/test_adapter.rb +38 -0
  21. data/lib/active_encode/engine_adapters/zencoder_adapter.rb +147 -0
  22. data/lib/active_encode/status.rb +38 -0
  23. data/lib/active_encode/technical_metadata.rb +11 -0
  24. data/lib/active_encode/version.rb +3 -0
  25. data/spec/fixtures/Bars_512kb.mp4 +0 -0
  26. data/spec/fixtures/matterhorn/cancelled_response.xml +323 -0
  27. data/spec/fixtures/matterhorn/completed_response.xml +4 -0
  28. data/spec/fixtures/matterhorn/create_response.xml +300 -0
  29. data/spec/fixtures/matterhorn/delete_track_response.xml +2 -0
  30. data/spec/fixtures/matterhorn/failed_response.xml +4 -0
  31. data/spec/fixtures/matterhorn/purged_response.xml +342 -0
  32. data/spec/fixtures/matterhorn/running_response.xml +1 -0
  33. data/spec/fixtures/matterhorn/stop_completed_response.xml +228 -0
  34. data/spec/fixtures/matterhorn/stop_running_response.xml +339 -0
  35. data/spec/fixtures/zencoder/job_create.json +1 -0
  36. data/spec/fixtures/zencoder/job_details_cancelled.json +1 -0
  37. data/spec/fixtures/zencoder/job_details_completed.json +1 -0
  38. data/spec/fixtures/zencoder/job_details_create.json +1 -0
  39. data/spec/fixtures/zencoder/job_details_failed.json +73 -0
  40. data/spec/fixtures/zencoder/job_details_running.json +1 -0
  41. data/spec/fixtures/zencoder/job_progress_cancelled.json +13 -0
  42. data/spec/fixtures/zencoder/job_progress_completed.json +13 -0
  43. data/spec/fixtures/zencoder/job_progress_create.json +1 -0
  44. data/spec/fixtures/zencoder/job_progress_failed.json +13 -0
  45. data/spec/fixtures/zencoder/job_progress_running.json +1 -0
  46. data/spec/integration/matterhorn_adapter_spec.rb +186 -0
  47. data/spec/integration/zencoder_adapter_spec.rb +153 -0
  48. data/spec/spec_helper.rb +12 -0
  49. data/spec/units/callbacks_spec.rb +67 -0
  50. data/spec/units/engine_adapter_spec.rb +68 -0
  51. data/spec/units/status_spec.rb +64 -0
  52. metadata +221 -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,13 @@
1
+ {
2
+ "state": "cancelled",
3
+ "input": {
4
+ "state": "cancelled",
5
+ "id": 165837500
6
+ },
7
+ "outputs": [
8
+ {
9
+ "state": "cancelled",
10
+ "id": 509953091
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "state": "finished",
3
+ "input": {
4
+ "state": "finished",
5
+ "id": 165810088
6
+ },
7
+ "outputs": [
8
+ {
9
+ "state": "finished",
10
+ "id": 509856876
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1 @@
1
+ {"state":"waiting", "input":{"state":"queued", "id":166179248}, "outputs":[{"state":"waiting", "id":511404522}]}
@@ -0,0 +1,13 @@
1
+ {
2
+ "state": "failed",
3
+ "input": {
4
+ "state": "failed",
5
+ "id": 166050851
6
+ },
7
+ "outputs": [
8
+ {
9
+ "state": "no_input",
10
+ "id": 510825144
11
+ }
12
+ ]
13
+ }
@@ -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 "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 'should remove 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,153 @@
1
+ require 'spec_helper'
2
+ require 'zencoder'
3
+ require 'json'
4
+
5
+ describe "ZencoderAdapter" do
6
+ before(:all) do
7
+ ActiveEncode::Base.engine_adapter = :zencoder
8
+ end
9
+ after(:all) do
10
+ ActiveEncode::Base.engine_adapter = :inline
11
+ end
12
+
13
+ let(:create_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_create.json'))) }
14
+
15
+ before do
16
+ allow(Zencoder::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(Zencoder::Job).to receive(:details).and_return(details_response)
24
+ allow(Zencoder::Job).to receive(:progress).and_return(progress_response)
25
+ end
26
+
27
+ let(:details_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_create.json'))) }
28
+ let(:progress_response) { Zencoder::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(Zencoder::Job).to receive(:details).and_return(details_response)
45
+ allow(Zencoder::Job).to receive(:progress).and_return(progress_response)
46
+ end
47
+
48
+ context "a running encode" do
49
+ let(:details_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_running.json'))) }
50
+ let(:progress_response) { Zencoder::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) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_cancelled.json'))) }
67
+ let(:progress_response) { Zencoder::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) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_completed.json'))) }
81
+ let(:progress_response) { Zencoder::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) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_failed.json'))) }
98
+ let(:progress_response) { Zencoder::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(Zencoder::Job).to receive(:cancel).and_return(cancel_response)
116
+ allow(Zencoder::Job).to receive(:details).and_return(details_response)
117
+ allow(Zencoder::Job).to receive(:progress).and_return(progress_response)
118
+ end
119
+
120
+ let(:cancel_response) { Zencoder::Response.new(code: 200) } #TODO check that this is the correct response code for a successful cancel
121
+ let(:details_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_cancelled.json'))) }
122
+ let(:progress_response) { Zencoder::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(Zencoder::Job).to receive(:details).and_return(details_response)
134
+ allow(Zencoder::Job).to receive(:progress).and_return(progress_response)
135
+ end
136
+
137
+ let(:details_response) { Zencoder::Response.new(body: JSON.parse(File.read('spec/fixtures/zencoder/job_details_running.json'))) }
138
+ let(:progress_response) { Zencoder::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
+
153
+ end