piliv2 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []