active_encode 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +16 -0
  4. data/.rubocop.yml +76 -0
  5. data/.travis.yml +10 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE +202 -0
  8. data/README.md +106 -0
  9. data/Rakefile +38 -0
  10. data/active_encode.gemspec +28 -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 +79 -0
  15. data/lib/active_encode/engine_adapter.rb +51 -0
  16. data/lib/active_encode/engine_adapters.rb +27 -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 +312 -0
  20. data/lib/active_encode/engine_adapters/shingoncoder_adapter.rb +56 -0
  21. data/lib/active_encode/engine_adapters/test_adapter.rb +38 -0
  22. data/lib/active_encode/engine_adapters/zencoder_adapter.rb +143 -0
  23. data/lib/active_encode/status.rb +38 -0
  24. data/lib/active_encode/technical_metadata.rb +11 -0
  25. data/lib/active_encode/version.rb +3 -0
  26. data/spec/fixtures/Bars_512kb.mp4 +0 -0
  27. data/spec/fixtures/matterhorn/cancelled_response.xml +323 -0
  28. data/spec/fixtures/matterhorn/completed_response.xml +4 -0
  29. data/spec/fixtures/matterhorn/create_response.xml +300 -0
  30. data/spec/fixtures/matterhorn/delete_track_response.xml +2 -0
  31. data/spec/fixtures/matterhorn/failed_response.xml +4 -0
  32. data/spec/fixtures/matterhorn/purged_response.xml +342 -0
  33. data/spec/fixtures/matterhorn/running_response.xml +1 -0
  34. data/spec/fixtures/matterhorn/stop_completed_response.xml +228 -0
  35. data/spec/fixtures/matterhorn/stop_running_response.xml +339 -0
  36. data/spec/fixtures/zencoder/job_create.json +1 -0
  37. data/spec/fixtures/zencoder/job_details_cancelled.json +1 -0
  38. data/spec/fixtures/zencoder/job_details_completed.json +1 -0
  39. data/spec/fixtures/zencoder/job_details_create.json +1 -0
  40. data/spec/fixtures/zencoder/job_details_failed.json +73 -0
  41. data/spec/fixtures/zencoder/job_details_running.json +1 -0
  42. data/spec/fixtures/zencoder/job_progress_cancelled.json +13 -0
  43. data/spec/fixtures/zencoder/job_progress_completed.json +13 -0
  44. data/spec/fixtures/zencoder/job_progress_create.json +1 -0
  45. data/spec/fixtures/zencoder/job_progress_failed.json +13 -0
  46. data/spec/fixtures/zencoder/job_progress_running.json +1 -0
  47. data/spec/integration/matterhorn_adapter_spec.rb +186 -0
  48. data/spec/integration/shingoncoder_adapter_spec.rb +152 -0
  49. data/spec/integration/zencoder_adapter_spec.rb +152 -0
  50. data/spec/spec_helper.rb +12 -0
  51. data/spec/units/callbacks_spec.rb +66 -0
  52. data/spec/units/engine_adapter_spec.rb +78 -0
  53. data/spec/units/status_spec.rb +62 -0
  54. metadata +210 -0
