azure_media_service 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 08fdee82fc0f65b5448bafb95f064da9ed031492
4
- data.tar.gz: 47143a23d14af482ba7232029c680c69aa0ad629
3
+ metadata.gz: 00a545eccf5a1d981e5d5eacbced9300cef26fd0
4
+ data.tar.gz: 5981d595b2245482d11e4aa0ad15585f7a54e85c
5
5
  SHA512:
6
- metadata.gz: 8a4528a7cebb310197623e84d367860596e42990b621d06a11935f8d0e9c0233e46ae19b832033a4cfcaf29749f08cd5b6bb331a9a460b1f4a2517c82c0b6f92
7
- data.tar.gz: 5f65881823d38b3db53843a04e2194227d830c7bdfff79492cbac328453bf6c6831e96e07314d7588ba2cba1f5534544128e9eff35dc8ba0030c65599a54da24
6
+ metadata.gz: 0fc36138286d3f0ea302c3aa559fe74c417849980ea7834611abb640242ef54a32cbf42ae2dfc7d172029f1d1bb4c53e7bcaaa05b5a6b66eb8860a0900c5a5f7
7
+ data.tar.gz: 8ca181545faa585d65657ff09ff807683e54ae638ff54a6cca82a4fc542ae3bb191f964e687b899270f778c21231666e9498123bf09b5d37caee51f867ec173e
data/README.md CHANGED
@@ -22,29 +22,30 @@ Or install it yourself as:
22
22
 
23
23
  # initialize
24
24
  AzureMediaService.configure do |config|
25
- cofig.id = 'xxxxxxxx'
25
+ cofig.id = 'xxxxxxxx'
26
26
  config.secret = 'xxxxxxxxxxxxxxxxxx'
27
27
  end
28
28
 
29
- # service instance
30
- ams = AzureMediaService.service
31
-
32
29
  # upload file
30
+ ams = AzureMediaService.service
33
31
  asset = ams.upload_media('path/to/example.mp4')
34
32
 
33
+ # or
34
+
35
+ asset = AzureMediaService::Asset.create(asset_name)
36
+ asset.upload('path/to/example.mp4')
37
+
35
38
  # encode job
36
- asset = ams.assets('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx')
39
+ asset = AzureMediaService::Asset.get('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx')
37
40
  job = asset.encode_job('H264 Smooth Streaming 720p')
38
41
 
39
42
  # or
40
- job = ams.create_encode_job('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx', 'H264 Smooth Streaming 720p')
43
+ job = AzureMediaService::Job.create('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx', 'H264 Smooth Streaming 720p')
41
44
 
42
45
  # publish asset
43
- asset = ams.assets('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx')
46
+ asset = AzureMediaService::Asset.get('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx')
44
47
  asset.publish(expire_minutes: 43200)
45
48
 
46
- # or
47
- ams.publish('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx', 43200)
48
49
  ```
49
50
 
50
51
  ### Custom Encode Task
@@ -54,11 +55,60 @@ AzureMediaService.configure do |config|
54
55
  config.add_encode_task('Custom Encode Task', File.read('path/to/custome_task.xml'))
55
56
  end
56
57
 
57
- ams = AzureMediaService.service
58
- asset = ams.assets('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx')
58
+ asset = AzureMediaService::Asset.get('nb:cid:UUID:xxxxxxxxxxx-xxxxxxxxxxx-xxxxxx-xxxxxxx')
59
59
  asset.encode_job('Custom Encode Task')
60
60
  ```
61
61
 
62
+ ### AES Protection
63
+
64
+ ```ruby
65
+ asset = AzureMediaService::Asset.get(asset_id)
66
+
67
+ key = ScureRandom::random_bytes(16)
68
+
69
+ content_key = AzureMediaService::ContentKey.create({
70
+ content_key: key,
71
+ content_key_type: AzureMediaService::ContentKey::ContentKeyTypes[:EnvelopeEncryption],
72
+ name: 'content-key-name'
73
+ })
74
+ asset.content_key_link(content_key)
75
+
76
+
77
+ content_key_policies = AzureMediaService::ContentKeyAuthorizationPolicy.get()
78
+ content_key_policy = content_key_policies.fin { |p| p.name == 'your policy name' }
79
+ unless content_key_policy
80
+ content_key_policy = AzureMediaService::ContentKeyAuthorizationPolicy.create('your policy name')
81
+ policy_options = AzureMediaService::ContentKeyAuthorizationPolicyOption.create({
82
+ name: 'policy option',
83
+ key_delivery_type: AzureMediaService::ContentKeyAuthorizationPolicyOption::KeyDeliveryTypes[:BaselineHttp],
84
+ key_delivery_configuration: nil,
85
+ restrictions: [
86
+ {
87
+ "Name" => "HLS Authorization Policy",
88
+ "KeyRestrictionType" => AzureMediaService::ContentKeyAuthorizationPolicyOption::KeyRestrictionTypes[:Open]
89
+ }
90
+ ]
91
+ })
92
+ content_key_policy.option_link(policy_options)
93
+ end
94
+
95
+ content_key.add_authorization_policy(content_key_policy.Id)
96
+
97
+ protocols = AzureMediaService::AssetDeliveryPolicy::Protocol
98
+ # Your need to register the key to your key delivery server
99
+ kid = content_key.Id.split(':').last
100
+ key_delivery_url = "your key delivery server url"
101
+ delivery_policy = AzureMediaService::AssetDeliveryPolicy.create({
102
+ name: 'your delivery policy name',
103
+ protocol: protocols[:HLS] | protocols[:SmoothStreaming] | protocols[:Dash],
104
+ policy_type: AzureMediaService::AssetDeliveryPolicy::PolicyType[:DynamicEnvelopeEncryption],
105
+ configuration: JSON.generate([{Key: AzureMediaService::AssetDeliveryPolicy::ConfigurationKey[:EnvelopeBaseKeyAcquisitionUrl], Vlaue: key_delivery_url}])
106
+ })
107
+ asset.delivery_policy_link(delivery_policy)
108
+
109
+ asset.publish(expire_minutes: 43200)
110
+ ```
111
+
62
112
  ## Contributing
