active-encode 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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>