pili 1.0.1 → 1.2.0
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.
- 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
|