63
113
 
64
114
  1. Fork it ( https://github.com/murayama/azure_media_service_ruby/fork )
@@ -5,6 +5,9 @@ require 'azure_media_service/request'
5
5
  require 'azure_media_service/service'
6
6
  require 'azure_media_service/model'
7
7
 
8
+ require 'base64'
9
+ require 'openssl'
10
+ require 'securerandom'
8
11
  require 'faraday'
9
12
  require 'faraday_middleware'
10
13
  require 'time'
@@ -12,6 +15,7 @@ require 'mime/types'
12
15
  require 'base64'
13
16
  require 'builder/xmlmarkup'
14
17
 
18
+
15
19
  module AzureMediaService
16
20
 
17
21
  @@tasks = {}
@@ -5,3 +5,7 @@ require 'azure_media_service/model/locator'
5
5
  require 'azure_media_service/model/asset_file'
6
6
  require 'azure_media_service/model/media_processor'
7
7
  require 'azure_media_service/model/job'
8
+ require 'azure_media_service/model/content_key'
9
+ require 'azure_media_service/model/content_key_authorization_policy'
10
+ require 'azure_media_service/model/content_key_authorization_policy_option'
11
+ require 'azure_media_service/model/asset_delivery_policy'
@@ -1,7 +1,16 @@
1
1
  module AzureMediaService
2
- module Model
3
- class AccessPolicy < Base
2
+ class AccessPolicy < Model::Base
4
3
 
4
+ class << self
5
+ def create(name:'Policy', duration_minutes:300, permission:2)
6
+ post_body = {
7
+ "Name" => name,
8
+ "DurationInMinutes" => duration_minutes,
9
+ "Permissions" => permission
10
+ }
11
+ create_response(service.post("AccessPolicies", post_body))
12
+ end
5
13
  end
14
+
6
15
  end
7
16
  end
@@ -1,197 +1,245 @@
1
1
  module AzureMediaService
2
- module Model
3
- class Asset < Base
4
-
5
- def locators
6
- @locators ||= []
7
- if @locators.empty?
8
- _uri = URI.parse(self.Locators["__deferred"]["uri"])
9
- url = _uri.path.gsub('/api/','')
10
- res = @request.get(url)
11
- res["d"]["results"].each do |v|
12
- @locators << Model::Locator.new(v)
13
- end
2
+ class Asset < Model::Base
3
+
4
+ class << self
5
+
6
+ def create(name)
7
+ post_body = {
8
+ "Name" => name
9
+ }
10
+ create_response(service.post("Assets", post_body))
11
+ end
12
+
13
+ def get(asset_id=nil)
14
+ service.get('Assets', Asset, asset_id)
15
+ end
16
+ end
17
+
18
+ def locators
19
+ @locators ||= []
20
+ if @locators.empty?
21
+ _uri = URI.parse(self.Locators["__deferred"]["uri"])
22
+ url = _uri.path.gsub('/api/','')
23
+ res = @request.get(url)
24
+ res["d"]["results"].each do |v|
25
+ @locators << Locator.new(v)
14
26
  end
15
- @locators
16
27
  end
28
+ @locators
29
+ end
17
30
 
18
- def files
19
- @files ||= []
20
- if @files.empty?
21
- _uri = URI.parse(self.Files["__deferred"]["uri"])
22
- url = _uri.path.gsub('/api/','')
23
- res = @request.get(url)
24
- res["d"]["results"].each do |v|
25
- @files << Model::AssetFile.new(v)
26
- end
31
+ def files
32
+ @files ||= []
33
+ if @files.empty?
34
+ _uri = URI.parse(self.Files["__deferred"]["uri"])
35
+ url = _uri.path.gsub('/api/','')
36
+ res = @request.get(url)
37
+ res["d"]["results"].each do |v|
38
+ @files << AssetFile.new(v)
27
39
  end
28
- @files
29
40
  end
41
+ @files
42
+ end
30
43
 
31
- def upload(filepath)
32
- begin
33
- mime_type = MIME::Types.type_for(filepath)[0].to_s
34
- basename = File.basename(filepath, '.*')
35
- filename = File.basename(filepath)
36
- f = Faraday::UploadIO.new(filepath, mime_type)
37
-
38
- # create policy
39
- policy = @service.create_access_policy(name:"UploadPolicy", duration_minutes:1800, permission:2)
40
-
41
- # create Locator
42
- locator = @service.create_locator(policy_id:policy.Id, asset_id:self.Id, type:1)
43
-
44
- # upload
45
- upload_url = File.join(locator.BaseUri, filename)
46
- upload_url += locator.ContentAccessComponent
47
-
48
- if f.size > Config::UPLOAD_LIMIT_SIZE
49
- # put block and put block list API
50
- i = 1
51
- blockids = []
52
- while buf = f.read(Config::READ_BUFFER_SIZE) do
53
- id = "%05d" % i # サイズを同じにしなければいけないので、5桁にする
54
- blockid = Base64.strict_encode64("#{id}-#{filename}")
55
- blockids << blockid
56
- put_block_url = upload_url + "&comp=block&blockid=#{URI.escape(blockid)}"
57
- res = put_blob(url:put_block_url, blob:buf)
58
- i+=1
59
- end
44
+ def content_keys
45
+ @content_keys ||= []
46
+ if @content_keys.empty?
47
+ _uri = URI.parse(self.ContentKeys["__deferred"]["uri"])
48
+ url = _uri.path.gsub('/api/','')
49
+ res = @request.get(url)
50
+ res["d"]["results"].each do |v|
51
+ @content_keys << ContentKey.new(v)
52
+ end
53
+ end
54
+ @content_keys
55
+ end
60
56
 
61
- put_block_list_url = upload_url + "&comp=blocklist"
62
- let = ''
63
- xml = Builder::XmlMarkup.new(:target => let, :indent => 3)
64
- xml.instruct!
65
- xml.BlockList {
66
- blockids.each do |id|
67
- xml.Latest id
68
- end
69
- }
70
-
71
- res = @request.put(put_block_list_url, let) do |headers|
72
- headers['x-ms-date'] = Time.now.httpdate
73
- headers['x-ms-version'] = '2014-02-14'
74
- headers['Content-Type'] = 'text/plain; charset = UTF-8'
75
- headers['Content-Length'] = let.size.to_s
76
- end
57
+ def delivery_policies
58
+ @delivery_policies ||= []
59
+ if @delivery_policies.empty?
60
+ _uri = URI.parse(self.DeliveryPolicies["__deferred"]["uri"])
61
+ url = _uri.path.gsub('/api/','')
62
+ res = @request.get(url)
63
+ res["d"]["results"].each do |v|
64
+ @delivery_policies << AssetDeliveryPolicy.new(v)
65
+ end
66
+ end
67
+ @delivery_policies
68
+ end
77
69
 
78
- else
79
- res = put_blob(url:upload_url, blob:f)
70
+ def upload(filepath)
71
+ begin
72
+ mime_type = MIME::Types.type_for(filepath)[0].to_s
73
+ basename = File.basename(filepath, '.*')
74
+ filename = File.basename(filepath)
75
+ f = Faraday::UploadIO.new(filepath, mime_type)
76
+
77
+ # create policy
78
+ policy = AccessPolicy.create(name:"UploadPolicy", duration_minutes:1800, permission:2)
79
+
80
+ # create Locator
81
+ locator = Locator.create(policy_id:policy.Id, asset_id:self.Id, type:1)
82
+
83
+ # upload
84
+ upload_url = File.join(locator.BaseUri, filename)
85
+ upload_url += locator.ContentAccessComponent
86
+
87
+ if f.size > Config::UPLOAD_LIMIT_SIZE
88
+ # put block and put block list API
89
+ i = 1
90
+ blockids = []
91
+ while buf = f.read(Config::READ_BUFFER_SIZE) do
92
+ id = "%05d" % i # サイズを同じにしなければいけないので、5桁にする
93
+ blockid = Base64.strict_encode64("#{id}-#{filename}")
94
+ blockids << blockid
95
+ put_block_url = upload_url + "&comp=block&blockid=#{URI.escape(blockid)}"
96
+ res = put_blob(url:put_block_url, blob:buf)
97
+ i+=1
80
98
  end
81
99
 
82
- # create metadata
83
- @request.get("CreateFileInfos", {"assetid" => "'#{URI.encode(self.Id)}'"})
100
+ put_block_list_url = upload_url + "&comp=blocklist"
101
+ let = ''
102
+ xml = Builder::XmlMarkup.new(:target => let, :indent => 3)
103
+ xml.instruct!
104
+ xml.BlockList {
105
+ blockids.each do |id|
106
+ xml.Latest id
107
+ end
108
+ }
109
+
110
+ res = @request.put_row(put_block_list_url, let) do |headers|
111
+ headers['x-ms-date'] = Time.now.httpdate
112
+ headers['x-ms-version'] = '2014-02-14'
113
+ headers['Content-Type'] = 'text/plain; charset = UTF-8'
114
+ headers['Content-Length'] = let.size.to_s
115
+ end
84
116
 
85
- clear_cache
86
- rescue => e
87
- raise MediaServiceError.new(e.message)
117
+ else
118
+ res = put_blob(url:upload_url, blob:f)
88
119
  end
89
- self
120
+
121
+ # create metadata
122
+ @request.get("CreateFileInfos", {"assetid" => "'#{URI.encode(self.Id)}'"})
123
+
124
+ clear_cache
125
+ rescue => e
126
+ raise MediaServiceError.new(e.message)
90
127
  end
128
+ self
129
+ end
91
130
 
92
131
 
93
- def encode_job(encode_configuration)
94
- media_processor = @service.media_processor_id_by_name('Windows Azure Media Encoder')
132
+ def encode_job(encode_configuration)
133
+ media_processor = @service.media_processor_id_by_name('Windows Azure Media Encoder')
95
134
 
96
- conf_str = encode_configuration.gsub(' ', '_')
135
+ conf_str = encode_configuration.gsub(' ', '_')
97
136
 
98
- if AzureMediaService.encode_tasks.has_key?(encode_configuration)
99
- encode_configuration = AzureMediaService.encode_tasks[encode_configuration]
100
- end
137
+ if AzureMediaService.encode_tasks.has_key?(encode_configuration)
138
+ encode_configuration = AzureMediaService.encode_tasks[encode_configuration]
139
+ end
101
140
 
102
- job_name, output_name = job_and_output_name(asset_name:self.Name, conf:conf_str)
141
+ job_name, output_name = job_and_output_name(asset_name:self.Name, conf:conf_str)
103
142
 
104
- post_body = {}
105
- post_body["Name"] = job_name
106
- post_body["InputMediaAssets"] = [
107
- {
108
- "__metadata" => {
109
- "uri" => self.__metadata["uri"]
110
- }
143
+ post_body = {}
144
+ post_body["Name"] = job_name
145
+ post_body["InputMediaAssets"] = [
146
+ {
147
+ "__metadata" => {
148
+ "uri" => self.__metadata["uri"]
111
149
  }
112
- ]
113
- task_body = ''
114
- xml = Builder::XmlMarkup.new(:target => task_body)
115
- xml.instruct!
116
- xml.taskBody {
117
- xml.inputAsset 'JobInputAsset(0)'
118
- xml.outputAsset 'JobOutputAsset(0)', :assetName => output_name
119
150
  }
120
- post_body["Tasks"] = [
121
- {
122
- "Configuration" => encode_configuration,
123
- "MediaProcessorId" => media_processor.Id,
124
- "TaskBody" => task_body
125
- }
126
- ]
151
+ ]
152
+ task_body = ''
153
+ xml = Builder::XmlMarkup.new(:target => task_body)
154
+ xml.instruct!
155
+ xml.taskBody {
156
+ xml.inputAsset 'JobInputAsset(0)'
157
+ xml.outputAsset 'JobOutputAsset(0)', :assetName => output_name
158
+ }
159
+ post_body["Tasks"] = [
160
+ {
161
+ "Configuration" => encode_configuration,
162
+ "MediaProcessorId" => media_processor.Id,
163
+ "TaskBody" => task_body
164
+ }
165
+ ]
127
166
 
128
- res = @request.post('Jobs', post_body)
129
- Model::Job.new(res["d"])
130
- end
167
+ res = @request.post('Jobs', post_body)
168
+ Job.new(res["d"])
169
+ end
131
170
 
132
171
 
133
- def publish(expire_minutes: 43200)
134
- locator = locators.select {|l| l.Type == 2}.first
135
- unless locator
136
- policy = @service.create_access_policy(name:"PublishPolicy", duration_minutes: expire_minutes, permission:1)
137
- locator = @service.create_locator(policy_id: policy.Id, asset_id: self.Id, type: 2)
138
- end
139
- locator
172
+ def publish(expire_minutes: 43200)
173
+ locator = locators.select {|l| l.Type == 2}.first
174
+ unless locator
175
+ policy = AccessPolicy.create(name:"PublishPolicy", duration_minutes: expire_minutes, permission:1)
176
+ locator = Locator.create(policy_id: policy.Id, asset_id: self.Id, type: 2)
140
177
  end
178
+ locator
179
+ end
141
180
 
142
- def publish_url
143
- primary_file = files.select {|f| f.IsPrimary == true}.first
144
- locator = locators.select {|l| l.Type == 2 }.first
145
- if primary_file && locator
146
- File.join(locator.Path, primary_file.Name, 'Manifest')
147
- else
148
- nil
149
- end
181
+ def publish_url
182
+ primary_file = files.select {|f| f.IsPrimary == true}.first
183
+ locator = locators.select {|l| l.Type == 2 }.first
184
+ if primary_file && locator
185
+ File.join(locator.Path, primary_file.Name, 'Manifest')
186
+ else
187
+ nil
150
188
  end
189
+ end
151
190
 
152
- def delete
153
- begin
154
- res = @request.delete("Assets('#{self.Id}')")
155
- clear_cache
156
- rescue => e
157
- raise MediaServiceError.new(e.message)
158
- end
159
- res
191
+ def delete
192
+ begin
193
+ res = @request.delete("Assets('#{self.Id}')")
194
+ clear_cache
195
+ rescue => e
196
+ raise MediaServiceError.new(e.message)
160
197
  end
198
+ res
199
+ end
161
200
 
162
- private
201
+ def content_key_link(content_key)
202
+ @request.post("Assets('#{CGI.escape(self.Id)}')/$links/ContentKeys", {uri: content_key.__metadata['uri']})
203
+ end
163
204
 
164
- def clear_cache
165
- @locators = nil
166
- @files = nil
167
- self
168
- end
205
+ def delivery_policy_link(asset_delivery_policy)
206
+ @request.post("Assets('#{CGI.escape(self.Id)}')/$links/DeliveryPolicies", {uri: asset_delivery_policy.__metadata['uri']})
207
+ end
169
208
 
170
- def job_and_output_name(asset_name:, conf:)
171
- job_names = []
172
- job_names << asset_name
173
- job_names << 'EncodeJob'
174
- job_names << conf
175
- job_name = job_names.join('-')
209
+ private
176
210
 
177
- output_names = []
178
- output_names << asset_name
179
- output_names << conf
180
- output_names << 'Output'
181
- output_name = output_names.join('-')
211
+ def clear_cache
212
+ @locators = nil
213
+ @files = nil
214
+ @content_keys = nil
215
+ @delivery_policies = nil
216
+ self
217
+ end
182
218
 
183
- [job_name, output_name]
184
- end
219
+ def job_and_output_name(asset_name:, conf:)
220
+ job_names = []
221
+ job_names << asset_name
222
+ job_names << 'EncodeJob'
223
+ job_names << conf
224
+ job_name = job_names.join('-')
185
225
 
186
- def put_blob(url:, blob:)
187
- res = @request.put(url, blob) do |headers|
188
- headers['x-ms-blob-type'] = 'BlockBlob'
189
- headers['x-ms-version'] = '2014-02-14' # Storage API Version
190
- headers['Content-Type'] = 'application/octet-stream'
191
- headers['Content-Length'] = blob.size.to_s
192
- end
193
- end
226
+ output_names = []
227
+ output_names << asset_name
228
+ output_names << conf
229
+ output_names << 'Output'
230
+ output_name = output_names.join('-')
231
+
232
+ [job_name, output_name]
194
233
  end
195
234
 
235
+ def put_blob(url:, blob:)
236
+ res = @request.put_row(url, blob) do |headers|
237
+ headers['x-ms-blob-type'] = 'BlockBlob'
238
+ headers['x-ms-version'] = '2014-02-14' # Storage API Version
239
+ headers['Content-Type'] = 'application/octet-stream'
240
+ headers['Content-Length'] = blob.size.to_s
241
+ end
242
+ end
196
243
  end
244
+
197
245
  end
@@ -0,0 +1,57 @@
1
+ module AzureMediaService
2
+ class AssetDeliveryPolicy < Model::Base
3
+
4
+ Protocol = {
5
+ None: 0x0,
6
+ SmoothStreaming: 0x1,
7
+ Dash: 0x2,
8
+ HLS: 0x4,
9
+ Hds: 0x8,
10
+ All: 0xFFFF
11
+ }
12
+
13
+ PolicyType = {
14
+ None: 0,
15
+ Blocked: 1,
16
+ NoDynamicEncryption: 2,
17
+ DynamicEnvelopeEncryption: 3,
18
+ DynamicCommonEncryption: 4
19
+ }
20
+
21
+ ConfigurationKey = {
22
+ None: 0,
23
+ EnvelopeKeyAcquisitionUrl: 1,
24
+ EnvelopeBaseKeyAcquisitionUrl: 2,
25
+ EnvelopeEncryptionIVAsBase64: 3,
26
+ PlayReadyLicenseAcquisitionUrl: 4,
27
+ PlayReadyCustomAttributes: 5,
28
+ EnvelopeEncryptionIV: 6
29
+ }
30
+
31
+
32
+ class << self
33
+ def create(name:, protocol:, policy_type:, configuration:)
34
+ body = {
35
+ "Name" => name,
36
+ "AssetDeliveryProtocol" => protocol,
37
+ "AssetDeliveryPolicyType" => policy_type,
38
+ "AssetDeliveryConfiguration" => configuration
39
+ }
40
+ create_response(service.post("AssetDeliveryPolicies", body))
41
+ end
42
+
43
+ def get(asset_delivery_policy_id=nil)
44
+ service.get("AssetDeliveryPolicies", AssetDeliveryPolicy, asset_delivery_policy_id)
45
+ end
46
+ end
47
+
48
+ def delete
49
+ begin
50
+ res = @request.delete("AssetDeliveryPolicies('#{self.Id}')")
51
+ rescue => e
52
+ raise MediaServiceError.new(e.message)
53
+ end
54
+ res
55
+ end
56
+ end
57
+ end
@@ -1,7 +1,5 @@
1
1
  module AzureMediaService
2
- module Model
3
- class AssetFile < Base
2
+ class AssetFile < Model::Base
4
3
 
5
- end
6
4
  end
7
5
  end
@@ -11,6 +11,22 @@ module AzureMediaService
11
11
  @request = AzureMediaService.request
12
12
  @service = AzureMediaService.service
13
13
  end
14
+
15
+ class << self
16
+
17
+ def service
18
+ AzureMediaService.service
19
+ end
20
+
21
+ def create_response(res)
22
+ if res["d"]
23
+ self.new(res["d"])
24
+ else
25
+ raise MediaServiceError.new(res["error"]["message"]["value"])
26
+ end
27
+ end
28
+
29
+ end
14
30
  end
15
31
  end
16
32
  end
@@ -0,0 +1,71 @@
1
+ module AzureMediaService
2
+ class ContentKey < Model::Base
3
+
4
+ ContentKeyTypes = {
5
+ CommonEncryption: 0,
6
+ StorageEncryption: 1,
7
+ ConfigurationEncryption: 2,
8
+ UrlEncryption: 3,
9
+ EnvelopeEncryption: 4
10
+ }
11
+
12
+ class << self
13
+ def create(content_key:, content_key_type: 4,protection_key_type: 0, name: nil )
14
+ id = "nb:kid:UUID:#{SecureRandom.uuid.upcase}"
15
+ # content_key = SecureRandom.random_bytes(16)
16
+ protection_key_id = service.get_protection_key_id(content_key_type)
17
+ protection_key = service.get_protection_key(protection_key_id) # X.509
18
+ x509 = OpenSSL::X509::Certificate.new(Base64.decode64(protection_key))
19
+ public_key = x509.public_key
20
+ encrypted_content_key = Base64.strict_encode64(public_key.public_encrypt(content_key, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING))
21
+
22
+ # create checksum
23
+ cipher = OpenSSL::Cipher.new('AES-128-ECB')
24
+ cipher.encrypt
25
+ cipher.key = content_key
26
+ cipher.padding = 0
27
+ encrypt_data = ""
28
+ encrypt_data << cipher.update(protection_key_id[0,16])
29
+ encrypt_data << cipher.final
30
+ check_sum = Base64.strict_encode64(encrypt_data[0,8])
31
+
32
+ post_body = {
33
+ "Id" => id,
34
+ "ContentKeyType" => content_key_type,
35
+ "EncryptedContentKey" => encrypted_content_key,
36
+ "ProtectionKeyId" => protection_key_id,
37
+ "ProtectionKeyType" => protection_key_type,
38
+ "Checksum" => check_sum,
39
+ "Name" => name
40
+ }
41
+ create_response(service.post("ContentKeys", post_body))
42
+ end
43
+
44
+ def get(content_key_id=nil)
45
+ service.get('ContentKeys', ContentKey, content_key_id)
46
+ end
47
+ end
48
+
49
+ def add_authorization_policy(policy_id)
50
+ res = @request.put("ContentKeys('#{CGI.escape(self.Id)}')", {AuthorizationPolicyId: policy_id})
51
+ end
52
+
53
+ # GetKeyDeliveryUrl
54
+ #
55
+ # @params key_delivery_type 1: PlayReady license 2: EnvelopeEncryption
56
+ #
57
+ def get_key_delivery_url(key_delivery_type)
58
+ @request.post("ContentKeys('#{CGI.escape(self.Id)}')/GetKeyDeliveryUrl", {KeyDeliveryType: key_delivery_type})
59
+ end
60
+
61
+ def delete
62
+ begin
63
+ res = @request.delete("ContentKeys('#{self.Id}')")
64
+ clear_cache
65
+ rescue => e
66
+ raise MediaServiceError.new(e.message)
67
+ end
68
+ res
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,27 @@
1
+ module AzureMediaService
2
+ class ContentKeyAuthorizationPolicy < Model::Base
3
+
4
+ class << self
5
+ def create(name)
6
+ create_response(service.post("ContentKeyAuthorizationPolicies", {Name: name}))
7
+ end
8
+
9
+ def get(content_key_authorization_policy_id=nil)
10
+ service.get("ContentKeyAuthorizationPolicies", ContentKeyAuthorizationPolicy, content_key_authorization_policy_id)
11
+ end
12
+ end
13
+
14
+ def option_link(options)
15
+ @request.post("ContentKeyAuthorizationPolicies('#{CGI.escape(self.Id)}')/$links/Options", {uri: options.__metadata['uri']})
16
+ end
17
+
18
+ def delete
19
+ begin
20
+ res = @request.delete("ContentKeyAuthorizationPolicies('#{self.Id}')")
21
+ rescue => e
22
+ raise MediaServiceError.new(e.message)
23
+ end
24
+ res
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ module AzureMediaService
2
+ class ContentKeyAuthorizationPolicyOption < Model::Base
3
+
4
+ KeyDeliveryTypes = {
5
+ None: 0,
6
+ PlayReadyLicense: 1,
7
+ BaselineHttp: 2
8
+ }
9
+
10
+ KeyRestrictionTypes = {
11
+ Open: 0,
12
+ TokenRestricted: 1,
13
+ IPRestricted: 2
14
+ }
15
+
16
+ class << self
17
+ def create(name:, key_delivery_type:, key_delivery_configuration: nil, restrictions:)
18
+ post_body = {
19
+ "Name" => name,
20
+ "KeyDeliveryType" => key_delivery_type,
21
+ "Restrictions" => {"results" => restrictions}
22
+ }
23
+ if key_delivery_configuration
24
+ post_body["KeyDeliveryConfiguration"] = key_delivery_configuration
25
+ end
26
+ create_response(service.post("ContentKeyAuthorizationPolicyOptions", post_body))
27
+ end
28
+
29
+ def get(content_key_authorization_policy_option_id=nil)
30
+ service.get("ContentKeyAuthorizationPolicyOptions", ContentKeyAuthorizationPolicyOption, content_key_authorization_policy_option_id)
31
+ end
32
+ end
33
+
34
+ def delete
35
+ begin
36
+ res = @request.delete("ContentKeyAuthorizationPolicyOptions('#{self.Id}')")
37
+ rescue => e
38
+ raise MediaServiceError.new(e.message)
39
+ end
40
+ res
41
+ end
42
+ end
43
+ end
44
+
@@ -1,32 +1,41 @@
1
1
  module AzureMediaService
2
- module Model
3
- class Job < Base
2
+ class Job < Model::Base
4
3
 
5
- def output_assets
6
- @output_assets ||= []
7
- if @output_assets.empty?
8
- _uri = URI.parse(self.OutputMediaAssets["__deferred"]["uri"])
9
- url = _uri.path.gsub('/api/','')
10
- res = @request.get(url)
11
- res["d"]["results"].each do |v|
12
- @output_assets << Model::Asset.new(v)
13
- end
4
+ class << self
5
+ def create(asset_id, encode_configuration)
6
+ asset = Asset.get(asset_id)
7
+ asset.encode_job(encode_configuration)
8
+ end
9
+
10
+ def get(job_id=nil)
11
+ service.get('Jobs', Job, job_id)
12
+ end
13
+ end
14
+
15
+ def output_assets
16
+ @output_assets ||= []
17
+ if @output_assets.empty?
18
+ _uri = URI.parse(self.OutputMediaAssets["__deferred"]["uri"])
19
+ url = _uri.path.gsub('/api/','')
20
+ res = @request.get(url)
21
+ res["d"]["results"].each do |v|
22
+ @output_assets << Asset.new(v)
14
23
  end
15
- @output_assets
16
24
  end
25
+ @output_assets
26
+ end
17
27
 
18
- def input_assets
19
- @input_assets ||= []
20
- if @input_assets.empty?
21
- _uri = URI.parse(self.InputMediaAssets["__deferred"]["uri"])
22
- url = _uri.path.gsub('/api/','')
23
- res = @request.get(url)
24
- res["d"]["results"].each do |v|
25
- @input_assets << Model::Asset.new(v)
26
- end
28
+ def input_assets
29
+ @input_assets ||= []
30
+ if @input_assets.empty?
31
+ _uri = URI.parse(self.InputMediaAssets["__deferred"]["uri"])
32
+ url = _uri.path.gsub('/api/','')
33
+ res = @request.get(url)
34
+ res["d"]["results"].each do |v|
35
+ @input_assets << Asset.new(v)
27
36
  end
28
- @input_assets
29
37
  end
38
+ @input_assets
30
39
  end
31
40
  end
32
41
  end
@@ -1,7 +1,17 @@
1
1
  module AzureMediaService
2
- module Model
3
- class Locator < Base
2
+ class Locator < Model::Base
4
3
 
4
+ class << self
5
+ def create(policy_id:,asset_id:,type:1)
6
+ post_body = {
7
+ "AccessPolicyId" => policy_id,
8
+ "AssetId" => asset_id,
9
+ "Type" => type,
10
+ "StartTime" => (Time.now - 5*60).gmtime.strftime('%Y-%m-%dT%H:%M:%SZ')
11
+ }
12
+ create_response(service.post("Locators", post_body))
13
+ end
5
14
  end
15
+
6
16
  end
7
17
  end
@@ -1,7 +1,5 @@
1
1
  module AzureMediaService
2
- module Model
3
- class MediaProcessor < Base
2
+ class MediaProcessor < Model::Base
4
3
 
5
- end
6
4
  end
7
5
  end
@@ -20,6 +20,9 @@ module AzureMediaService
20
20
  @config[:mediaURI] = res.headers['location']
21
21
  get(endpoint, params)
22
22
  else
23
+ if res.headers[:error]
24
+ raise MediaServiceError.new("#{res.headers[:error]}: #{res.headers[:error_description]}")
25
+ end
23
26
  res.body
24
27
  end
25
28
  end
@@ -38,11 +41,35 @@ module AzureMediaService
38
41
  @config[:mediaURI] = res.headers['location']
39
42
  post(endpoint, body)
40
43
  else
44
+ if res.headers[:error]
45
+ raise MediaServiceError.new("#{res.headers[:error]}: #{res.headers[:error_description]}")
46
+ end
41
47
  res.body
42
48
  end
43
49
  end
44
50
 
45
- def put(url, body)
51
+ def put(endpoint, body)
52
+ setToken if token_expire?
53
+
54
+ res = conn(@config[:mediaURI]).put do |req|
55
+ req.url endpoint
56
+ req.headers = @default_headers
57
+ req.headers[:Authorization] = "Bearer #{@access_token}"
58
+ req.body = body
59
+ end
60
+
61
+ if res.status == 301
62
+ @config[:mediaURI] = res.headers['location']
63
+ post(endpoint, body)
64
+ else
65
+ if res.headers[:error]
66
+ raise MediaServiceError.new("#{res.headers[:error]}: #{res.headers[:error_description]}")
67
+ end
68
+ res.body
69
+ end
70
+ end
71
+
72
+ def put_row(url, body)
46
73
 
47
74
  _conn = conn(url) do |builder|
48
75
  builder.request :multipart
@@ -62,6 +89,9 @@ module AzureMediaService
62
89
  @config[:mediaURI] = res.headers['location']
63
90
  put(url, body)
64
91
  else
92
+ if res.headers[:error]
93
+ raise MediaServiceError.new("#{res.headers[:error]}: #{res.headers[:error_description]}")
94
+ end
65
95
  res.body
66
96
  end
67
97
  end
@@ -81,6 +111,9 @@ module AzureMediaService
81
111
  @config[:mediaURI] = res.headers['location']
82
112
  delete(endpoint, params)
83
113
  else
114
+ if res.headers[:error]
115
+ raise MediaServiceError.new("#{res.headers[:error]}: #{res.headers[:error_description]}")
116
+ end
84
117
  res.body
85
118
  end
86
119
  end
@@ -100,7 +133,7 @@ module AzureMediaService
100
133
  "Accept" => "application/json;odata=verbose",
101
134
  "DataServiceVersion" => "3.0",
102
135
  "MaxDataServiceVersion" => "3.0",
103
- "x-ms-version" => "2.5"
136
+ "x-ms-version" => "2.9"
104
137
  }
105
138
  end
106
139
 
@@ -7,31 +7,35 @@ module AzureMediaService
7
7
 
8
8
  # assets
9
9
  def assets(asset_id=nil)
10
- get('Assets', Model::Asset, asset_id)
10
+ warn("DEPRECATION WARNING: Service#assets is deprecated. Use AzureMediaService::Asset.get() instead.")
11
+ get('Assets', Asset, asset_id)
11
12
  end
12
13
 
13
14
  # assets create
14
15
  def create_asset(name)
16
+ warn("DEPRECATION WARNING: Service#create_asset is deprecated. Use AzureMediaService::Asset.create() instead.")
15
17
  post_body = {
16
18
  "Name" => name
17
19
  }
18
20
  res = @request.post("Assets", post_body)
19
- Model::Asset.new(res["d"])
21
+ Asset.new(res["d"])
20
22
  end
21
23
 
22
24
  # access policy create
23
25
  def create_access_policy(name:'Policy', duration_minutes:300, permission:2)
26
+ warn("DEPRECATION WARNING: Service#create_access_policy is deprecated. Use AzureMediaService::AccessPolicy.create() instead.")
24
27
  post_body = {
25
28
  "Name" => name,
26
29
  "DurationInMinutes" => duration_minutes,
27
30
  "Permissions" => permission
28
31
  }
29
32
  res = @request.post("AccessPolicies", post_body)
30
- Model::AccessPolicy.new(res["d"])
33
+ AccessPolicy.new(res["d"])
31
34
  end
32
35
 
33
36
  # locator create
34
37
  def create_locator(policy_id:,asset_id:,type:1)
38
+ warn("DEPRECATION WARNING: Service#create_locator is deprecated. Use AzureMediaService::Locator.create() instead.")
35
39
  post_body = {
36
40
  "AccessPolicyId" => policy_id,
37
41
  "AssetId" => asset_id,
@@ -39,33 +43,38 @@ module AzureMediaService
39
43
  "StartTime" => (Time.now - 5*60).gmtime.strftime('%Y-%m-%dT%H:%M:%SZ')
40
44
  }
41
45
  res = @request.post("Locators", post_body)
42
- Model::Locator.new(res["d"])
46
+ Locator.new(res["d"])
43
47
  end
44
48
 
45
49
  def upload_media(filepath)
46
50
  basename = File.basename(filepath, '.*')
47
51
  asset_name = "#{basename}-Source-#{Time.now.strftime('%Y%m%d%H%M%S')}"
48
- asset = create_asset(asset_name)
52
+ asset = Asset.create(asset_name)
49
53
  asset.upload(filepath)
50
54
  end
51
55
 
52
56
  def create_encode_job(asset_id, encode_configuration)
57
+ warn("DEPRECATION WARNING: Service#create_encode_job is deprecated. Use AzureMediaService::Job.create() instead.")
53
58
  asset = assets(asset_id)
54
59
  asset.encode_job(encode_configuration)
55
60
  end
56
61
 
57
62
  def jobs(job_id=nil)
58
- get('Jobs', Model::Job, job_id)
63
+ warn("DEPRECATION WARNING: Service#jobs is deprecated. Use AzureMediaService::Job.get() instead.")
64
+ get('Jobs', Job, job_id)
59
65
  end
60
66
 
67
+
61
68
  # publish asset
62
69
  def publish(asset_id, expire_minutes=nil)
63
- asset = assets(asset_id)
70
+ warn("DEPRECATION WARNING: Service#publish is deprecated. Use AzureMediaService::Asset#publish() instead.")
71
+ asset = Asset.get(asset_id)
64
72
  asset.publish(expire_minutes)
65
73
  end
66
74
 
67
75
  def publish_url(asset_id)
68
- asset = assets(asset_id)
76
+ warn("DEPRECATION WARNING: Service#publish_url is deprecated. Use AzureMediaService::Asset#publish_url() instead.")
77
+ asset = Asset.get(asset_id)
69
78
  asset.publish_url
70
79
  end
71
80
 
@@ -76,22 +85,49 @@ module AzureMediaService
76
85
  }.sort{|a,b|
77
86
  b["Version"].to_i <=> a["Version"].to_i
78
87
  }.first
79
- Model::MediaProcessor.new(mp)
88
+ MediaProcessor.new(mp)
89
+ end
90
+
91
+ def get_protection_key_id(content_key_type)
92
+ res = @request.get("GetProtectionKeyId", contentKeyType: content_key_type)
93
+ if res["d"]
94
+ res["d"]["GetProtectionKeyId"]
95
+ else
96
+ raise MediaServiceError.new(res["error"]["message"]["value"])
97
+ end
98
+ end
99
+
100
+ def get_protection_key(protection_key_id)
101
+ res = @request.get("GetProtectionKey", ProtectionKeyId: "'#{protection_key_id}'")
102
+ if res["d"]
103
+ res["d"]["GetProtectionKey"]
104
+ else
105
+ raise MediaServiceError.new(res["error"]["message"]["value"])
106
+ end
80
107
  end
81
108
 
82
109
  def get(method, klass, id=nil)
83
110
  if id.nil?
84
111
  res = @request.get(method)
85
112
  results = []
86
- res["d"]["results"].each do |a|
87
- results << klass.new(a)
113
+ if res["d"]
114
+ res["d"]["results"].each do |a|
115
+ results << klass.new(a)
116
+ end
88
117
  end
89
118
  else
90
119
  res = @request.get("#{method}('#{id}')")
91
- results = klass.new(res["d"])
120
+ results = nil
121
+ if res["d"]
122
+ results = klass.new(res["d"])
123
+ end
92
124
  end
93
125
  results
94
126
  end
95
127
 
128
+ def post(method, body)
129
+ @request.post(method, body)
130
+ end
131
+
96
132
  end
97
133
  end
@@ -1,3 +1,3 @@
1
1
  module AzureMediaService
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: azure_media_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - murayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-04 00:00:00.000000000 Z
11
+ date: 2015-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -127,8 +127,12 @@ files:
127
127
  - lib/azure_media_service/model.rb
128
128
  - lib/azure_media_service/model/access_policy.rb
129
129
  - lib/azure_media_service/model/asset.rb
130
+ - lib/azure_media_service/model/asset_delivery_policy.rb
130
131
  - lib/azure_media_service/model/asset_file.rb
131
132
  - lib/azure_media_service/model/base.rb
133
+ - lib/azure_media_service/model/content_key.rb
134
+ - lib/azure_media_service/model/content_key_authorization_policy.rb
135
+ - lib/azure_media_service/model/content_key_authorization_policy_option.rb
132
136
  - lib/azure_media_service/model/job.rb
133
137
  - lib/azure_media_service/model/locator.rb
134
138
  - lib/azure_media_service/model/media_processor.rb
@@ -157,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
161
  version: '0'
158
162
  requirements: []
159
163
  rubyforge_project:
160
- rubygems_version: 2.2.2
164
+ rubygems_version: 2.4.5
161
165
  signing_key:
162
166
  specification_version: 4
163
167
  summary: Azure Media Service SDK for ruby