opentok 3.1.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +3 -1
- data/README.md +35 -4
- data/lib/opentok/archives.rb +12 -1
- data/lib/opentok/sip.rb +0 -2
- data/lib/opentok/version.rb +1 -1
- data/opentok.gemspec +9 -8
- data/sample/Broadcast/Gemfile +4 -0
- data/sample/Broadcast/README.md +201 -0
- data/sample/Broadcast/broadcast_sample.rb +97 -0
- data/sample/Broadcast/public/css/sample.css +64 -0
- data/sample/Broadcast/public/js/host.js +185 -0
- data/sample/Broadcast/public/js/participant.js +85 -0
- data/sample/Broadcast/views/host.erb +82 -0
- data/sample/Broadcast/views/index.erb +32 -0
- data/sample/Broadcast/views/layout.erb +29 -0
- data/sample/Broadcast/views/participant.erb +27 -0
- data/sample/HelloWorld/public/js/helloworld.js +4 -10
- data/sample/HelloWorld/views/index.erb +1 -3
- data/spec/cassettes/OpenTok_Archives/calls_layout_on_archive_object.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/changes_the_layout_of_an_archive.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/http_client_errors/.yml +34 -0
- data/spec/cassettes/OpenTok_Archives/should_create_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_create_audio_only_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_create_custom_layout_archives.yml +48 -0
- data/spec/cassettes/OpenTok_Archives/should_create_hd_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_create_individual_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_create_named_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_delete_an_archive_by_id.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_find_archives_by_id.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_find_archives_with_unknown_properties.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_find_expired_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_find_paused_archives_by_id.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/should_stop_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_all_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_archives_with_an_offset.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_count_number_of_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_part_of_the_archives_when_using_offset_and_count.yml +1 -1
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_session_archives.yml +1 -1
- data/spec/cassettes/OpenTok_Broadcasts/calls_layout_on_broadcast_object.yml +1 -1
- data/spec/cassettes/OpenTok_Broadcasts/changes_the_layout_of_a_broadcast.yml +1 -1
- data/spec/cassettes/OpenTok_Broadcasts/fetches_a_hls_broadcast_url.yml +1 -1
- data/spec/cassettes/OpenTok_Broadcasts/finds_a_broadcast.yml +1 -1
- data/spec/cassettes/OpenTok_Broadcasts/starts_a_rtmp_broadcast.yml +1 -1
- data/spec/cassettes/OpenTok_Broadcasts/stops_a_broadcast.yml +1 -1
- data/spec/cassettes/OpenTok_Connections/forces_a_connection_to_be_terminated.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_default_sessions.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_for_invalid_media_modes.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_with_a_location_hint.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_with_a_location_hint.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_sessions_with_a_location_hint.yml +1 -1
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/with_an_addendum_to_the_user_agent_string/should_append_the_addendum_to_the_user_agent_header.yml +1 -1
- data/spec/cassettes/OpenTok_Signals/receives_a_valid_response_for_a_connection.yml +1 -1
- data/spec/cassettes/OpenTok_Signals/receives_a_valid_response_for_all_connections.yml +1 -1
- data/spec/cassettes/OpenTok_Sip/receives_a_valid_response.yml +1 -1
- data/spec/cassettes/OpenTok_Streams/get_all_streams_information.yml +1 -1
- data/spec/cassettes/OpenTok_Streams/get_specific_stream_information.yml +1 -1
- data/spec/cassettes/OpenTok_Streams/layout_working_on_two_stream_list.yml +1 -1
- data/spec/opentok/archives_spec.rb +11 -1
- data/spec/spec_helper.rb +2 -0
- metadata +33 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2d54c20aba3659203311b38260a883c4586590ebbeeeeea059a4f3bbaf53cd88
|
4
|
+
data.tar.gz: 14808a5dccb04fd42df4b1768fc1943b4620b2e2e753a123db244f9849e82e6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ee3bf5992a0c962099f5db88d8db4043699d596566256ff3256447f1658173610fdd76fa10c086620742d3dddb4fe45e56ab66b3724b749f336c1b748be7dcd
|
7
|
+
data.tar.gz: 9e39c51d175a273666d2af2e5cd8667d46b1c04531f10ca297dd9d3b19db2a3e080fb989480038d290e702c816ca790aa1baf39d051dbb2e438c87b9e00f61f2
|
data/.travis.yml
CHANGED
@@ -5,11 +5,13 @@ language: ruby
|
|
5
5
|
cache: bundler
|
6
6
|
before_install: gem update bundler
|
7
7
|
rvm:
|
8
|
-
- 2.0
|
9
8
|
- 2.1
|
10
9
|
- 2.2
|
11
10
|
- 2.3
|
12
11
|
- 2.4
|
12
|
+
- 2.5
|
13
|
+
- 2.6
|
14
|
+
- 2.7
|
13
15
|
notifications:
|
14
16
|
slack:
|
15
17
|
secure: agVll2R9PTPvJMcUgbvOh9eGt60zGDc8kPUwEsiQr828rCgXh/ZxD5irYDyKQg3ZsS8+f3MjFCwzU7uQALkia2pDrie9d8g8m1dt4Q5U7Qm6QecshvE0U9JwbB5Ngxaftbqyf0XEFrE7CKs7RI1BzFRpe8m+fdZgfwccX8Gb7pc=
|
data/README.md
CHANGED
@@ -21,7 +21,7 @@ Bundler helps manage dependencies for Ruby projects. Find more info here: <http:
|
|
21
21
|
Add this gem to your `Gemfile`:
|
22
22
|
|
23
23
|
```ruby
|
24
|
-
gem "opentok", "~>
|
24
|
+
gem "opentok", "~> 4.0.0"
|
25
25
|
```
|
26
26
|
|
27
27
|
Allow bundler to install the change.
|
@@ -181,6 +181,30 @@ opts = {
|
|
181
181
|
archive = opentok.archives.create session_id, opts
|
182
182
|
```
|
183
183
|
|
184
|
+
To customize the initial layout of composed archives, you can use the `:layout` option.
|
185
|
+
Set this to a hash containing two keys: `:type` and `:stylesheet`. Valid values for
|
186
|
+
`:type` are "bestFit" (best fit), "custom" (custom), "horizontalPresentation"
|
187
|
+
(horizontal presentation), "pip" (picture-in-picture), and "verticalPresentation"
|
188
|
+
(vertical presentation)). If you specify a "custom" layout type, set the `:stylesheet`
|
189
|
+
key to the stylesheet (CSS). (For other layout types, do not set the `:stylesheet` key.)
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
opts = {
|
193
|
+
:output_mode => :composed,
|
194
|
+
:resolution => "1280x720",
|
195
|
+
:layout => {
|
196
|
+
:type => "custom",
|
197
|
+
:stylesheet => "stream:last-child{display: block;margin: 0;top: 0;left: 0;width: 1px;height: 1px;}stream:first-child{display: block;margin: 0;top: 0;left: 0;width: 100%;height: 100%;}"
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
archive = opentok.archives.create session_id, opts
|
202
|
+
```
|
203
|
+
|
204
|
+
If you do not specify an initial layout type, the archive uses the best fit
|
205
|
+
layout type. For more information, see [Customizing the video layout for composed
|
206
|
+
archives](https://tokbox.com/developer/guides/archiving/layout-control.html).
|
207
|
+
|
184
208
|
You can stop the recording of a started Archive using the `opentok.archives.stop_by_id(archive_id)`
|
185
209
|
method. You can also do this using the `Archive#stop()` method.
|
186
210
|
|
@@ -432,11 +456,12 @@ For more information on SIP Interconnect, see the
|
|
432
456
|
|
433
457
|
# Samples
|
434
458
|
|
435
|
-
There are
|
436
|
-
repository and
|
459
|
+
There are three sample applications included in this repository. To get going as fast as possible, clone the whole
|
460
|
+
repository and read the README in each of the sample directories:
|
437
461
|
|
438
462
|
* [HelloWorld](sample/HelloWorld/README.md)
|
439
463
|
* [Archiving](sample/Archiving/README.md)
|
464
|
+
* [Broadcast](sample/Broadcast/README.md)
|
440
465
|
|
441
466
|
# Documentation
|
442
467
|
|
@@ -447,7 +472,7 @@ Reference documentation is available at <http://www.tokbox.com//opentok/librarie
|
|
447
472
|
You need an OpenTok API key and API secret, which you can obtain by logging into your
|
448
473
|
[TokBox account](https://tokbox.com/account).
|
449
474
|
|
450
|
-
The OpenTok Ruby SDK requires Ruby 1.
|
475
|
+
The OpenTok Ruby SDK requires Ruby 2.1.0 or greater.
|
451
476
|
|
452
477
|
# Release Notes
|
453
478
|
|
@@ -456,6 +481,12 @@ about each release.
|
|
456
481
|
|
457
482
|
## Important changes since v2.2.0
|
458
483
|
|
484
|
+
**Changes in v4.0.0:**
|
485
|
+
|
486
|
+
The SDK adds support for Ruby v2.7 and now requires Ruby v2.1.0 or higher.
|
487
|
+
For Ruby v2.0.0 please continue to use the OpenTok Ruby SDK v3.0.0.
|
488
|
+
For Ruby v1.9.3 please continue to use the OpenTok Ruby SDK v2.5.0.
|
489
|
+
|
459
490
|
**Changes in v3.0.0:**
|
460
491
|
|
461
492
|
The SDK now now requires Ruby v2.0.0 or higher. For Ruby v1.9.3 please continue to use the
|
data/lib/opentok/archives.rb
CHANGED
@@ -48,6 +48,17 @@ module OpenTok
|
|
48
48
|
# default) or "1280x720" (HD). This property only applies to composed archives. If you set
|
49
49
|
# this property and set the outputMode property to "individual", the call the method
|
50
50
|
# results in an error.
|
51
|
+
# @option options [Hash] :layout Specify this to assign the initial layout type for
|
52
|
+
# the archive. This applies only to composed archives. This is a hash containing two keys:
|
53
|
+
# <code>:type</code> and <code>:stylesheet<code>. Valid values for <code>:type</code> are
|
54
|
+
# "bestFit" (best fit), "custom" (custom), "horizontalPresentation" (horizontal presentation),
|
55
|
+
# "pip" (picture-in-picture), and "verticalPresentation" (vertical presentation)).
|
56
|
+
# If you specify a "custom" layout type, set the <code>:stylesheet</code> key to the
|
57
|
+
# stylesheet (CSS). (For other layout types, do not set the <code>:stylesheet</code> key.)
|
58
|
+
# If you do not specify an initial layout type, the archive uses the best fit
|
59
|
+
# layout type. For more information, see
|
60
|
+
# {https://tokbox.com/developer/guides/archiving/layout-control.html Customizing
|
61
|
+
# the video layout for composed archives}.
|
51
62
|
#
|
52
63
|
# @return [Archive] The Archive object, which includes properties defining the archive,
|
53
64
|
# including the archive ID.
|
@@ -66,7 +77,7 @@ module OpenTok
|
|
66
77
|
"Resolution cannot be supplied for individual output mode" if options.key?(:resolution) and options[:output_mode] == :individual
|
67
78
|
|
68
79
|
# normalize opts so all keys are symbols and only include valid_opts
|
69
|
-
valid_opts = [ :name, :has_audio, :has_video, :output_mode, :resolution ]
|
80
|
+
valid_opts = [ :name, :has_audio, :has_video, :output_mode, :resolution, :layout ]
|
70
81
|
opts = options.inject({}) do |m,(k,v)|
|
71
82
|
if valid_opts.include? k.to_sym
|
72
83
|
m[k.to_sym] = v
|
data/lib/opentok/sip.rb
CHANGED
@@ -30,8 +30,6 @@ module OpenTok
|
|
30
30
|
# PSTN phones.
|
31
31
|
# @option opts [Hash] :headers This hash defines custom headers to be added
|
32
32
|
# to the SIP INVITE request initiated from OpenTok to the your SIP platform.
|
33
|
-
# Each of the custom headers must start with the "X-" prefix, or the call
|
34
|
-
# will result in a Bad Request (400) response.
|
35
33
|
# @option opts [Hash] :auth This object contains the username and password
|
36
34
|
# to be used in the the SIP INVITE request for HTTP digest authentication,
|
37
35
|
# if it is required by your SIP platform.
|
data/lib/opentok/version.rb
CHANGED
data/opentok.gemspec
CHANGED
@@ -16,17 +16,18 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
|
19
|
-
|
20
|
-
spec.add_development_dependency "
|
21
|
-
spec.add_development_dependency "
|
22
|
-
spec.add_development_dependency "
|
23
|
-
spec.add_development_dependency "
|
24
|
-
spec.add_development_dependency "
|
19
|
+
bundler_version = RUBY_VERSION < '2.1' ? '~> 1.5' : '>= 1.5'
|
20
|
+
spec.add_development_dependency "bundler", bundler_version
|
21
|
+
spec.add_development_dependency "rake", "~> 12.0.0"
|
22
|
+
spec.add_development_dependency "rspec", "~> 3.9.0"
|
23
|
+
spec.add_development_dependency "webmock", ">= 2.3.2"
|
24
|
+
spec.add_development_dependency "vcr", ">= 2.8.0"
|
25
|
+
spec.add_development_dependency "yard", ">= 0.9.11"
|
25
26
|
# TODO: exclude this for compatibility with rbx
|
26
27
|
# spec.add_development_dependency "debugger", "~> 1.6.6"
|
27
28
|
|
28
29
|
spec.add_dependency "addressable", "~> 2.3" # 2.3.0 <= version < 3.0.0
|
29
|
-
spec.add_dependency "httparty", "
|
30
|
+
spec.add_dependency "httparty", ">= 0.15.5"
|
30
31
|
spec.add_dependency "activesupport", ">= 2.0"
|
31
|
-
spec.add_dependency "jwt", "
|
32
|
+
spec.add_dependency "jwt", ">= 1.5.6"
|
32
33
|
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# OpenTok Broadcasting Sample for Ruby
|
2
|
+
|
3
|
+
This is a simple demo app that shows how you can use the OpenTok Ruby SDK to broadcast
|
4
|
+
sessions and how to stop them, change the layout of the broadcast and/or the streams within.
|
5
|
+
|
6
|
+
## Running the App
|
7
|
+
|
8
|
+
First, download the dependencies using [Bundler](http://bundler.io)
|
9
|
+
|
10
|
+
```
|
11
|
+
$ bundle install
|
12
|
+
```
|
13
|
+
|
14
|
+
Next, add your OpenTok API key and API secret to the environment variables. There are a few ways to do
|
15
|
+
this but the simplest would be to do it right in your shell.
|
16
|
+
|
17
|
+
```
|
18
|
+
$ export API_KEY=0000000
|
19
|
+
$ export API_SECRET=abcdef1234567890abcdef01234567890abcdef
|
20
|
+
```
|
21
|
+
|
22
|
+
Finally, start the server using Bundler to handle dependencies
|
23
|
+
|
24
|
+
```
|
25
|
+
$ bundle exec ruby broadcast_sample.rb
|
26
|
+
```
|
27
|
+
|
28
|
+
Visit <http://localhost:4567> in your browser. You can now create new broadcast (with a host and
|
29
|
+
as a participant) and also view those broadcasts.
|
30
|
+
|
31
|
+
## Walkthrough
|
32
|
+
|
33
|
+
This demo application uses the same frameworks and libraries as the HelloWorld sample. If you have
|
34
|
+
not already gotten familiar with the code in that project, consider doing so before continuing.
|
35
|
+
|
36
|
+
The explanations below are separated by page. Each section will focus on a route handler within the
|
37
|
+
main application (broadcast_sample.rb).
|
38
|
+
|
39
|
+
### Creating Broadcasts – Host View
|
40
|
+
|
41
|
+
The Host view manages the broadcasting process. Visit the host page at <http://localhost:4567/host>.
|
42
|
+
Your browser will first ask you to approve permission to use the camera and microphone.
|
43
|
+
Once you've accepted, your image will appear inside the section titled 'Host'. To start broadcasting
|
44
|
+
the video stream, press the 'Start Broadcast' button. You can specify the maximum duration,
|
45
|
+
resolution, and layout of the broadcast. Once broadcasting has begun the button will turn
|
46
|
+
green and change to 'Stop Broadcast'. Click this button when you are done broadcasting.
|
47
|
+
|
48
|
+
The host page basically sets up the OpenTok session with the API key and secret you provided.
|
49
|
+
If a previously started broadcast exists, it defaults to it, along with the layout and the stream
|
50
|
+
that has the focus:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
get '/host' do
|
54
|
+
api_key = settings.api_key
|
55
|
+
session_id = settings.session.session_id
|
56
|
+
token = settings.opentok.generate_token(session_id, role: :publisher, initialLayoutClassList: ['focus'])
|
57
|
+
|
58
|
+
erb :host, locals: {
|
59
|
+
apiKey: api_key,
|
60
|
+
sessionId: session_id,
|
61
|
+
token: token,
|
62
|
+
initialBroadcastId: settings.broadcast_id,
|
63
|
+
focusStreamId: settings.focus_stream_id,
|
64
|
+
initialLayout: settings.broadcast_layout
|
65
|
+
}
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
This handler generates the three strings that the client (JavaScript) needs to connect
|
70
|
+
to the session: `apiKey`, `sessionId`, and `token`. The `initialBroadcastId` is the broadcast ID,
|
71
|
+
`focusStreamId` is the stream ID that has the current focus (if there is one), and
|
72
|
+
`initialLayout` is the initial layout for the current broadcast in progress (if there is one).
|
73
|
+
(We will discuss focus stream and broadcast layout below.)
|
74
|
+
|
75
|
+
In the host page, the user presses the 'Start Broadcast' button, which sends an XHR (or Ajax)
|
76
|
+
request to the <http://localhost:4567/start> URL. The route handler for this URL is shown below:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
post '/start' do
|
80
|
+
opts = {
|
81
|
+
:maxDuration => params.key?("maxDuration") ? params[:maxDuration] : 7200,
|
82
|
+
:resolution => params[:resolution],
|
83
|
+
:layout => params[:layout],
|
84
|
+
:outputs => {
|
85
|
+
:hls => {}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
broadcast = settings.opentok.broadcasts.create(settings.session.session_id, opts)
|
89
|
+
settings.broadcast_id = broadcast.id
|
90
|
+
body broadcast.to_json
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
In this handler, `opentok.broadcasts.create` is called with the `session_id` for
|
95
|
+
the OpenTok session to broadcast. The optional second argument is a hash which defines
|
96
|
+
optional properties for the broadcast. It consists of `maxDuration` of the broadcast,
|
97
|
+
`resolution`, and broadcast `layout`. This sample app starts an HLS broadcast (not RTMP),
|
98
|
+
so it only specifies an `hls` property of the `outputs` property. See the
|
99
|
+
[Ruby SDK documentation](https://github.com/opentok/OpenTok-Ruby-SDK) for information
|
100
|
+
on adding RTMP broadcast streams. In this case, as in the HelloWorld sample app, there is
|
101
|
+
only one session created and it is used here and for the participant view.
|
102
|
+
This will trigger the broadcasting to begin. The response sent back to the client’s XHR request
|
103
|
+
will be the JSON representation of the broadcast, which is returned from the `to_json()` method.
|
104
|
+
|
105
|
+
You can view the HLS broadcast by opening the root URL (<http://localhost:4567/>) in
|
106
|
+
a different tab and clicking the `Broadcast URL` button. The code for handling this is as follows:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
get '/broadcast' do
|
110
|
+
return 'No broadcast id exists' if settings.broadcast_id.nil? || settings.broadcast_id.empty?
|
111
|
+
broadcast = settings.opentok.broadcasts.find settings.broadcast_id
|
112
|
+
redirect broadcast.broadcastUrls['hls'] if broadcast.status == 'started'
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
The route for Stop Broadcast has the following code:
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
get '/stop/:broadcastId' do
|
120
|
+
broadcast = settings.opentok.broadcasts.stop settings.broadcast_id
|
121
|
+
settings.broadcast_id = nil
|
122
|
+
settings.focus_stream_id = ''
|
123
|
+
settings.broadcast_layout = 'horizontalPresentation'
|
124
|
+
body broadcast.to_json
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
The settings revert backs to the settings when you start the app.
|
129
|
+
|
130
|
+
The host page includes a `Toggle Layout` button, which toggles between
|
131
|
+
`verticalPresentation` and `horizontalPresentation`.
|
132
|
+
|
133
|
+
The route for `Toggle Layout` has the following code:
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
post '/broadcast/:broadcastId/layout' do
|
137
|
+
layoutType = params[:type]
|
138
|
+
settings.opentok.broadcasts.layout(settings.broadcast_id, type: layoutType)
|
139
|
+
settings.broadcast_layout = layoutType
|
140
|
+
end
|
141
|
+
```
|
142
|
+
|
143
|
+
This calls the `opentok.broadcasts.layout()` method, setting the broadcast layout to
|
144
|
+
the layout type defined in the POST request's body. In this app, the layout type is
|
145
|
+
set to `horizontalPresentation` or `verticalPresentation`, two of the [predefined layout
|
146
|
+
types](https://tokbox.com/developer/guides/broadcast/live-streaming/#predefined-layout-types)
|
147
|
+
available to live streaming broadcasts.
|
148
|
+
|
149
|
+
### Creating Broadcast - Participant View
|
150
|
+
|
151
|
+
With the host view still open and publishing, open an additional tab and navigate to
|
152
|
+
<http://localhost:4567/participant> and allow the browser to use your camera and microphone.
|
153
|
+
You will now see the participant in the broadcast.
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
get '/participant' do
|
157
|
+
api_key = settings.api_key
|
158
|
+
session_id = settings.session.session_id
|
159
|
+
token = settings.opentok.generate_token(session_id, role: :publisher)
|
160
|
+
|
161
|
+
erb :participant, locals: {
|
162
|
+
apiKey: api_key,
|
163
|
+
sessionId: session_id,
|
164
|
+
token: token,
|
165
|
+
focusStreamId: settings.focus_stream_id,
|
166
|
+
layout: settings.broadcast_layout
|
167
|
+
}
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
### Changing the layout classes for streams
|
172
|
+
|
173
|
+
In the host page, if you click on either the host or a participant video, that video gets
|
174
|
+
the `focus` layout in the broadcast. The host page sends the `focus` stream ID and
|
175
|
+
the other streams' layout class lists can be cleared, as shown below:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
post '/focus' do
|
179
|
+
hash = { items: [] }
|
180
|
+
hash[:items] << { id: params[:focus], layoutClassList: ['focus'] }
|
181
|
+
settings.focus_stream_id = params[:focus]
|
182
|
+
if params.key?('otherStreams')
|
183
|
+
params[:otherStreams].each do |stream|
|
184
|
+
hash[:items] << { id: stream, layoutClassList: [] }
|
185
|
+
end
|
186
|
+
end
|
187
|
+
settings.opentok.streams.layout(settings.session.session_id, hash)
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
The host client page also uses OpenTok signaling to notify other clients when the layout type and
|
192
|
+
focus stream changes, and they then update the local display of streams in the HTML DOM accordingly.
|
193
|
+
However, this is not necessary. The layout of the broadcast is unrelated to the layout of
|
194
|
+
streams in the web clients.
|
195
|
+
|
196
|
+
When you view the broadcast stream, the layout type and focus stream changes, based on calls
|
197
|
+
to the `OpenTok.setBroadcastLayout()` and `OpenTok.setStreamClassLists()` methods during
|
198
|
+
the broadcast.
|
199
|
+
|
200
|
+
For more information, see [Configuring video layout for OpenTok live streaming
|
201
|
+
broadcasts](https://tokbox.com/developer/guides/broadcast/live-streaming/#configuring-video-layout-for-opentok-live-streaming-broadcasts).
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'opentok'
|
3
|
+
|
4
|
+
raise "You must define API_KEY and API_SECRET environment variables" unless ENV.has_key?("API_KEY") && ENV.has_key?("API_SECRET")
|
5
|
+
|
6
|
+
class BroadcastSample < Sinatra::Base
|
7
|
+
|
8
|
+
set :api_key, ENV['API_KEY']
|
9
|
+
set :opentok, OpenTok::OpenTok.new(api_key, ENV['API_SECRET'])
|
10
|
+
set :session, opentok.create_session(:media_mode => :routed)
|
11
|
+
set :erb, :layout => :layout
|
12
|
+
set :broadcast_id, nil
|
13
|
+
set :focus_stream_id, ''
|
14
|
+
set :broadcast_layout, 'horizontalPresentation'
|
15
|
+
|
16
|
+
get '/' do
|
17
|
+
erb :index
|
18
|
+
end
|
19
|
+
|
20
|
+
get '/host' do
|
21
|
+
api_key = settings.api_key
|
22
|
+
session_id = settings.session.session_id
|
23
|
+
token = settings.opentok.generate_token(session_id, role: :publisher, initialLayoutClassList: ['focus'])
|
24
|
+
|
25
|
+
erb :host, locals: {
|
26
|
+
apiKey: api_key,
|
27
|
+
sessionId: session_id,
|
28
|
+
token: token,
|
29
|
+
initialBroadcastId: settings.broadcast_id,
|
30
|
+
focusStreamId: settings.focus_stream_id,
|
31
|
+
initialLayout: settings.broadcast_layout
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
get '/participant' do
|
36
|
+
api_key = settings.api_key
|
37
|
+
session_id = settings.session.session_id
|
38
|
+
token = settings.opentok.generate_token(session_id, role: :publisher)
|
39
|
+
|
40
|
+
erb :participant, locals: {
|
41
|
+
apiKey: api_key,
|
42
|
+
sessionId: session_id,
|
43
|
+
token: token,
|
44
|
+
focusStreamId: settings.focus_stream_id,
|
45
|
+
layout: settings.broadcast_layout
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
post '/start' do
|
50
|
+
opts = {
|
51
|
+
:maxDuration => params.key?("maxDuration") ? params[:maxDuration] : 7200,
|
52
|
+
:resolution => params[:resolution],
|
53
|
+
:layout => params[:layout],
|
54
|
+
:outputs => {
|
55
|
+
:hls => {}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
broadcast = settings.opentok.broadcasts.create(settings.session.session_id, opts)
|
59
|
+
settings.broadcast_id = broadcast.id
|
60
|
+
body broadcast.to_json
|
61
|
+
end
|
62
|
+
|
63
|
+
get '/broadcast' do
|
64
|
+
return 'No broadcast id exists' if settings.broadcast_id.nil? || settings.broadcast_id.empty?
|
65
|
+
broadcast = settings.opentok.broadcasts.find settings.broadcast_id
|
66
|
+
redirect broadcast.broadcastUrls['hls'] if broadcast.status == 'started'
|
67
|
+
end
|
68
|
+
|
69
|
+
get '/stop/:broadcastId' do
|
70
|
+
broadcast = settings.opentok.broadcasts.stop settings.broadcast_id
|
71
|
+
settings.broadcast_id = nil
|
72
|
+
settings.focus_stream_id = ''
|
73
|
+
settings.broadcast_layout = 'horizontalPresentation'
|
74
|
+
body broadcast.to_json
|
75
|
+
end
|
76
|
+
|
77
|
+
post '/broadcast/:broadcastId/layout' do
|
78
|
+
layoutType = params[:type]
|
79
|
+
settings.opentok.broadcasts.layout(settings.broadcast_id, type: layoutType)
|
80
|
+
settings.broadcast_layout = layoutType
|
81
|
+
end
|
82
|
+
|
83
|
+
post '/focus' do
|
84
|
+
hash = { items: [] }
|
85
|
+
hash[:items] << { id: params[:focus], layoutClassList: ['focus'] }
|
86
|
+
settings.focus_stream_id = params[:focus]
|
87
|
+
if params.key?('otherStreams')
|
88
|
+
params[:otherStreams].each do |stream|
|
89
|
+
hash[:items] << { id: stream, layoutClassList: [] }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
settings.opentok.streams.layout(settings.session.session_id, hash)
|
93
|
+
end
|
94
|
+
|
95
|
+
# start the server if ruby file executed directly
|
96
|
+
run! if app_file == $0
|
97
|
+
end
|