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,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
+ return @encodes[id]
17
+ end
18
+
19
+ def list(*filters)
20
+ raise 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
+ raise NotImplementedError
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,147 @@
1
+ module ActiveEncode
2
+ module EngineAdapters
3
+ class ZencoderAdapter
4
+
5
+ #TODO add a stub for an input helper (supplied by an initializer) that transforms encode.input into a zencoder accepted url
6
+ def create(encode)
7
+ response = Zencoder::Job.create(:input => "#{encode.input}")
8
+ build_encode(get_job_details(response.body["id"]), encode.class)
9
+ end
10
+
11
+ def find(id, opts = {})
12
+ build_encode(get_job_details(id), opts[:cast])
13
+ end
14
+
15
+ def list(*filters)
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def cancel(encode)
20
+ response = Zencoder::Job.cancel(encode.id)
21
+ if response.success?
22
+ build_encode(get_job_details(encode.id), encode.class)
23
+ else
24
+ nil
25
+ end
26
+ end
27
+
28
+ def purge(encode)
29
+ raise NotImplementedError
30
+ end
31
+
32
+ def remove_output(encode, output_id)
33
+ raise NotImplementedError
34
+ end
35
+
36
+ private
37
+ def get_job_details(job_id)
38
+ Zencoder::Job.details(job_id)
39
+ end
40
+
41
+ def get_job_progress(job_id)
42
+ Zencoder::Job.progress(job_id)
43
+ end
44
+
45
+ def build_encode(job_details, cast)
46
+ return nil if job_details.nil?
47
+ encode = cast.new(convert_input(job_details), convert_options(job_details))
48
+ encode.id = job_details.body["job"]["id"].to_s
49
+ encode.state = convert_state(job_details)
50
+ job_progress = get_job_progress(encode.id)
51
+ encode.current_operations = convert_current_operations(job_progress)
52
+ encode.percent_complete = convert_percent_complete(job_progress, job_details)
53
+ encode.output = convert_output(job_details)
54
+ encode.errors = convert_errors(job_details)
55
+ encode.tech_metadata = convert_tech_metadata(job_details.body["job"]["input_media_file"])
56
+ encode
57
+ end
58
+
59
+ def convert_state(job_details)
60
+ case job_details.body["job"]["state"]
61
+ when "pending", "waiting", "processing" #Should there be a queued state?
62
+ :running
63
+ when "cancelled"
64
+ :cancelled
65
+ when "failed"
66
+ :failed
67
+ when "finished"
68
+ :completed
69
+ end
70
+ end
71
+
72
+ def convert_current_operations(job_progress)
73
+ current_ops = []
74
+ job_progress.body["outputs"].each {|output| current_ops << output["current_event"] unless output["current_event"].nil?}
75
+ current_ops
76
+ end
77
+
78
+ def convert_percent_complete(job_progress, job_details)
79
+ percent = job_progress.body["progress"]
80
+ percent ||= 100 if convert_state(job_details) == :completed
81
+ percent ||= 0
82
+ percent
83
+ end
84
+
85
+ def convert_input(job_details)
86
+ job_details.body["job"]["input_media_file"]["url"]
87
+ end
88
+
89
+ def convert_options(job_details)
90
+ {}
91
+ end
92
+
93
+ def convert_output(job_details)
94
+ output = []
95
+ job_details.body["job"]["output_media_files"].each do |o|
96
+ track_id = o["id"].to_s
97
+ label = o["label"]
98
+ url = o["url"]
99
+ output << convert_tech_metadata(o).merge({id: track_id, url: url, label: label})
100
+ end
101
+ output
102
+ end
103
+
104
+ def convert_errors(job_details)
105
+ errors = []
106
+ input_error = job_details.body["job"]["input_media_file"]["error_message"]
107
+ errors << input_error unless input_error.blank?
108
+ job_details.body["job"]["output_media_files"].each {|o| errors << o["error_message"] unless o["error_message"].blank?}
109
+ errors
110
+ end
111
+
112
+ def convert_tech_metadata(media_file)
113
+ return {} if media_file.nil?
114
+
115
+ metadata = {}
116
+ media_file.each_pair do |key, value|
117
+ next if value.blank?
118
+ case key
119
+ when "md5_checksum"
120
+ metadata[:checksum] = value
121
+ when "format"
122
+ metadata[:mime_type] = value
123
+ when "duration_in_ms"
124
+ metadata[:duration] = value.to_s
125
+ when "audio_codec"
126
+ metadata[:audio_codec] = value.to_s
127
+ when "channels"
128
+ metadata[:audio_channels] = value.to_s
129
+ when "audio_bitrate_in_kbps"
130
+ metadata[:audio_bitrate] = value.to_s
131
+ when "video_codec"
132
+ metadata[:video_codec] = value
133
+ when "frame_rate"
134
+ metadata[:video_framerate] = value.to_s
135
+ when "video_bitrate_in_kbps"
136
+ metadata[:video_bitrate] = value.to_s
137
+ when "width"
138
+ metadata[:width] = value.to_s
139
+ when "height"
140
+ metadata[:height] = value.to_s
141
+ end
142
+ end
143
+ metadata
144
+ end
145
+ end
146
+ end
147
+ 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.1'
3
+ end
@@ -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>