pili 1.0.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +132 -76
- data/lib/pili/api.rb +74 -0
- data/lib/pili/client.rb +48 -0
- data/lib/pili/config.rb +12 -26
- data/lib/pili/exceptions.rb +28 -0
- data/lib/pili/stream.rb +141 -0
- data/lib/pili/utils.rb +0 -5
- data/lib/pili/version.rb +1 -1
- data/lib/pili.rb +9 -140
- data/pili.gemspec +2 -2
- metadata +8 -5
- data/lib/pili/http.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb22831f58fe2ba275e403086a5d6f582db1b276
|
4
|
+
data.tar.gz: 666a132c978cca3be0e787d7e5ce71c408019d52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f502768f7388d7bff3fa9af451282fcdc3080266ca13581cb3c51e4c8592e71fde7bde1be864d081cb4038c235b82596ee4f339acc6b33a049124925be3f55d
|
7
|
+
data.tar.gz: 185233ddbda8853da59537e5ce5f87f720cc40e33b05c71ac1fa3cb713d3db4eca2ceaf970a4e6de02e87faba0483fe1f6823bed6fcfcc97098d88d35fb1f2b3
|
data/README.md
CHANGED
@@ -1,7 +1,36 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# Pili server-side library for Ruby
|
2
|
+
|
3
|
+
## Features
|
4
|
+
|
5
|
+
- [x] Stream operations (Create, Delete, Update, Get)
|
6
|
+
- [x] Get Streams list
|
7
|
+
- [x] Get Stream status
|
8
|
+
- [x] Get Stream segments
|
9
|
+
- [x] Generate RTMP publish URL
|
10
|
+
- [x] Generate RTMP / HLS live play URL
|
11
|
+
- [x] Generate HLS playback URL
|
12
|
+
|
13
|
+
## Content
|
14
|
+
|
15
|
+
- [Installation](#installation)
|
16
|
+
- [Usage](#usage)
|
17
|
+
- [Configuration](#configuration)
|
18
|
+
- [Client](#client)
|
19
|
+
- [Create a Pili client](#create-a-pili-client)
|
20
|
+
- [Create a stream](#create-a-stream)
|
21
|
+
- [Get a stream](#get-a-stream)
|
22
|
+
- [List streams](#list-streams)
|
23
|
+
- [Stream](#stream)
|
24
|
+
- [Update a stream](#update-a-stream)
|
25
|
+
- [Delete a stream](#delete-a-stream)
|
26
|
+
- [Get stream segments](#get-stream-segments)
|
27
|
+
- [Get stream status](#get-stream-status)
|
28
|
+
- [Generate RTMP publish URL](#generate-rtmp-publish-url)
|
29
|
+
- [Generate RTMP live play URL](#generate-rtmp-live-play-urls)
|
30
|
+
- [Generate HLS live play URL](#generate-hls-live-play-url)
|
31
|
+
- [Generate HLS playback URL](#generate-hls-playback-url)
|
32
|
+
- [To JSON String](#to-json-string)
|
33
|
+
- [History](#history)
|
5
34
|
|
6
35
|
## Installation
|
7
36
|
|
@@ -17,6 +46,7 @@ Or install it yourself as:
|
|
17
46
|
|
18
47
|
$ gem install pili
|
19
48
|
|
49
|
+
|
20
50
|
## Usage
|
21
51
|
|
22
52
|
### Configuration
|
@@ -24,134 +54,160 @@ Or install it yourself as:
|
|
24
54
|
```ruby
|
25
55
|
require 'pili'
|
26
56
|
|
27
|
-
|
28
|
-
|
29
|
-
```
|
30
|
-
|
31
|
-
#### with rails:
|
57
|
+
ACCESS_KEY = 'qiniu_access_key'
|
58
|
+
SECRETE_KEY = 'qiniu_secret_key'
|
32
59
|
|
33
|
-
|
60
|
+
HUB_NAME = 'hub_name'
|
61
|
+
```
|
34
62
|
|
63
|
+
### Client
|
35
64
|
|
36
|
-
|
65
|
+
#### Create a Pili client
|
37
66
|
|
38
67
|
```ruby
|
39
|
-
|
40
|
-
|
41
|
-
RTMP_PLAY_HOST = "xxx.live1.z1.pili.qiniucdn.com"
|
42
|
-
HLS_PLAY_HOST = "xxx.hls1.z1.pili.qiniucdn.com"
|
43
|
-
|
44
|
-
# Replace with your hub name
|
45
|
-
HUB_NAME = "hub_name"
|
68
|
+
client = Pili::Client.new(ACCESS_KEY, SECRETE_KEY, HUB_NAME)
|
69
|
+
# return client object...
|
46
70
|
```
|
47
71
|
|
48
|
-
|
49
|
-
#### Create Stream
|
72
|
+
#### Create a stream
|
50
73
|
|
51
74
|
```ruby
|
52
|
-
# HUB_NAME: string, required
|
53
75
|
# title: optional, default is auto-generated
|
54
76
|
# publish_key: optional, a secret key for signing the <publishToken>
|
55
77
|
# publish_security: optional, can be "dynamic" or "static", default is "dynamic"
|
56
|
-
|
78
|
+
client.create_stream(title: "title", publish_key: "publish_key", publish_security: "static")
|
79
|
+
# return stream object...
|
57
80
|
```
|
58
81
|
|
59
|
-
#### Get
|
82
|
+
#### Get a stream
|
60
83
|
|
61
84
|
```ruby
|
62
85
|
# stream_id: string, required
|
63
|
-
|
86
|
+
client.get_stream(stream_id)
|
87
|
+
# return stream object...
|
64
88
|
```
|
65
89
|
|
66
|
-
####
|
90
|
+
#### List streams
|
67
91
|
|
68
92
|
```ruby
|
69
|
-
#
|
70
|
-
|
93
|
+
# marker: string, optional
|
94
|
+
# limit: integer, optional
|
95
|
+
client.list_streams(marker: "marker", limit: 1000)
|
71
96
|
```
|
72
97
|
|
73
|
-
|
98
|
+
### Stream
|
99
|
+
|
100
|
+
#### Update a stream
|
74
101
|
|
75
102
|
```ruby
|
76
|
-
# stream_id: string, required
|
77
103
|
# publish_key: optional, a secret key for signing the <publishToken>
|
78
104
|
# publish_security: optional, can be "dynamic" or "static", default is "dynamic"
|
79
105
|
# disabled: optional, can be true or false
|
80
|
-
|
106
|
+
stream.update(publish_key: "new_key", publish_security: "dynamic", disabled: true)
|
107
|
+
# return updated stream object...
|
81
108
|
```
|
82
109
|
|
83
|
-
####
|
110
|
+
#### Delete a stream
|
84
111
|
|
85
112
|
```ruby
|
86
|
-
|
87
|
-
# marker: string, optional
|
88
|
-
# limit: integer, optional
|
89
|
-
Pili.stream_list(HUB_NAME, marker: "marker", limit: 50)
|
113
|
+
stream.delete()
|
90
114
|
```
|
91
115
|
|
92
|
-
####
|
116
|
+
#### Get stream segments
|
93
117
|
|
94
118
|
```ruby
|
95
|
-
#
|
96
|
-
|
119
|
+
# start_second: integer, optional
|
120
|
+
# end_second: integer, optional
|
121
|
+
stream.segments(start_second, end_second)
|
122
|
+
|
123
|
+
# [
|
124
|
+
# {
|
125
|
+
# "start": <StartSecond>,
|
126
|
+
# "end": <EndSecond>
|
127
|
+
# },
|
128
|
+
# {
|
129
|
+
# "start": <StartSecond>,
|
130
|
+
# "end": <EndSecond>
|
131
|
+
# },
|
132
|
+
# ...
|
133
|
+
# ]
|
97
134
|
```
|
98
135
|
|
99
|
-
#### Get
|
136
|
+
#### Get stream status
|
100
137
|
|
101
138
|
```ruby
|
102
|
-
|
103
|
-
#
|
104
|
-
|
139
|
+
stream.status()
|
140
|
+
# {
|
141
|
+
# "addr": "106.187.43.211:51393",
|
142
|
+
# "status": "disconnected"
|
143
|
+
# }
|
105
144
|
```
|
106
145
|
|
107
|
-
####
|
146
|
+
#### Generate RTMP publish URL
|
108
147
|
|
109
148
|
```ruby
|
110
|
-
|
111
|
-
#
|
112
|
-
# publish_key: string, required
|
113
|
-
# publish_security: string, required
|
114
|
-
# nonce: unix timestamp, optional
|
115
|
-
Pili.get_stream_publish_url(RTMP_PUBLISH_HOST, stream_id, publish_key, publish_security, nonce)
|
149
|
+
stream.rtmp_publish_url()
|
150
|
+
# return a rtmp publish url, eg. "rtmp://test.qiniucdn.com/hubname/test?key=publish_test_key"
|
116
151
|
```
|
117
152
|
|
118
|
-
####
|
153
|
+
#### Generate RTMP live play URLs
|
119
154
|
|
120
155
|
```ruby
|
121
|
-
|
122
|
-
#
|
123
|
-
#
|
124
|
-
|
156
|
+
stream.rtmp_live_urls()
|
157
|
+
# return rtmp live play urls, eg.
|
158
|
+
# {
|
159
|
+
# "ORIGIN" => "rtmp://test.qiniucdn.com/hubname/test",
|
160
|
+
# "240p" => "rtmp://test.qiniucdn.com/hubname/test@240p",
|
161
|
+
# ...
|
162
|
+
# }
|
125
163
|
```
|
126
164
|
|
127
|
-
####
|
165
|
+
#### Generate HLS live play URLs
|
128
166
|
|
129
167
|
```ruby
|
130
|
-
|
131
|
-
#
|
132
|
-
#
|
133
|
-
|
168
|
+
stream.hls_live_urls()
|
169
|
+
# return hls live play urls, eg.
|
170
|
+
# {
|
171
|
+
# "ORIGIN" => "http://test.qiniucdn.com/hubname/test.m3u8",
|
172
|
+
# "240p" => "http://test.qiniucdn.com/hubname/test@240p.m3u8"
|
173
|
+
# ...
|
174
|
+
# }
|
134
175
|
```
|
135
176
|
|
136
|
-
####
|
177
|
+
#### Generate HLS playback URLs
|
137
178
|
|
138
179
|
```ruby
|
139
|
-
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
|
180
|
+
stream.hls_playback_urls(start_second, end_second)
|
181
|
+
# return hls playback urls, eg.
|
182
|
+
# {
|
183
|
+
# "ORIGIN" => "http://test.qiniucdn.com/hubname/test.m3u8?start=1436843430&end=1436846938",
|
184
|
+
# "240p" => "http://test.qiniucdn.com/hubname/test@240p.m3u8?start=1436843430&end=1436846938"
|
185
|
+
# ...
|
186
|
+
# }
|
144
187
|
```
|
145
188
|
|
189
|
+
#### To JSON String
|
190
|
+
```ruby
|
191
|
+
stream.to_json()
|
192
|
+
```
|
146
193
|
|
147
|
-
##
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
194
|
+
## History
|
195
|
+
|
196
|
+
- 2.0.0
|
197
|
+
- Add Client, Stream class
|
198
|
+
- 1.0.1
|
199
|
+
- Add get stream status method.
|
200
|
+
- Update update_stream method.
|
201
|
+
- 1.0.0
|
202
|
+
- Update README create stream example code.
|
203
|
+
- 0.1.3
|
204
|
+
- Update README create stream example code.
|
205
|
+
- 0.1.2
|
206
|
+
- Fix stream list method parameter type.
|
207
|
+
- 0.1.0
|
208
|
+
- Update README
|
209
|
+
- Update get milliseconds method
|
210
|
+
- 0.0.1
|
211
|
+
- Init SDK
|
212
|
+
- Add Stream API
|
213
|
+
- Add publish and play policy
|
data/lib/pili/api.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
module Pili
|
5
|
+
module API
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def get(access_key, secret_key, url)
|
9
|
+
signature_options = {
|
10
|
+
:url => url,
|
11
|
+
:method => "GET"
|
12
|
+
}
|
13
|
+
|
14
|
+
encoded_sign = Auth.sign(secret_key, Auth.generate_signature(signature_options))
|
15
|
+
|
16
|
+
headers = { "Authorization" => "Qiniu #{access_key}:#{encoded_sign}" }
|
17
|
+
|
18
|
+
response = HTTParty.get(url, :headers => headers)
|
19
|
+
|
20
|
+
if response.code == 200
|
21
|
+
response.parsed_response
|
22
|
+
else
|
23
|
+
raise ResponseError.new("Pili API Request Error", response)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def post(access_key, secret_key, url, body)
|
29
|
+
signature_options = {
|
30
|
+
:url => url,
|
31
|
+
:content_type => "application/json",
|
32
|
+
:method => "POST",
|
33
|
+
:body => body
|
34
|
+
}
|
35
|
+
|
36
|
+
encoded_sign = Auth.sign(secret_key, Auth.generate_signature(signature_options))
|
37
|
+
|
38
|
+
headers = {
|
39
|
+
"Authorization" => "Qiniu #{access_key}:#{encoded_sign}",
|
40
|
+
"Content-Type" => "application/json"
|
41
|
+
}
|
42
|
+
|
43
|
+
response = HTTParty.post(url, :headers => headers, :body => body.to_json)
|
44
|
+
|
45
|
+
if response.code == 200
|
46
|
+
response.parsed_response
|
47
|
+
else
|
48
|
+
raise ResponseError.new("Pili API Request Error", response)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def delete(access_key, secret_key, url)
|
54
|
+
signature_options = {
|
55
|
+
:url => url,
|
56
|
+
:method => "DELETE"
|
57
|
+
}
|
58
|
+
|
59
|
+
encoded_sign = Auth.sign(secret_key, Auth.generate_signature(signature_options))
|
60
|
+
|
61
|
+
headers = { "Authorization" => "Qiniu #{access_key}:#{encoded_sign}" }
|
62
|
+
|
63
|
+
response = HTTParty.delete(url, :headers => headers)
|
64
|
+
|
65
|
+
if response.code == 204
|
66
|
+
response.parsed_response
|
67
|
+
else
|
68
|
+
raise ResponseError.new("Pili API Request Error", response)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/pili/client.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Pili
|
3
|
+
class Client
|
4
|
+
|
5
|
+
attr_reader :access_key, :secret_key, :hub_name
|
6
|
+
|
7
|
+
|
8
|
+
def initialize(access_key, secret_key, hub_name)
|
9
|
+
@access_key = access_key
|
10
|
+
@secret_key = secret_key
|
11
|
+
@hub_name = hub_name
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def create_stream(options = {})
|
16
|
+
url = Config.api_base_url + "/streams"
|
17
|
+
|
18
|
+
body = {
|
19
|
+
:hub => @hub_name,
|
20
|
+
:title => options[:title],
|
21
|
+
:publishKey => options[:publish_key],
|
22
|
+
:publishSecurity => options[:publish_security] == "static" ? "static" : "dynamic",
|
23
|
+
:clientIp => options[:client_ip]
|
24
|
+
}
|
25
|
+
|
26
|
+
body.delete_if { |k, v| v.nil? }
|
27
|
+
|
28
|
+
Stream.new self, API.post(@access_key, @secret_key, url, body)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def get_stream(stream_id)
|
33
|
+
url = Config.api_base_url + "/streams/" + stream_id
|
34
|
+
Stream.new self, API.get(@access_key, @secret_key, url)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def list_streams(options = {})
|
39
|
+
url = Config.api_base_url + "/streams?hub=#{@hub_name}"
|
40
|
+
|
41
|
+
url += "&marker=#{options[:marker]}" unless Utils.blank?(options[:marker])
|
42
|
+
url += "&limit=#{options[:limit]}" if options[:limit].is_a?(Fixnum)
|
43
|
+
|
44
|
+
API.get(@access_key, @secret_key, url)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
data/lib/pili/config.rb
CHANGED
@@ -3,34 +3,20 @@ module Pili
|
|
3
3
|
module Config
|
4
4
|
class << self
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
}
|
11
|
-
|
12
|
-
REQUIRED_OPTION_KEYS
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@settings = DEFAULT_OPTIONS.merge!(options)
|
18
|
-
REQUIRED_OPTION_KEYS.each do |opt|
|
19
|
-
raise("You did not provide both required args. Please provide the #{opt}.") unless @settings.has_key?(opt)
|
20
|
-
end
|
21
|
-
@settings
|
22
|
-
end
|
6
|
+
API_SCHEME = "http"
|
7
|
+
API_HOST = "pili.qiniuapi.com"
|
8
|
+
API_VERSION = "v1"
|
9
|
+
|
10
|
+
# def init(options = {})
|
11
|
+
# @settings = DEFAULT_OPTIONS.merge!(options)
|
12
|
+
# REQUIRED_OPTION_KEYS.each do |opt|
|
13
|
+
# raise("You did not provide both required args. Please provide the #{opt}.") unless @settings.has_key?(opt)
|
14
|
+
# end
|
15
|
+
# @settings
|
16
|
+
# end
|
23
17
|
|
24
18
|
def api_base_url
|
25
|
-
"#{
|
26
|
-
end
|
27
|
-
|
28
|
-
def access_key
|
29
|
-
settings[:access_key]
|
30
|
-
end
|
31
|
-
|
32
|
-
def secret_key
|
33
|
-
settings[:secret_key]
|
19
|
+
"#{API_SCHEME}://#{API_HOST}/#{API_VERSION}"
|
34
20
|
end
|
35
21
|
|
36
22
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Pili
|
3
|
+
class ResponseError < Exception
|
4
|
+
|
5
|
+
attr_reader :response
|
6
|
+
|
7
|
+
def initialize(message, response = nil)
|
8
|
+
@response = response
|
9
|
+
super(message)
|
10
|
+
end
|
11
|
+
|
12
|
+
def http_code
|
13
|
+
@response.code if @response
|
14
|
+
end
|
15
|
+
|
16
|
+
def error_code
|
17
|
+
@response.parsed_response["error"] if @response
|
18
|
+
end
|
19
|
+
|
20
|
+
def error_message
|
21
|
+
@response.parsed_response["message"] if @response
|
22
|
+
end
|
23
|
+
|
24
|
+
def http_body
|
25
|
+
@response.body if @response
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/pili/stream.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Pili
|
3
|
+
class Stream
|
4
|
+
|
5
|
+
LIVE_URL_ORIGIN_KEY = "ORIGIN"
|
6
|
+
|
7
|
+
attr_reader :client
|
8
|
+
attr_reader :id, :created_at, :updated_at, :title, :hub, :profiles, :hosts
|
9
|
+
|
10
|
+
attr_accessor :publish_key, :publish_security, :disabled
|
11
|
+
|
12
|
+
|
13
|
+
def initialize(client, options = {})
|
14
|
+
@client = client
|
15
|
+
@id = options["id"]
|
16
|
+
@title = options["title"]
|
17
|
+
@hub = options["hub"]
|
18
|
+
@profiles = options["profiles"] || []
|
19
|
+
@publish_key = options["publishKey"]
|
20
|
+
@publish_security = options["publishSecurity"]
|
21
|
+
@disabled = options["disabled"]
|
22
|
+
@hosts = options["hosts"]
|
23
|
+
|
24
|
+
@created_at = options["createdAt"]
|
25
|
+
@updated_at = options["updatedAt"]
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def status
|
30
|
+
url = Config.api_base_url + "/streams/#{@id}/status"
|
31
|
+
API.get(@client.access_key, @client.secret_key, url)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def update(options = {})
|
36
|
+
url = Config.api_base_url + "/streams/" + @id
|
37
|
+
|
38
|
+
body = {}
|
39
|
+
body[:publishKey] = options[:publish_key]
|
40
|
+
body[:publishSecurity] = options[:publish_security] == "static" ? "static" : "dynamic"
|
41
|
+
body[:disabled] = options[:disabled]
|
42
|
+
|
43
|
+
body.delete_if { |k, v| v.nil? }
|
44
|
+
|
45
|
+
stream = API.post(@client.access_key, @client.secret_key, url, body)
|
46
|
+
|
47
|
+
@publish_key = stream["publishKey"]
|
48
|
+
@publish_security = stream["publishSecurity"]
|
49
|
+
@disabled = stream["disabled"]
|
50
|
+
@updated_at = stream["updatedAt"]
|
51
|
+
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def delete
|
57
|
+
url = Config.api_base_url + "/streams/" + @id
|
58
|
+
API.delete(@client.access_key, @client.secret_key, url)
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def segments(options = {})
|
63
|
+
url = Config.api_base_url + "/streams/#{@id}/segments"
|
64
|
+
|
65
|
+
url += "?start=#{options[:start]}" if options[:start].is_a?(Fixnum)
|
66
|
+
url += "&end=#{options[:end]}" if options[:end].is_a?(Fixnum)
|
67
|
+
|
68
|
+
response = API.get(@client.access_key, @client.secret_key, url)
|
69
|
+
response["segments"] || []
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def rtmp_publish_url
|
74
|
+
rtmp_publish_host = @hosts["publish"]["rtmp"]
|
75
|
+
|
76
|
+
if @publish_security == "static"
|
77
|
+
return "rtmp://#{rtmp_publish_host}/#{@hub}/#{@title}?key=#{@publish_key}"
|
78
|
+
else
|
79
|
+
nonce = (Time.now.to_f * 1000.0).to_i
|
80
|
+
token = Auth.sign(publish_key, "/#{@hub}/#{@title}?nonce=#{nonce}")
|
81
|
+
return "rtmp://#{rtmp_publish_host}/#{@hub}/#{@title}?nonce=#{nonce}&token=#{token}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def rtmp_live_urls
|
87
|
+
rtmp_play_host = @hosts["play"]["rtmp"]
|
88
|
+
|
89
|
+
urls = { LIVE_URL_ORIGIN_KEY => "rtmp://#{rtmp_play_host}/#{@hub}/#{@title}" }
|
90
|
+
|
91
|
+
@profiles.each do |profile|
|
92
|
+
urls[profile] = "rtmp://#{rtmp_play_host}/#{@hub}/#{@title}@#{profile}"
|
93
|
+
end
|
94
|
+
|
95
|
+
urls
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def hls_live_urls
|
100
|
+
hls_play_host = @hosts["play"]["hls"]
|
101
|
+
|
102
|
+
urls = { LIVE_URL_ORIGIN_KEY => "http://#{hls_play_host}/#{@hub}/#{@title}.m3u8" }
|
103
|
+
|
104
|
+
@profiles.each do |profile|
|
105
|
+
urls[profile] = "http://#{hls_play_host}/#{@hub}/#{@title}@#{profile}.m3u8"
|
106
|
+
end
|
107
|
+
|
108
|
+
urls
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def hls_playback_urls(start_second, end_second)
|
113
|
+
hls_play_host = @hosts["play"]["hls"]
|
114
|
+
|
115
|
+
urls = { LIVE_URL_ORIGIN_KEY => "http://#{hls_play_host}/#{@hub}/#{@title}.m3u8?start=#{start_second}&end=#{end_second}" }
|
116
|
+
|
117
|
+
@profiles.each do |profile|
|
118
|
+
urls[profile] = "http://#{hls_play_host}/#{@hub}/#{@title}@#{profile}.m3u8?start=#{start_second}&end=#{end_second}"
|
119
|
+
end
|
120
|
+
|
121
|
+
urls
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
def to_json
|
126
|
+
{
|
127
|
+
id: @id,
|
128
|
+
title: @title,
|
129
|
+
hub: @hub,
|
130
|
+
profiles: @profiles,
|
131
|
+
publish_key: @publish_key,
|
132
|
+
publish_security: @publish_security,
|
133
|
+
disabled: @disabled,
|
134
|
+
hosts: @hosts,
|
135
|
+
created_at: @created_at,
|
136
|
+
updated_at: @updated_at
|
137
|
+
}.to_json
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
data/lib/pili/utils.rb
CHANGED
data/lib/pili/version.rb
CHANGED
data/lib/pili.rb
CHANGED
@@ -4,143 +4,12 @@ require 'httparty'
|
|
4
4
|
require "pili/version"
|
5
5
|
|
6
6
|
module Pili
|
7
|
-
autoload :Auth,
|
8
|
-
autoload :Config,
|
9
|
-
autoload :
|
10
|
-
autoload :Utils,
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
def stream_list(hub, options = {})
|
20
|
-
url = Config.api_base_url + "/streams?hub=#{hub}"
|
21
|
-
|
22
|
-
url += "&marker=#{options[:marker]}" unless Utils.blank?(options[:marker])
|
23
|
-
url += "&limit=#{options[:limit]}" if options[:limit].is_a?(Fixnum)
|
24
|
-
|
25
|
-
response = HTTP.api_get(url)
|
26
|
-
response.parsed_response
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
def create_stream(hub, options = {})
|
31
|
-
url = Config.api_base_url + "/streams"
|
32
|
-
|
33
|
-
body = {
|
34
|
-
:hub => hub,
|
35
|
-
:title => options[:title],
|
36
|
-
:publishKey => options[:publish_key],
|
37
|
-
:publishSecurity => options[:publish_security] == "static" ? "static" : "dynamic",
|
38
|
-
:clientIp => options[:client_ip]
|
39
|
-
}
|
40
|
-
|
41
|
-
body.delete_if { |k, v| v.nil? }
|
42
|
-
|
43
|
-
response = HTTP.api_post(url, body)
|
44
|
-
response.parsed_response
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
def get_stream(stream_id)
|
49
|
-
url = Config.api_base_url + "/streams/" + stream_id
|
50
|
-
response = HTTP.api_get(url)
|
51
|
-
response.parsed_response
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
def get_stream_status(stream_id)
|
56
|
-
url = Config.api_base_url + "/streams/#{stream_id}/status"
|
57
|
-
response = HTTP.api_get(url)
|
58
|
-
response.parsed_response
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
|
-
def update_stream(stream_id, options = {})
|
63
|
-
url = Config.api_base_url + "/streams/" + stream_id
|
64
|
-
|
65
|
-
body = {
|
66
|
-
:publishKey => options[:publish_key],
|
67
|
-
:publishSecurity => options[:publish_security] == "static" ? "static" : "dynamic",
|
68
|
-
:disabled => options[:disabled]
|
69
|
-
}
|
70
|
-
|
71
|
-
body.delete_if { |k, v| v.nil? }
|
72
|
-
|
73
|
-
response = HTTP.api_post(url, body)
|
74
|
-
response.parsed_response
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
def delete_stream(stream_id)
|
79
|
-
url = Config.api_base_url + "/streams/" + stream_id
|
80
|
-
response = HTTP.api_delete(url)
|
81
|
-
response.parsed_response
|
82
|
-
end
|
83
|
-
|
84
|
-
|
85
|
-
def get_stream_segments(stream_id, options = {})
|
86
|
-
url = Config.api_base_url + "/streams/#{stream_id}/segments"
|
87
|
-
|
88
|
-
url += "?start=#{options[:start]}" if options[:start].is_a?(Fixnum)
|
89
|
-
url += "&end=#{options[:end]}" if options[:end].is_a?(Fixnum)
|
90
|
-
|
91
|
-
response = HTTP.api_get(url)
|
92
|
-
response.parsed_response
|
93
|
-
end
|
94
|
-
|
95
|
-
|
96
|
-
def get_stream_publish_url(publish_host, stream_id, publish_key, publish_security, nonce = nil)
|
97
|
-
nonce = nonce.to_i
|
98
|
-
nonce = (Time.now.to_f * 1000.0).to_i if nonce == 0
|
99
|
-
|
100
|
-
hub, title = Utils.get_stream_hub_and_title(stream_id)
|
101
|
-
|
102
|
-
if publish_security == "static"
|
103
|
-
return "rtmp://#{publish_host}/#{hub}/#{title}?key=#{publish_key}"
|
104
|
-
else
|
105
|
-
token = Auth.sign(publish_key, "/#{hub}/#{title}?nonce=#{nonce}")
|
106
|
-
return "rtmp://#{publish_host}/#{hub}/#{title}?nonce=#{nonce}&token=#{token}"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
|
111
|
-
def get_stream_rtmp_live_url(play_host, stream_id, preset = nil)
|
112
|
-
hub, title = Utils.get_stream_hub_and_title(stream_id)
|
113
|
-
|
114
|
-
if Utils.blank? preset
|
115
|
-
return "rtmp://#{play_host}/#{hub}/#{title}"
|
116
|
-
else
|
117
|
-
return "rtmp://#{play_host}/#{hub}/#{title}@#{preset}"
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
|
122
|
-
def get_stream_hls_live_url(play_host, stream_id, preset = nil)
|
123
|
-
hub, title = Utils.get_stream_hub_and_title(stream_id)
|
124
|
-
|
125
|
-
if Utils.blank? preset
|
126
|
-
return "http://#{play_host}/#{hub}/#{title}.m3u8"
|
127
|
-
else
|
128
|
-
return "http://#{play_host}/#{hub}/#{title}@#{preset}.m3u8"
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
|
133
|
-
def get_stream_hls_playback_url(play_host, stream_id, start_second, end_second, preset = nil)
|
134
|
-
hub, title = Utils.get_stream_hub_and_title(stream_id)
|
135
|
-
|
136
|
-
if Utils.blank? preset
|
137
|
-
return "http://#{play_host}/#{hub}/#{title}.m3u8?start=#{start_second}&end=#{end_second}"
|
138
|
-
else
|
139
|
-
return "http://#{play_host}/#{hub}/#{title}@#{preset}.m3u8?start=#{start_second}&end=#{end_second}"
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|
7
|
+
autoload :Auth, 'pili/auth'
|
8
|
+
autoload :Config, 'pili/config'
|
9
|
+
autoload :API, 'pili/api'
|
10
|
+
autoload :Utils, 'pili/utils'
|
11
|
+
autoload :ResponseError, 'pili/exceptions'
|
12
|
+
|
13
|
+
autoload :Client, 'pili/client'
|
14
|
+
autoload :Stream, 'pili/stream'
|
15
|
+
end
|
data/pili.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Miclle"]
|
10
10
|
spec.email = ["pili@qiniu.com"]
|
11
11
|
spec.summary = %q{Pili SDK for Ruby.}
|
12
|
-
spec.description = %q{Pili SDK for Ruby. https://github.com/pili-
|
13
|
-
spec.homepage = "https://github.com/pili-
|
12
|
+
spec.description = %q{Pili SDK for Ruby. https://github.com/pili-engineering/pili-sdk-ruby}
|
13
|
+
spec.homepage = "https://github.com/pili-engineering/pili-sdk-ruby"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pili
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miclle
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.13.3
|
55
|
-
description: Pili SDK for Ruby. https://github.com/pili-
|
55
|
+
description: Pili SDK for Ruby. https://github.com/pili-engineering/pili-sdk-ruby
|
56
56
|
email:
|
57
57
|
- pili@qiniu.com
|
58
58
|
executables: []
|
@@ -66,13 +66,16 @@ files:
|
|
66
66
|
- README.md
|
67
67
|
- Rakefile
|
68
68
|
- lib/pili.rb
|
69
|
+
- lib/pili/api.rb
|
69
70
|
- lib/pili/auth.rb
|
71
|
+
- lib/pili/client.rb
|
70
72
|
- lib/pili/config.rb
|
71
|
-
- lib/pili/
|
73
|
+
- lib/pili/exceptions.rb
|
74
|
+
- lib/pili/stream.rb
|
72
75
|
- lib/pili/utils.rb
|
73
76
|
- lib/pili/version.rb
|
74
77
|
- pili.gemspec
|
75
|
-
homepage: https://github.com/pili-
|
78
|
+
homepage: https://github.com/pili-engineering/pili-sdk-ruby
|
76
79
|
licenses:
|
77
80
|
- MIT
|
78
81
|
metadata: {}
|
data/lib/pili/http.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
require 'httparty'
|
3
|
-
|
4
|
-
module Pili
|
5
|
-
class HTTP
|
6
|
-
|
7
|
-
include HTTParty
|
8
|
-
format :json
|
9
|
-
|
10
|
-
class << self
|
11
|
-
|
12
|
-
def api_get(url)
|
13
|
-
signature_options = {
|
14
|
-
:url => url,
|
15
|
-
:method => "GET"
|
16
|
-
}
|
17
|
-
|
18
|
-
encoded_sign = Auth.sign(Config.secret_key, Auth.generate_signature(signature_options))
|
19
|
-
|
20
|
-
headers = { "Authorization" => "Qiniu #{Config.access_key}:#{encoded_sign}" }
|
21
|
-
|
22
|
-
get(url, :headers => headers)
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
def api_post(url, body)
|
27
|
-
signature_options = {
|
28
|
-
:url => url,
|
29
|
-
:content_type => "application/json",
|
30
|
-
:method => "POST",
|
31
|
-
:body => body
|
32
|
-
}
|
33
|
-
|
34
|
-
encoded_sign = Auth.sign(Config.secret_key, Auth.generate_signature(signature_options))
|
35
|
-
|
36
|
-
headers = {
|
37
|
-
"Authorization" => "Qiniu #{Config.access_key}:#{encoded_sign}",
|
38
|
-
"Content-Type" => "application/json"
|
39
|
-
}
|
40
|
-
|
41
|
-
post(url, :headers => headers, :body => body.to_json)
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
def api_delete(url)
|
46
|
-
signature_options = {
|
47
|
-
:url => url,
|
48
|
-
:method => "DELETE"
|
49
|
-
}
|
50
|
-
|
51
|
-
encoded_sign = Auth.sign(Config.secret_key, Auth.generate_signature(signature_options))
|
52
|
-
|
53
|
-
headers = { "Authorization" => "Qiniu #{Config.access_key}:#{encoded_sign}" }
|
54
|
-
|
55
|
-
delete(url, :headers => headers)
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|