@@ -0,0 +1,56 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+
4
+ module ActiveEncode
5
+ module EngineAdapters
6
+ class ShingoncoderAdapter < ZencoderAdapter
7
+ # @param [ActiveEncode::Base] encode
8
+ def create(encode)
9
+ response = Shingoncoder::Job.create(input: encode.input)
10
+ build_encode(job_details(response.body["id"]), encode.class)
11
+ end
12
+
13
+ # @param [Fixnum] id
14
+ # @param [Hash] opts
15
+ # @option opts :cast the class to cast the encoding job to.
16
+ def find(id, opts = {})
17
+ build_encode(job_details(id), opts[:cast])
18
+ end
19
+
20
+ # @param [ActiveEncode::Base] encode
21
+ def cancel(encode)
22
+ response = Shingoncoder::Job.cancel(encode.id)
23
+ build_encode(job_details(encode.id), encode.class) if response.success?
24
+ end
25
+
26
+ private
27
+
28
+ # @param [Fixnum] job_id the identifier for the job
29
+ # @return [Shingoncoder::Response] the response from Shingoncoder
30
+ def job_details(job_id)
31
+ Shingoncoder::Job.details(job_id)
32
+ end
33
+
34
+ # @return [Shingoncoder::Response] the response from Shingoncoder
35
+ def job_progress(job_id)
36
+ Shingoncoder::Job.progress(job_id)
37
+ end
38
+
39
+ # @param [Shingoncoder::Response] job_details
40
+ # @param [Class] cast the class of object to instantiate and return
41
+ def build_encode(job_details, cast)
42
+ return nil if job_details.nil?
43
+ encode = cast.new(convert_input(job_details), convert_options(job_details))
44
+ encode.id = job_details.body["job"]["id"].to_s
45
+ encode.state = convert_state(job_details)
46
+ progress = job_progress(encode.id)
47
+ encode.current_operations = convert_current_operations(progress)
48
+ encode.percent_complete = convert_percent_complete(progress, job_details)
49
+ encode.output = convert_output(job_details)
50
+ encode.errors = convert_errors(job_details)
51
+ encode.tech_metadata = convert_tech_metadata(job_details.body["job"]["input_media_file"])
52
+ encode
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,38 @@
1
+ module ActiveEncode
2
+ module EngineAdapters
3
+ class TestAdapter
4
+ def initialize
5
+ @encodes = {}
6
+ end
7
+
8
+ def create(encode)
9
+ encode.id = SecureRandom.uuid
10
+ @encodes[encode.id] = encode
11
+ encode.state = :running
12
+ encode
13
+ end
14
+
15
+ def find(id, _opts = {})
16
+ @encodes[id]
17
+ end
18
+
19
+ def list(*_filters)
20
+ fail NotImplementedError
21
+ end
22
+
23
+ def cancel(encode)
24
+ e = @encodes[encode.id]
25
+ e.state = :cancelled
26
+ e
27
+ end
28
+
29
+ def purge(encode)
30
+ @encodes.delete(encode.id)
31
+ end
32
+
33
+ def remove_output(_encode, _output_id)
34
+ fail NotImplementedError
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,143 @@
1
+ module ActiveEncode
2
+ module EngineAdapters
3
+ class ZencoderAdapter
4
+ # TODO: add a stub for an input helper (supplied by an initializer) that transforms encode.input into a zencoder accepted url
5
+ def create(encode)
6
+ response = Zencoder::Job.create(input: "#{encode.input}")
7
+ build_encode(get_job_details(response.body["id"]), encode.class)
8
+ end
9
+
10
+ def find(id, opts = {})
11
+ build_encode(get_job_details(id), opts[:cast])
12
+ end
13
+
14
+ def list(*_filters)
15
+ fail NotImplementedError
16
+ end
17
+
18
+ def cancel(encode)
19
+ response = Zencoder::Job.cancel(encode.id)
20
+ build_encode(get_job_details(encode.id), encode.class) if response.success?
21
+ end
22
+
23
+ def purge(_encode)
24
+ fail NotImplementedError
25
+ end
26
+
27
+ def remove_output(_encode, _output_id)
28
+ fail NotImplementedError
29
+ end
30
+
31
+ private
32
+
33
+ def get_job_details(job_id)
34
+ Zencoder::Job.details(job_id)
35
+ end
36
+
37
+ def get_job_progress(job_id)
38
+ Zencoder::Job.progress(job_id)
39
+ end
40
+
41
+ def build_encode(job_details, cast)
42
+ return nil if job_details.nil?
43
+ encode = cast.new(convert_input(job_details), convert_options(job_details))
44
+ encode.id = job_details.body["job"]["id"].to_s
45
+ encode.state = convert_state(job_details)
46
+ job_progress = get_job_progress(encode.id)
47
+ encode.current_operations = convert_current_operations(job_progress)
48
+ encode.percent_complete = convert_percent_complete(job_progress, job_details)
49
+ encode.output = convert_output(job_details)
50
+ encode.errors = convert_errors(job_details)
51
+ encode.tech_metadata = convert_tech_metadata(job_details.body["job"]["input_media_file"])
52
+ encode
53
+ end
54
+
55
+ def convert_state(job_details)
56
+ case job_details.body["job"]["state"]
57
+ when "pending", "waiting", "processing" # Should there be a queued state?
58
+ :running
59
+ when "cancelled"
60
+ :cancelled
61
+ when "failed"
62
+ :failed
63
+ when "finished"
64
+ :completed
65
+ end
66
+ end
67
+
68
+ def convert_current_operations(job_progress)
69
+ current_ops = []
70
+ job_progress.body["outputs"].each { |output| current_ops << output["current_event"] unless output["current_event"].nil? }
71
+ current_ops
72
+ end
73
+
74
+ def convert_percent_complete(job_progress, job_details)
75
+ percent = job_progress.body["progress"]
76
+ percent ||= 100 if convert_state(job_details) == :completed
77
+ percent ||= 0
78
+ percent
79
+ end
80
+
81
+ def convert_input(job_details)
82
+ job_details.body["job"]["input_media_file"]["url"]
83
+ end
84
+
85
+ def convert_options(_job_details)
86
+ {}
87
+ end
88
+
89
+ def convert_output(job_details)
90
+ output = []
91
+ job_details.body["job"]["output_media_files"].each do |o|
92
+ track_id = o["id"].to_s
93
+ label = o["label"]
94
+ url = o["url"]
95
+ output << convert_tech_metadata(o).merge(id: track_id, url: url, label: label)
96
+ end
97
+ output
98
+ end
99
+
100
+ def convert_errors(job_details)
101
+ errors = []
102
+ input_error = job_details.body["job"]["input_media_file"]["error_message"]
103
+ errors << input_error unless input_error.blank?
104
+ job_details.body["job"]["output_media_files"].each { |o| errors << o["error_message"] unless o["error_message"].blank? }
105
+ errors
106
+ end
107
+
108
+ def convert_tech_metadata(media_file)
109
+ return {} if media_file.nil?
110
+
111
+ metadata = {}
112
+ media_file.each_pair do |key, value|
113
+ next if value.blank?
114
+ case key
115
+ when "md5_checksum"
116
+ metadata[:checksum] = value
117
+ when "format"
118
+ metadata[:mime_type] = value
119
+ when "duration_in_ms"
120
+ metadata[:duration] = value.to_s
121
+ when "audio_codec"
122
+ metadata[:audio_codec] = value.to_s
123
+ when "channels"
124
+ metadata[:audio_channels] = value.to_s
125
+ when "audio_bitrate_in_kbps"
126
+ metadata[:audio_bitrate] = value.to_s
127
+ when "video_codec"
128
+ metadata[:video_codec] = value
129
+ when "frame_rate"
130
+ metadata[:video_framerate] = value.to_s
131
+ when "video_bitrate_in_kbps"
132
+ metadata[:video_bitrate] = value.to_s
133
+ when "width"
134
+ metadata[:width] = value.to_s
135
+ when "height"
136
+ metadata[:height] = value.to_s
137
+ end
138
+ end
139
+ metadata
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_support'
2
+
3
+ module ActiveEncode
4
+ module Status
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ # Current state of the encoding process
9
+ attr_accessor :state
10
+
11
+ attr_accessor :current_operations
12
+
13
+ attr_accessor :percent_complete
14
+
15
+ attr_accessor :errors
16
+ end
17
+
18
+ def created?
19
+ !id.nil?
20
+ end
21
+
22
+ def cancelled?
23
+ state == :cancelled
24
+ end
25
+
26
+ def completed?
27
+ state == :completed
28
+ end
29
+
30
+ def running?
31
+ state == :running
32
+ end
33
+
34
+ def failed?
35
+ state == :failed
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ require 'active_support'
2
+
3
+ module ActiveEncode
4
+ module TechnicalMetadata
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attr_accessor :tech_metadata
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveEncode
2
+ VERSION = '0.0.2'
3
+ end
Binary file
@@ -0,0 +1,323 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <workflow xmlns="http://workflow.opencastproject.org" xmlns:ns2="http://org.opencastproject.security" xmlns:ns3="http://mediapackage.opencastproject.org" state="STOPPED" id="cancelled-id">
3
+ <template>full</template>
4
+ <description>A workflow that puts mediapackages on hold</description>
5
+ <parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
6
+ <ns2:creator>
7
+ <ns2:userName>matterhorn_system_account</ns2:userName>
8
+ <ns2:roles>MATTERHORN_ADMINISTRATOR</ns2:roles>
9
+ <ns2:roles>ROLE_ADMIN</ns2:roles>
10
+ <ns2:roles>ROLE_ANONYMOUS</ns2:roles>
11
+ <ns2:roles>ROLE_OAUTH_USER</ns2:roles>
12
+ <ns2:roles>ROLE_USER</ns2:roles>
13
+ <ns2:organization>mh_default_org</ns2:organization>
14
+ </ns2:creator>
15
+ <ns2:organization id="mh_default_org">
16
+ <ns2:name>Opencast Project</ns2:name>
17
+ <ns2:servers>
18
+ <ns2:server port="8080" name="localhost"/>
19
+ </ns2:servers>
20
+ <ns2:adminRole>ROLE_ADMIN</ns2:adminRole>
21
+ <ns2:anonymousRole>ROLE_ANONYMOUS</ns2:anonymousRole>
22
+ <ns2:properties>
23
+ <ns2:property key="engageui.link_mobile_redirect.description">For more information have a look at the official site.</ns2:property>
24
+ <ns2:property key="engageui.link_mobile_redirect.url">http://opencast.org/matterhorn/</ns2:property>
25
+ <ns2:property key="engageui.annotations.enable">true</ns2:property>
26
+ <ns2:property key="adminui.series_prepopulate.enable">false</ns2:property>
27
+ <ns2:property key="adminui.i18n_tab_episode.enable">true</ns2:property>
28
+ <ns2:property key="avalon.stream_base">file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams</ns2:property>
29
+ <ns2:property key="engageui.link_download.enable">false</ns2:property>
30
+ <ns2:property key="adminui.chunksize">2024</ns2:property>
31
+ <ns2:property key="logo_large">/engage/ui/img/mh_logos/MatterhornLogo_large.png</ns2:property>
32
+ <ns2:property key="adminui.i18n_tab_users.enable">false</ns2:property>
33
+ <ns2:property key="engageui.link_mobile_redirect.enable">false</ns2:property>
34
+ <ns2:property key="engageui.links_media_module.enable">true</ns2:property>
35
+ <ns2:property key="logo_small">/engage/ui/img/mh_logos/OpencastLogo.png</ns2:property>
36
+ </ns2:properties>
37
+ </ns2:organization>
38
+ <ns3:mediapackage start="2015-04-20T18:01:57Z" id="609312d8-e41b-436f-9499-aedb05125510">
39
+ <ns3:title>Bars_512kb.mp4</ns3:title>
40
+ <ns3:media>
41
+ <ns3:track type="presenter/source" id="de77d14b-d002-465d-8012-838ecf289960">
42
+ <ns3:tags>
43
+ <ns3:tag>archive</ns3:tag>
44
+ </ns3:tags>
45
+ <ns3:url>http://localhost:8080/files/mediapackage/609312d8-e41b-436f-9499-aedb05125510/de77d14b-d002-465d-8012-838ecf289960/Bars_512kb.mp4</ns3:url>
46
+ </ns3:track>
47
+ </ns3:media>
48
+ <ns3:metadata>
49
+ <ns3:catalog type="dublincore/episode" id="9075b60e-b4ce-490b-8c04-7a18bb890db1">
50
+ <ns3:mimetype>text/xml</ns3:mimetype>
51
+ <ns3:tags>
52
+ <ns3:tag>archive</ns3:tag>
53
+ <ns3:tag>engage</ns3:tag>
54
+ </ns3:tags>
55
+ <ns3:url>http://localhost:8080/files/mediapackage/609312d8-e41b-436f-9499-aedb05125510/9075b60e-b4ce-490b-8c04-7a18bb890db1/dublincore.xml</ns3:url>
56
+ </ns3:catalog>
57
+ </ns3:metadata>
58
+ <ns3:attachments/>
59
+ </ns3:mediapackage>
60
+ <operations>
61
+ <operation retry-strategy="none" execution-host="http://localhost:8080" failed-attempts="0" max-attempts="1" continuable="true" abortable="true" fail-on-error="true" description="Hold for workflow selection" state="SUCCEEDED" job="6972" id="append">
62
+ <configurations/>
63
+ <holdurl>/workflow/hold/org.opencastproject.workflow.handler.appendworkflowoperationhandler</holdurl>
64
+ <hold-action-title>Action</hold-action-title>
65
+ <started>1429641937935</started>
66
+ <completed>1429641938521</completed>
67
+ <time-in-queue>0</time-in-queue>
68
+ <execution-history/>
69
+ </operation>
70
+ <operation retry-strategy="none" execution-host="http://localhost:8080" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Applying access control rules" state="SUCCEEDED" job="7341" id="apply-acl">
71
+ <configurations/>
72
+ <started>1429641946745</started>
73
+ <completed>1429641947473</completed>
74
+ <time-in-queue>0</time-in-queue>
75
+ <execution-history/>
76
+ </operation>
77
+ <operation retry-strategy="none" execution-host="http://localhost:8080" failed-attempts="0" max-attempts="1" fail-on-error="true" description="Tagging source material for archival" state="SUCCEEDED" job="7342" id="tag">
78
+ <configurations>
79
+ <configuration key="source-flavors">*/source,dublincore/*,security/*</configuration>
80
+ <configuration key="target-tags">+archive</configuration>
81
+ </configurations>
82
+ <started>1429641955975</started>
83
+ <completed>1429641956685</completed>
84
+ <time-in-queue>0</time-in-queue>
85
+ <execution-history/>
86
+ </operation>
87
+ <operation retry-strategy="none" execution-host="http://localhost:8080" failed-attempts="0" max-attempts="1" fail-on-error="true" description="Tagging dublin core catalogs for publishing" state="SUCCEEDED" job="7343" id="tag">
88
+ <configurations>
89
+ <configuration key="source-flavors">dublincore/*</configuration>
90
+ <configuration key="target-tags">+engage</configuration>
91
+ </configurations>
92
+ <started>1429641965321</started>
93
+ <completed>1429641965842</completed>
94
+ <time-in-queue>0</time-in-queue>
95
+ <execution-history/>
96
+ </operation>
97
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Inspecting the media package" state="INSTANTIATED" job="7344" id="inspect">
98
+ <configurations/>
99
+ <execution-history/>
100
+ </operation>
101
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Preparing presenter audio and video work versions" state="INSTANTIATED" id="prepare-av">
102
+ <configurations>
103
+ <configuration key="target-flavor">presenter/work</configuration>
104
+ <configuration key="rewrite">false</configuration>
105
+ <configuration key="promiscuous-audio-muxing">true</configuration>
106
+ <configuration key="source-flavor">presenter/source</configuration>
107
+ </configurations>
108
+ <execution-history/>
109
+ </operation>
110
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Preparing presentation audio and video work version" state="INSTANTIATED" id="prepare-av">
111
+ <configurations>
112
+ <configuration key="target-flavor">presentation/work</configuration>
113
+ <configuration key="rewrite">false</configuration>
114
+ <configuration key="promiscuous-audio-muxing">true</configuration>
115
+ <configuration key="source-flavor">presentation/source</configuration>
116
+ </configurations>
117
+ <execution-history/>
118
+ </operation>
119
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" if="${videoPreview}" fail-on-error="true" description="Encoding presenter (camera) video for preview" state="INSTANTIATED" id="compose">
120
+ <configurations>
121
+ <configuration key="target-flavor">*/preview</configuration>
122
+ <configuration key="encoding-profile">flash-preview.http</configuration>
123
+ <configuration key="source-flavor">*/work</configuration>
124
+ </configurations>
125
+ <execution-history/>
126
+ </operation>
127
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" if="${trimHold}" fail-on-error="true" description="Waiting for user to review / trim recording" state="INSTANTIATED" id="trim">
128
+ <configurations>
129
+ <configuration key="encoding-profile">trim.work</configuration>
130
+ <configuration key="target-flavor-subtype">trimmed</configuration>
131
+ <configuration key="source-flavor">*/work</configuration>
132
+ </configurations>
133
+ <execution-history/>
134
+ </operation>
135
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" fail-on-error="true" description="Tagging trimmed media for archive" state="INSTANTIATED" id="tag">
136
+ <configurations>
137
+ <configuration key="source-flavors">*/trimmed</configuration>
138
+ <configuration key="target-tags">+archive</configuration>
139
+ </configurations>
140
+ <execution-history/>
141
+ </operation>
142
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" if="${captionHold}" fail-on-error="true" description="Waiting for user to upload captions" state="INSTANTIATED" id="caption">
143
+ <configurations>
144
+ <configuration key="target-tags">engage,archive</configuration>
145
+ </configurations>
146
+ <execution-history/>
147
+ </operation>
148
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding presenter (camera) to player preview image" state="INSTANTIATED" id="image">
149
+ <configurations>
150
+ <configuration key="source-tags"/>
151
+ <configuration key="target-flavor">presenter/player+preview</configuration>
152
+ <configuration key="time">1</configuration>
153
+ <configuration key="encoding-profile">player-preview.http</configuration>
154
+ <configuration key="target-tags">engage</configuration>
155
+ <configuration key="source-flavor">presenter/trimmed</configuration>
156
+ </configurations>
157
+ <execution-history/>
158
+ </operation>
159
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding presentation (screen) to player preview image" state="INSTANTIATED" id="image">
160
+ <configurations>
161
+ <configuration key="source-tags"/>
162
+ <configuration key="target-flavor">presentation/player+preview</configuration>
163
+ <configuration key="time">1</configuration>
164
+ <configuration key="encoding-profile">player-preview.http</configuration>
165
+ <configuration key="target-tags">engage</configuration>
166
+ <configuration key="source-flavor">presentation/trimmed</configuration>
167
+ </configurations>
168
+ <execution-history/>
169
+ </operation>
170
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding presenter (camera) video to Flash download" state="INSTANTIATED" id="compose">
171
+ <configurations>
172
+ <configuration key="target-flavor">presenter/delivery</configuration>
173
+ <configuration key="encoding-profile">flash.http</configuration>
174
+ <configuration key="target-tags">engage</configuration>
175
+ <configuration key="source-flavor">presenter/trimmed</configuration>
176
+ </configurations>
177
+ <execution-history/>
178
+ </operation>
179
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding presentation (screen) to Flash download" state="INSTANTIATED" id="compose">
180
+ <configurations>
181
+ <configuration key="target-flavor">presentation/delivery</configuration>
182
+ <configuration key="encoding-profile">flash-vga.http</configuration>
183
+ <configuration key="target-tags">engage</configuration>
184
+ <configuration key="source-flavor">presentation/trimmed</configuration>
185
+ </configurations>
186
+ <execution-history/>
187
+ </operation>
188
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="false" description="Encoding presenter (screen) to flash audio download" state="INSTANTIATED" id="compose">
189
+ <configurations>
190
+ <configuration key="target-flavor">presenter/delivery</configuration>
191
+ <configuration key="encoding-profile">flash-audio.http</configuration>
192
+ <configuration key="target-tags">engage</configuration>
193
+ <configuration key="source-flavor">presenter/trimmed</configuration>
194
+ </configurations>
195
+ <execution-history/>
196
+ </operation>
197
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="false" description="Extracting segments from presentation" state="INSTANTIATED" id="segment-video">
198
+ <configurations>
199
+ <configuration key="source-flavor">presentation/trimmed</configuration>
200
+ </configurations>
201
+ <execution-history/>
202
+ </operation>
203
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding presenter (camera) to search result preview image" state="INSTANTIATED" id="image">
204
+ <configurations>
205
+ <configuration key="source-tags"/>
206
+ <configuration key="target-flavor">presenter/search+preview</configuration>
207
+ <configuration key="time">1</configuration>
208
+ <configuration key="encoding-profile">search-cover.http</configuration>
209
+ <configuration key="target-tags">engage</configuration>
210
+ <configuration key="source-flavor">presenter/trimmed</configuration>
211
+ </configurations>
212
+ <execution-history/>
213
+ </operation>
214
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding presentation (screen) to search result preview image" state="INSTANTIATED" id="image">
215
+ <configurations>
216
+ <configuration key="source-tags"/>
217
+ <configuration key="target-flavor">presentation/search+preview</configuration>
218
+ <configuration key="time">1</configuration>
219
+ <configuration key="encoding-profile">search-cover.http</configuration>
220
+ <configuration key="target-tags">engage</configuration>
221
+ <configuration key="source-flavor">presentation/trimmed</configuration>
222
+ </configurations>
223
+ <execution-history/>
224
+ </operation>
225
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding to feed download formats" state="INSTANTIATED" id="compose">
226
+ <configurations>
227
+ <configuration key="target-flavor">*/delivery</configuration>
228
+ <configuration key="encoding-profiles">feed-m4a.http, feed-avi.http</configuration>
229
+ <configuration key="target-tags">rss, atom</configuration>
230
+ <configuration key="source-flavor">*/trimmed</configuration>
231
+ </configurations>
232
+ <execution-history/>
233
+ </operation>
234
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding presenter (camera) to feed preview image" state="INSTANTIATED" id="image">
235
+ <configurations>
236
+ <configuration key="source-tags"/>
237
+ <configuration key="target-flavor">presenter/feed+preview</configuration>
238
+ <configuration key="time">1</configuration>
239
+ <configuration key="encoding-profile">feed-cover.http</configuration>
240
+ <configuration key="target-tags">rss, atom</configuration>
241
+ <configuration key="source-flavor">presenter/trimmed</configuration>
242
+ </configurations>
243
+ <execution-history/>
244
+ </operation>
245
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Encoding presentation (screen) to feed preview image" state="INSTANTIATED" id="image">
246
+ <configurations>
247
+ <configuration key="source-tags"/>
248
+ <configuration key="target-flavor">presentation/feed+preview</configuration>
249
+ <configuration key="time">1</configuration>
250
+ <configuration key="encoding-profile">feed-cover.http</configuration>
251
+ <configuration key="target-tags">rss, atom</configuration>
252
+ <configuration key="source-flavor">presentation/trimmed</configuration>
253
+ </configurations>
254
+ <execution-history/>
255
+ </operation>
256
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="false" description="Encoding presentation (screen) to segment preview image" state="INSTANTIATED" id="segmentpreviews">
257
+ <configurations>
258
+ <configuration key="source-tags"/>
259
+ <configuration key="target-flavor">presentation/segment+preview</configuration>
260
+ <configuration key="encoding-profile">player-slides.http</configuration>
261
+ <configuration key="reference-flavor">presentation/delivery</configuration>
262
+ <configuration key="target-tags">engage</configuration>
263
+ <configuration key="reference-tags">engage</configuration>
264
+ <configuration key="source-flavor">presentation/trimmed</configuration>
265
+ </configurations>
266
+ <execution-history/>
267
+ </operation>
268
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="false" description="Extracting text from presentation segments" state="INSTANTIATED" id="extract-text">
269
+ <configurations>
270
+ <configuration key="source-tags"/>
271
+ <configuration key="target-tags">engage,archive</configuration>
272
+ <configuration key="source-flavor">presentation/trimmed</configuration>
273
+ </configurations>
274
+ <execution-history/>
275
+ </operation>
276
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="2" exception-handler-workflow="error" fail-on-error="true" description="Distributing to progressive downloads" state="INSTANTIATED" id="distribute-download">
277
+ <configurations>
278
+ <configuration key="source-tags">engage,atom,rss,-publish</configuration>
279
+ <configuration key="target-tags">publish</configuration>
280
+ <configuration key="check-availability">true</configuration>
281
+ </configurations>
282
+ <execution-history/>
283
+ </operation>
284
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="2" exception-handler-workflow="error" if="rtmp://localhost/vod" fail-on-error="true" description="Distributing to streaming server" state="INSTANTIATED" id="distribute-streaming">
285
+ <configurations>
286
+ <configuration key="source-tags">engage,-publish</configuration>
287
+ <configuration key="target-tags">publish</configuration>
288
+ </configurations>
289
+ <execution-history/>
290
+ </operation>
291
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" fail-on-error="true" description="Removing archive tag from distributed material" state="INSTANTIATED" id="tag">
292
+ <configurations>
293
+ <configuration key="source-tags">publish</configuration>
294
+ <configuration key="target-tags">-archive</configuration>
295
+ </configurations>
296
+ <execution-history/>
297
+ </operation>
298
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" if="${archiveOp}" fail-on-error="true" description="Archiving" state="INSTANTIATED" id="archive">
299
+ <configurations>
300
+ <configuration key="source-tags">archive</configuration>
301
+ </configurations>
302
+ <execution-history/>
303
+ </operation>
304
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" exception-handler-workflow="error" fail-on-error="true" description="Publishing" state="INSTANTIATED" id="publish">
305
+ <configurations>
306
+ <configuration key="source-tags">publish</configuration>
307
+ </configurations>
308
+ <execution-history/>
309
+ </operation>
310
+ <operation retry-strategy="none" failed-attempts="0" max-attempts="1" fail-on-error="false" description="Cleaning up" state="INSTANTIATED" id="cleanup">
311
+ <configurations>
312
+ <configuration key="preserve-flavors"/>
313
+ </configurations>
314
+ <execution-history/>
315
+ </operation>
316
+ </operations>
317
+ <configurations>
318
+ <configuration key="workflowSelector">full</configuration>
319
+ <configuration key="distribution">Matterhorn Media Module</configuration>
320
+ <configuration key="archiveOp">true</configuration>
321
+ </configurations>
322
+ <errors/>
323
+ </workflow>