piliv2 2.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 698dc78d73f17a61df99562bafa0147e5b0a03cc
4
+ data.tar.gz: 805206f6c3a86feeaf724fae2b3ef338a831dba8
5
+ SHA512:
6
+ metadata.gz: 71ff1db811bc913d6982f2a75785342747db9737c9a0e53961d48dfc774b908dc47320822689e8f12f5ff1d81ff1235449b3834aa5bd820dab6f0b25b36772a3
7
+ data.tar.gz: 1517952e3cfd76a6e3eb9500fe02a6e974dea49d9661c31f1675188c0c3be476e3d995ffb95cfc7ab04bb49ce76a7492f0232a79d5e5e2dc3ae01ab019c69648
data/.gitignore ADDED
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.5
4
+ gemfile:
5
+ - Gemfile
6
+ deploy:
7
+ provider: rubygems
8
+ api_key:
9
+ secure: frhK5TRyrplKjwEktkjx4nGyXBhELae7B/rfDTWUqLrwX4Gmx2XTf0j3VSwKphf2PclW2Phs1o029JFjivgjCB0gYpb4/lgPLxXAjYoUv7cbyZ1SdvIkhJsxilPgkPOr/t6XZ4OB1WU0yLJxDKNyJCh6fHJ47OlMfy7neGPtFKI=
10
+ gemspec: pili.gemspec
11
+ on:
12
+ tags: true
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pili.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 pili.qiniu.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,224 @@
1
+ # Pili Streaming Cloud server-side library for Ruby
2
+
3
+ ## Features
4
+
5
+ - URL
6
+ - [x] RTMP推流地址: rtmp_publish_url(domain, hub, stream_key, mac, expire_after_seconds)
7
+ - [x] RTMP直播地址: rtmp_play_url(domain, hub, stream_key)
8
+ - [x] HLS直播地址: hls_play_url(domain, hub, stream_key)
9
+ - [x] HDL直播地址: hdl_play_url(domain, hub, stream_key)
10
+ - [x] 截图直播地址: snapshot_play_url(domain, hub, stream_key)
11
+ - Hub
12
+ - [x] 创建流: hub.create(stream_key)
13
+ - [x] 获得流: hub.stream(stream_key)
14
+ - [x] 列出流: hub.list(...)
15
+ - [x] 列出正在直播的流: hub.list_live(...)
16
+ - Stream
17
+ - [x] 流信息: stream.info()
18
+ - [x] 禁用流: stream.disable()
19
+ - [x] 启用流: stream.enable()
20
+ - [x] 查询直播状态: stream.live_status()
21
+ - [x] 保存直播回放: stream.save(...)
22
+ - [x] 查询直播历史: stream.history_activity(...)
23
+
24
+ ## Contents
25
+
26
+ - [Installation](#installation)
27
+ - [Usage](#usage)
28
+ - [Configuration](#configuration)
29
+ - [URL](#url)
30
+ - [Generate RTMP publish URL](#generate-rtmp-publish-url)
31
+ - [Generate RTMP play URL](#generate-rtmp-play-url)
32
+ - [Generate HLS play URL](#generate-hls-play-url)
33
+ - [Generate HDL play URL](#generate-hdl-play-url)
34
+ - [Generate Snapshot play URL](#generate-snapshot-play-url)
35
+ - [Hub](#hub)
36
+ - [Instantiate a Pili Hub object](#instantiate-a-pili-hub-object)
37
+ - [Create a new Stream](#create-a-new-stream)
38
+ - [Get a Stream](#get-a-stream)
39
+ - [List Streams](#list-streams)
40
+ - [List live Streams](#list-live-streams)
41
+ - [Stream](#stream)
42
+ - [Get Stream info](#get-stream-info)
43
+ - [Disable a Stream](#disable-a-stream)
44
+ - [Enable a Stream](#enable-a-stream)
45
+ - [Get Stream live status](#get-stream-live-status)
46
+ - [Get Stream history activity](#get-stream-history-activity)
47
+ - [Save Stream live playback](#save-stream-live-playback)
48
+
49
+ ## Installation
50
+
51
+ Add this line to your application's Gemfile:
52
+
53
+ gem 'piliv2'
54
+
55
+ And then execute:
56
+
57
+ $ bundle
58
+
59
+ Or install it yourself as:
60
+
61
+ $ gem install piliv2
62
+
63
+
64
+ ## Usage
65
+
66
+ ### Configuration
67
+
68
+ ```ruby
69
+ require "piliv2"
70
+
71
+ access_key = "<QINIU ACCESS KEY>" # 替换成自己 Qiniu 账号的 AccessKey.
72
+ secret_key = "<QINIU SECRET KEY>" # 替换成自己 Qiniu 账号的 SecretKey.
73
+ hub_name = "<PILI HUB NAME>" # Hub 必须事先存在.
74
+
75
+ mac = Pili::Mac.new(access_key, secret_key)
76
+ client = Pili::Client.new(mac)
77
+ hub = client.hub(hub_name)
78
+ ```
79
+
80
+ ### URL
81
+
82
+ #### Generate RTMP publish URL
83
+
84
+ ```ruby
85
+ url = Pili.rtmp_publish_url("publish-rtmp.test.com", "PiliSDKTest", "streamkey", 60)
86
+ puts(url)
87
+ # rtmp://publish-rtmp.test.com/PiliSDKTest/streamkey?e=1463023142&token=7O7hf7Ld1RrC_fpZdFvU8aCgOPuhw2K4eapYOdII:-5IVlpFNNGJHwv-2qKwVIakC0ME=
88
+ ```
89
+
90
+ #### Generate RTMP play URL
91
+
92
+ ```ruby
93
+ url = Pili.rtmp_play_url("live-rtmp.test.com", "PiliSDKTest", "streamkey")
94
+ puts(url)
95
+ # rtmp://live-rtmp.test.com/PiliSDKTest/streamkey
96
+ ```
97
+
98
+ #### Generate HLS play URL
99
+
100
+ ```ruby
101
+ url = Pili.hls_play_url("live-hls.test.com", "PiliSDKTest", "streamkey")
102
+ puts(url)
103
+ # http://live-hls.test.com/PiliSDKTest/streamkey.m3u8
104
+ ```
105
+
106
+ #### Generate HDL play URL
107
+
108
+ ```ruby
109
+ url = Pili.hdl_play_url("live-hdl.test.com", "PiliSDKTest", "streamkey")
110
+ puts(url)
111
+ # http://live-hdl.test.com/PiliSDKTest/streamkey.flv
112
+ ```
113
+
114
+ #### Generate Snapshot play URL
115
+
116
+ ```ruby
117
+ url = Pili.snapshot_play_url("live-snapshot.test.com", "PiliSDKTest", "streamkey")
118
+ puts(url)
119
+ # http://live-snapshot.test.com/PiliSDKTest/streamkey.jpg
120
+ ```
121
+
122
+ ### Hub
123
+
124
+ #### Instantiate a Pili Hub object
125
+
126
+ ```ruby
127
+ mac = Pili::Mac.new(access_key, secret_key)
128
+ client = Pili::Client.new(mac)
129
+ hub = client.hub("PiliSDKTest")
130
+ ```
131
+
132
+ #### Create a new Stream
133
+
134
+ ```ruby
135
+ stream = hub.create("streamkey")
136
+ puts(stream.info.to_json)
137
+ # {"hub":"PiliSDKTest","key":"streamkey","disabled":false}
138
+ ```
139
+
140
+ #### Get a Stream
141
+
142
+ ```ruby
143
+ stream = hub.stream("streamkey")
144
+ puts(stream.info.to_json)
145
+ # {"hub":"PiliSDKTest","key":"streamkey","disabled":false}
146
+ ```
147
+
148
+ #### List Streams
149
+
150
+ ```ruby
151
+ keys, marker = hub.list(:prefix=>"str", :limit=>10)
152
+ puts keys.to_s, marker
153
+ # [<keys...>], <marker>
154
+ ```
155
+
156
+ #### List live Streams
157
+
158
+ ```ruby
159
+ keys, marker = hub.list_live(:prefix=>"str", :limit=>10)
160
+ puts keys.to_s, marker
161
+ # [<keys...>], <marker>
162
+ ```
163
+
164
+ ### Stream
165
+
166
+ #### Get Stream info
167
+
168
+ ```ruby
169
+ stream = hub.stream(key)
170
+ puts(stream.info.to_json)
171
+ # {"hub": "PiliSDKTest", "key": "streamkey", "disabled": false}
172
+ ```
173
+
174
+ #### Disable a Stream
175
+
176
+ ```ruby
177
+ stream = hub.stream("streamkey")
178
+ puts("before disable: #{stream.info.to_json}")
179
+
180
+ stream.disable()
181
+
182
+ stream = hub.stream("streamkey")
183
+ puts("after disable: #{stream.info.to_json}")
184
+ # before disable: {"hub":"PiliSDKTest","key":"streamkey","disabled":false}
185
+ # after disable: {"hub":"PiliSDKTest","key":"streamkey","disabled":true}
186
+ ```
187
+
188
+ #### Enable a Stream
189
+
190
+ ```ruby
191
+ stream = hub.stream("streamkey")
192
+ puts("before enable: #{stream.info.to_json}")
193
+
194
+ stream.enable()
195
+
196
+ stream = hub.get("streamkey")
197
+ puts("after enable: #{stream.info.to_json}")
198
+ # before disable: {"hub":"PiliSDKTest","key":"streamkey","disabled":true}
199
+ # after disable: {"hub":"PiliSDKTest","key":"streamkey","disabled":false}
200
+ ```
201
+
202
+ #### Get Stream live status
203
+
204
+ ```ruby
205
+ status = stream.live_status()
206
+ puts(status.to_json)
207
+ # {"startAt":1463022236,"clientIP":"222.73.202.226","bps":248,"fps":{"audio":45,"vedio":28,"data":0}}
208
+ ```
209
+
210
+ #### Get Stream history activity
211
+
212
+ ```ruby
213
+ activity = stream.history_activity()
214
+ puts(activity.to_json)
215
+ # [{"start":1463022236,"end":1463022518}]
216
+ ```
217
+
218
+ #### Save Stream live playback
219
+
220
+ ```ruby
221
+ fname = stream.save()
222
+ puts(fname)
223
+ # recordings/z1.PiliSDKTest.streamkey/1463156847_1463157463.m3u8
224
+ ```
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :default => [] # Just in case it hasn't already been set
@@ -0,0 +1,111 @@
1
+ require 'pili'
2
+
3
+ access_key = ENV["PILI_ACCESS_KEY"]
4
+ secret_key = ENV["PILI_SECRET_KEY"]
5
+
6
+ hub_name = ENV["PILI_HUB_NAME"]
7
+
8
+ if access_key == nil || secret_key == nil
9
+ raise 'access_key = #{access_key} secret_key = #{secret_key}'
10
+ end
11
+
12
+ srand
13
+ stream_key_prefix = "ruby-sdkexample-#{rand 1000000000}"
14
+
15
+ puts "初始化 client."
16
+ mac = Pili::Mac.new access_key, secret_key
17
+ client = Pili::Client.new mac
18
+ hub = client.hub hub_name
19
+
20
+ puts "获得不存在的流."
21
+ key_a = stream_key_prefix + "-a"
22
+ begin
23
+ stream_a = hub.stream key_a
24
+ stream_a.info
25
+ rescue Pili::ResourceNotExist => e
26
+ puts e
27
+ end
28
+
29
+ puts "创建流."
30
+ stream_a = hub.create(key_a)
31
+ puts stream_a.info
32
+
33
+ puts "获得流."
34
+ stream_a = hub.stream(key_a)
35
+ puts "to_json: #{stream_a.info.to_json}"
36
+
37
+ puts "创建重复的流."
38
+ begin
39
+ hub.create(key_a)
40
+ rescue Pili::ResourceConflict => e
41
+ puts e
42
+ end
43
+
44
+ puts "创建另一路流."
45
+ key_b = stream_key_prefix + "-b"
46
+ stream_b = hub.create(key_b)
47
+ puts stream_b.info
48
+
49
+ puts "列出所有流."
50
+ begin
51
+ keys, marker = hub.list(:prefix=>stream_key_prefix)
52
+ puts keys.to_s, marker
53
+ rescue Pili::ResourceNotExist => e
54
+ puts e
55
+ end
56
+
57
+ puts "列出正在直播的流."
58
+ begin
59
+ keys, marker = hub.list_live(:prefix=>stream_key_prefix)
60
+ puts keys.to_s, marker
61
+ rescue Pili::ResourceNotExist => e
62
+ puts e
63
+ end
64
+
65
+ puts "禁用流."
66
+ stream_a.disable()
67
+ puts stream_a.info
68
+
69
+ puts "启用流."
70
+ stream_a.enable()
71
+ puts stream_a.info
72
+
73
+ puts "查询直播状态."
74
+ begin
75
+ status = stream_a.live_status()
76
+ puts keys, marker
77
+ rescue Pili::ResourceNotExist => e
78
+ puts e
79
+ end
80
+
81
+ puts "查询推流历史."
82
+ activity = stream_a.history_activity()
83
+ puts activity
84
+
85
+ puts "保存直播数据."
86
+ begin
87
+ fname = stream_a.save()
88
+ puts fname
89
+ rescue Exception => e
90
+ puts e
91
+ end
92
+
93
+ puts "RTMP 推流地址."
94
+ url = Pili.rtmp_publish_url("publish-rtmp.test.com", hub_name, key_a, mac, 3600)
95
+ puts url
96
+
97
+ puts "RTMP 直播放址."
98
+ url = Pili.rtmp_play_url("live-rtmp.test.com", hub_name, key_a)
99
+ puts url
100
+
101
+ puts "HLS 直播地址."
102
+ url = Pili.hls_play_url("live-hls.test.com", hub_name, key_a)
103
+ puts url
104
+
105
+ puts "HDL 直播地址."
106
+ url = Pili.hdl_play_url("live-hdl.test.com", hub_name, key_a)
107
+ puts url
108
+
109
+ puts "截图直播地址"
110
+ url = Pili.snapshot_play_url("live-snapshot.test.com", hub_name, key_a)
111
+ puts url
data/lib/pili/auth.rb ADDED
@@ -0,0 +1,48 @@
1
+ # coding: utf-8
2
+ require 'digest/hmac'
3
+ require "base64"
4
+
5
+ module Pili
6
+ class Mac
7
+
8
+ attr_reader :access_key, :secret_key
9
+
10
+ def initialize(access_key, secret_key)
11
+ @access_key = access_key
12
+ @secret_key = secret_key
13
+ end
14
+
15
+ def sign(data)
16
+ signature = Base64.urlsafe_encode64(Digest::HMAC.digest(data, @secret_key, Digest::SHA1))
17
+ "#{@access_key}:#{signature}"
18
+ end
19
+
20
+ def inc_body(req, content_type)
21
+ type_ok = content_type != nil && content_type != "application/octet-stream"
22
+ length_ok = req.content_length != nil && req.content_length > 0 && req.content_length < 1024*1024
23
+ req.body != nil && type_ok && length_ok
24
+ end
25
+
26
+ def sign_request(req)
27
+ data = "#{req.method} #{req.path}"
28
+
29
+ # FIXME: how to deal with port, because default uri.port is 80
30
+ data += "\nHost: #{req.uri.host}"
31
+
32
+ content_type = req["Content-Type"]
33
+ if content_type != nil
34
+ data += "\nContent-Type: #{content_type}"
35
+ end
36
+
37
+ data += "\n\n"
38
+
39
+ if inc_body(req, content_type)
40
+ data += "#{req.body}"
41
+ end
42
+
43
+ sign(data)
44
+ end
45
+
46
+ private :inc_body
47
+ end
48
+ end
@@ -0,0 +1,48 @@
1
+ # coding: utf-8
2
+
3
+ module Pili
4
+ class Client
5
+ attr_reader :mac, :rpc
6
+
7
+ def initialize(mac)
8
+ @mac = mac
9
+ @rpc = RPC.new mac
10
+ end
11
+
12
+ # hub 初始化一个 Hub.
13
+ def hub(hub_name)
14
+ Hub.new hub_name, self
15
+ end
16
+ end
17
+
18
+ class << self
19
+ # 生成 RTMP 推流地址.
20
+ # +expire_after_seconds+ 表示 URL 在多久之后失效.
21
+ def rtmp_publish_url(domain, hub, stream_key, mac, expire_after_seconds)
22
+ expire = Time.new.to_i + expire_after_seconds
23
+ path = "/#{hub}/#{stream_key}?e=#{expire}"
24
+ token = mac.sign(path)
25
+ "rtmp://#{domain}#{path}&token=#{token}"
26
+ end
27
+
28
+ # 生成 RTMP 直播地址.
29
+ def rtmp_play_url(domain, hub, stream_key)
30
+ "rtmp://#{domain}/#{hub}/#{stream_key}"
31
+ end
32
+
33
+ # 生成 HLS 直播地址.
34
+ def hls_play_url(domain, hub, stream_key)
35
+ "http://#{domain}/#{hub}/#{stream_key}.m3u8"
36
+ end
37
+
38
+ # 生成 HDL 直播地址.
39
+ def hdl_play_url(domain, hub, stream_key)
40
+ "http://#{domain}/#{hub}/#{stream_key}.flv"
41
+ end
42
+
43
+ # 生成截图直播地址.
44
+ def snapshot_play_url(domain, hub, stream_key)
45
+ "http://#{domain}/#{hub}/#{stream_key}.jpg"
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ module Pili
3
+ module Config
4
+ class << self
5
+
6
+ @@settings = {
7
+ :api_scheme => "http",
8
+ :api_host => "pili.qiniuapi.com",
9
+ :api_version => "v2",
10
+ :api_user_agent => "pili-sdk-ruby/v2-#{Pili::VERSION} Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
11
+ }
12
+
13
+ def init(options = {})
14
+ @@settings.merge!(options)
15
+ end
16
+
17
+ def api_base_url
18
+ "#{@@settings[:api_scheme]}://#{@@settings[:api_host]}/#{@@settings[:api_version]}"
19
+ end
20
+
21
+ def user_agent
22
+ @@settings[:api_user_agent]
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+
3
+ require "json"
4
+
5
+ module Pili
6
+
7
+ class RPCError < Exception
8
+
9
+ attr_reader :resp
10
+
11
+ def initialize(message, resp)
12
+ @resp = resp
13
+ super(message)
14
+ end
15
+
16
+ def code
17
+ resp.code
18
+ end
19
+
20
+ def reqid
21
+ resp["X-Reqid"]
22
+ end
23
+
24
+ def message
25
+ to_s
26
+ end
27
+
28
+ def to_s
29
+ "#{super.to_s}: #{@resp.body}"
30
+ end
31
+ end
32
+
33
+ # 资源已存在冲突错误
34
+ class ResourceConflict < RPCError
35
+ end
36
+
37
+ # 资源不存在错误
38
+ class ResourceNotExist < RPCError
39
+ end
40
+
41
+ end
data/lib/pili/hub.rb ADDED
@@ -0,0 +1,93 @@
1
+ # coding: utf-8
2
+ module Pili
3
+ # Hub 表示一个 Hub, 一个 Hub 包含多个 Stream
4
+ class Hub
5
+
6
+ attr_reader :hub
7
+
8
+ def initialize(hub, client)
9
+ @hub = hub
10
+ @client = client
11
+ @base_url = "#{Config.api_base_url}/hubs/#{hub}"
12
+ end
13
+
14
+ # 创建一个流对象.
15
+ # 使用一个合法 rtmp_publish_url 发起推流就会自动创建流对象.
16
+ # 一般情况下不需要调用这个 API, 除非是想提前对这一个流做一些特殊配置.
17
+ def create(stream_key)
18
+ @client.rpc.call_with_json("POST", "#{@base_url}/streams", {:key => stream_key})
19
+ Stream.new(@hub, stream_key, @client)
20
+ end
21
+
22
+ # 初始化一个流对象.
23
+ def stream(stream_key)
24
+ Stream.new(@hub, stream_key, @client)
25
+ end
26
+
27
+ def plist(opt = {})
28
+ opt[:liveonly] ||= false
29
+ opt[:prefix] ||= ""
30
+ opt[:limit] ||= 0
31
+ opt[:marker] ||= ""
32
+
33
+ ret = @client.rpc.call_with_json("GET", "#{@base_url}/streams?#{URI.encode_www_form opt}", nil)
34
+ [ret["items"].map{|x| x["key"]}, ret["marker"]]
35
+ end
36
+ private :plist
37
+
38
+ # list 根据 prefix 遍历 Hub 的流列表.
39
+ #
40
+ # 参数:
41
+ #
42
+ # limit 限定了一次最多可以返回的流个数, 实际返回的流个数可能小于这个 limit 值.
43
+ # marker 是上一次遍历得到的流标.
44
+ # omarker 记录了此次遍历到的游标, 在下次请求时应该带上, 如果 omarker 为 "" 表示已经遍历完所有流.
45
+ #
46
+ # For example:
47
+ #
48
+ # marker = ""
49
+ # while true
50
+ # keys, marker = hub.list(:marker=> marker)
51
+ # # do something with keys.
52
+ # if marker == ""
53
+ # break
54
+ # end
55
+ # end
56
+ def list(opt = {})
57
+ opt[:liveonly] = false
58
+ plist(opt)
59
+ end
60
+
61
+ # list 根据 prefix 遍历 Hub 正在播放的流列表.
62
+ #
63
+ # 参数:
64
+ #
65
+ # limit 限定了一次最多可以返回的流个数, 实际返回的流个数可能小于这个 limit 值.
66
+ # marker 是上一次遍历得到的流标.
67
+ # omarker 记录了此次遍历到的游标, 在下次请求时应该带上, 如果 omarker 为 "" 表示已经遍历完所有流.
68
+ #
69
+ # For example:
70
+ #
71
+ # marker = ""
72
+ # while true
73
+ # keys, marker = hub.list_live(:marker=> marker)
74
+ # # do something with keys.
75
+ # if marker == ""
76
+ # break
77
+ # end
78
+ # end
79
+ def list_live(opt = {})
80
+ opt[:liveonly] = true
81
+ plist(opt)
82
+ end
83
+
84
+ def to_s
85
+ "#<#{self.class} #{@hub}>"
86
+ end
87
+
88
+ def to_json
89
+ {:hub=>@hub}.to_json
90
+ end
91
+
92
+ end
93
+ end
data/lib/pili/rpc.rb ADDED
@@ -0,0 +1,60 @@
1
+ # coding: utf-8
2
+ require "json"
3
+ require "net/http"
4
+
5
+ module Pili
6
+ class RPC
7
+ def initialize(mac)
8
+ @mac = mac
9
+ end
10
+
11
+ def new_request(method, url)
12
+ case method
13
+ when "POST"
14
+ req = Net::HTTP::Post.new(URI(url))
15
+ when "GET"
16
+ req = Net::HTTP::Get.new(URI(url))
17
+ else
18
+ raise "unsupport RPC method #{method}"
19
+ end
20
+ req["User-Agent"] = Config.user_agent()
21
+ req
22
+ end
23
+
24
+ def request(req)
25
+ req["Authorization"] = "Qiniu #{@mac.sign_request req}"
26
+ Net::HTTP.start(req.uri.host, req.uri.port) {|http| http.request req}
27
+ end
28
+
29
+ def call_with_json(method, url, params)
30
+ req = new_request(method, url)
31
+
32
+ if method == "POST" && params != nil
33
+ req.body = params.to_json
34
+ req["Content-Type"] = "application/json"
35
+ req["Content-Length"] = req.body.length
36
+ end
37
+ resp = request(req)
38
+ if resp.code.start_with? "2"
39
+ if resp["Content-Type"] == "application/json"
40
+ JSON.load resp.body
41
+ else
42
+ resp.body
43
+ end
44
+ else
45
+ msg = "call #{url} failed: #{resp.code}"
46
+ case resp.code
47
+ when '612', '619'
48
+ e = ResourceNotExist.new msg, resp
49
+ when '614'
50
+ e = ResourceConflict.new msg, resp
51
+ else
52
+ e = RPCError.new msg, resp
53
+ end
54
+ raise e
55
+ end
56
+ end
57
+ end
58
+
59
+ private_constant :RPC
60
+ end
@@ -0,0 +1,115 @@
1
+ # coding: utf-8
2
+
3
+ require "base64"
4
+
5
+ module Pili
6
+ class StreamInfo
7
+ attr_reader :hub, :key
8
+
9
+ # 表示禁用结束的时间, 0 表示不禁用, -1 表示永久禁用.
10
+ attr_reader :disabled_till
11
+
12
+ def initialize(hub, key, disabled_till)
13
+ @hub = hub
14
+ @key = key
15
+ @disabled_till = disabled_till
16
+ end
17
+
18
+ def disabled?
19
+ @disabled_till == -1 || @disabled_till > Time.new.to_i
20
+ end
21
+
22
+ def to_s
23
+ "#<#{self.class} #{@hub}/#{@key} disabled:#{disabled?}>"
24
+ end
25
+
26
+ def to_json
27
+ {:hub=>@hub, :key=>@key, :disabled=>disabled?}.to_json
28
+ end
29
+ end
30
+
31
+ class Stream
32
+ attr_reader :hub, :key
33
+
34
+ def initialize(hub, key, client)
35
+ @hub = hub
36
+ @key = key
37
+
38
+ ekey = Base64.urlsafe_encode64(key)
39
+ @base_url = "#{Config.api_base_url}/hubs/#{hub}/streams/#{ekey}"
40
+
41
+ @client = client
42
+ end
43
+
44
+ # Info 获得流信息.
45
+ def info
46
+ ret = @client.rpc.call_with_json("GET", @base_url, nil)
47
+ StreamInfo.new @hub, @key, ret["disabledTill"]
48
+ end
49
+
50
+ # 禁用一个流.
51
+ def disable
52
+ @client.rpc.call_with_json("POST", "#{@base_url}/disabled", {:disabledTill=>-1})
53
+ end
54
+
55
+ # 启用一个流.
56
+ def enable
57
+ @client.rpc.call_with_json("POST", "#{@base_url}/disabled", {:disabledTill=>0})
58
+ end
59
+
60
+ # 查询直播状态.
61
+ #
62
+ # 返回
63
+ #
64
+ # {
65
+ # "startAt" => <Integer>, # 直播开始的 Unix 时间戳, 0 表示当前没在直播.
66
+ # "clientIp" => <String>, # 直播的客户端 IP.
67
+ # "bps" => <Integer>, # 直播的码率、帧率信息.
68
+ # "fps" => {
69
+ # "audio" => <Integer>,
70
+ # "video" => <Integer>,
71
+ # "data" => <Integer>
72
+ # }
73
+ # }
74
+ def live_status
75
+ @client.rpc.call_with_json("GET", "#{@base_url}/live", nil)
76
+ end
77
+
78
+ # 保存直播回放.
79
+ #
80
+ # 参数: start, end 是 Unix 时间戳, 限定了保存的直播的时间范围, 0 值表示不限定, 系统会默认保存最近一次直播的内容.
81
+ #
82
+ # 返回保存的文件名, 由系统生成.
83
+ def save(opt = {})
84
+ ret = @client.rpc.call_with_json("POST", "#{@base_url}/saveas", opt)
85
+ ret["fname"]
86
+ end
87
+
88
+ # 查询直播历史.
89
+ #
90
+ # 参数: start, end 是 Unix 时间戳, 限定了查询的时间范围, 0 值表示不限定, 系统会返回所有时间的直播历史.
91
+ #
92
+ # 返回:
93
+ #
94
+ # {
95
+ # "start" => <Integer>,
96
+ # "end" => <Integer>
97
+ # }
98
+ def history_activity(opt = {})
99
+ url = "#{@base_url}/historyactivity"
100
+ if !opt.empty?
101
+ url += "?#{URI.encode_www_form opt}"
102
+ end
103
+ ret = @client.rpc.call_with_json("GET", url, nil)
104
+ ret["items"]
105
+ end
106
+
107
+ def to_s
108
+ "#<#{self.class} #{@hub}/#{@key}>"
109
+ end
110
+
111
+ def to_json
112
+ {:hub=>@hub, :key=>@key}.to_json
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ module Pili
2
+ VERSION = "2.0.0"
3
+ end
data/lib/pili.rb ADDED
@@ -0,0 +1,11 @@
1
+ # coding: utf-8
2
+ require 'json'
3
+
4
+ require_relative "pili/version"
5
+ require_relative "pili/config"
6
+ require_relative "pili/exception"
7
+ require_relative "pili/auth"
8
+ require_relative "pili/rpc"
9
+ require_relative "pili/client"
10
+ require_relative "pili/hub"
11
+ require_relative "pili/stream"
data/pili.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pili/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "piliv2"
8
+ spec.version = Pili::VERSION
9
+ spec.authors = ["Pili Engineer"]
10
+ spec.email = ["pili@qiniu.com"]
11
+ spec.summary = %q{Pili Streaming Cloud Server-Side Library For Ruby.}
12
+ spec.description = %q{Pili Streaming Cloud Server-Side Library For Ruby.}
13
+ spec.homepage = "https://github.com/pili-engineering/pili-sdk-ruby"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: piliv2
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Pili Engineer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Pili Streaming Cloud Server-Side Library For Ruby.
42
+ email:
43
+ - pili@qiniu.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".travis.yml"
50
+ - Gemfile
51
+ - LICENSE
52
+ - README.md
53
+ - Rakefile
54
+ - example/example.rb
55
+ - lib/pili.rb
56
+ - lib/pili/auth.rb
57
+ - lib/pili/client.rb
58
+ - lib/pili/config.rb
59
+ - lib/pili/exception.rb
60
+ - lib/pili/hub.rb
61
+ - lib/pili/rpc.rb
62
+ - lib/pili/stream.rb
63
+ - lib/pili/version.rb
64
+ - pili.gemspec
65
+ homepage: https://github.com/pili-engineering/pili-sdk-ruby
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.5.1
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Pili Streaming Cloud Server-Side Library For Ruby.
89
+ test_files: []