Skip to content

Commit

Permalink
Merge pull request #196 from opentok/dev
Browse files Browse the repository at this point in the history
v4.0.0 - Update gems, Ruby 2.7 support, add layout to archive create, broadcast sample
  • Loading branch information
msach22 authored Jan 28, 2020
2 parents dfa22dc + a24b7b0 commit 2426a37
Show file tree
Hide file tree
Showing 62 changed files with 1,006 additions and 71 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ language: ruby
cache: bundler
before_install: gem update bundler
rvm:
- 2.0
- 2.1
- 2.2
- 2.3
- 2.4
- 2.5
- 2.6
- 2.7
notifications:
slack:
secure: agVll2R9PTPvJMcUgbvOh9eGt60zGDc8kPUwEsiQr828rCgXh/ZxD5irYDyKQg3ZsS8+f3MjFCwzU7uQALkia2pDrie9d8g8m1dt4Q5U7Qm6QecshvE0U9JwbB5Ngxaftbqyf0XEFrE7CKs7RI1BzFRpe8m+fdZgfwccX8Gb7pc=
39 changes: 35 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Bundler helps manage dependencies for Ruby projects. Find more info here: <http:
Add this gem to your `Gemfile`:

```ruby
gem "opentok", "~> 3.1.0"
gem "opentok", "~> 4.0.0"
```

Allow bundler to install the change.
Expand Down Expand Up @@ -181,6 +181,30 @@ opts = {
archive = opentok.archives.create session_id, opts
```

To customize the initial layout of composed archives, you can use the `:layout` option.
Set this to a hash containing two keys: `:type` and `:stylesheet`. Valid values for
`:type` are "bestFit" (best fit), "custom" (custom), "horizontalPresentation"
(horizontal presentation), "pip" (picture-in-picture), and "verticalPresentation"
(vertical presentation)). If you specify a "custom" layout type, set the `:stylesheet`
key to the stylesheet (CSS). (For other layout types, do not set the `:stylesheet` key.)

```ruby
opts = {
:output_mode => :composed,
:resolution => "1280x720",
:layout => {
:type => "custom",
: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%;}"
}
}

archive = opentok.archives.create session_id, opts
```

If you do not specify an initial layout type, the archive uses the best fit
layout type. For more information, see [Customizing the video layout for composed
archives](https://tokbox.com/developer/guides/archiving/layout-control.html).

You can stop the recording of a started Archive using the `opentok.archives.stop_by_id(archive_id)`
method. You can also do this using the `Archive#stop()` method.

Expand Down Expand Up @@ -432,11 +456,12 @@ For more information on SIP Interconnect, see the

# Samples

There are two sample applications included in this repository. To get going as fast as possible, clone the whole
repository and follow the Walkthroughs:
There are three sample applications included in this repository. To get going as fast as possible, clone the whole
repository and read the README in each of the sample directories:

* [HelloWorld](sample/HelloWorld/README.md)
* [Archiving](sample/Archiving/README.md)
* [Broadcast](sample/Broadcast/README.md)

# Documentation

Expand All @@ -447,7 +472,7 @@ Reference documentation is available at <http://www.tokbox.com//opentok/librarie
You need an OpenTok API key and API secret, which you can obtain by logging into your
[TokBox account](https://tokbox.com/account).

The OpenTok Ruby SDK requires Ruby 1.9.3 or greater.
The OpenTok Ruby SDK requires Ruby 2.1.0 or greater.

# Release Notes

Expand All @@ -456,6 +481,12 @@ about each release.

## Important changes since v2.2.0

**Changes in v4.0.0:**

The SDK adds support for Ruby v2.7 and now requires Ruby v2.1.0 or higher.
For Ruby v2.0.0 please continue to use the OpenTok Ruby SDK v3.0.0.
For Ruby v1.9.3 please continue to use the OpenTok Ruby SDK v2.5.0.

**Changes in v3.0.0:**

The SDK now now requires Ruby v2.0.0 or higher. For Ruby v1.9.3 please continue to use the
Expand Down
13 changes: 12 additions & 1 deletion lib/opentok/archives.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ def initialize(client)
# default) or "1280x720" (HD). This property only applies to composed archives. If you set
# this property and set the outputMode property to "individual", the call the method
# results in an error.
# @option options [Hash] :layout Specify this to assign the initial layout type for
# the archive. This applies only to composed archives. This is a hash containing two keys:
# <code>:type</code> and <code>:stylesheet<code>. Valid values for <code>:type</code> are
# "bestFit" (best fit), "custom" (custom), "horizontalPresentation" (horizontal presentation),
# "pip" (picture-in-picture), and "verticalPresentation" (vertical presentation)).
# If you specify a "custom" layout type, set the <code>:stylesheet</code> key to the
# stylesheet (CSS). (For other layout types, do not set the <code>:stylesheet</code> key.)
# If you do not specify an initial layout type, the archive uses the best fit
# layout type. For more information, see
# {https://tokbox.com/developer/guides/archiving/layout-control.html Customizing
# the video layout for composed archives}.
#
# @return [Archive] The Archive object, which includes properties defining the archive,
# including the archive ID.
Expand All @@ -66,7 +77,7 @@ def create(session_id, options = {})
"Resolution cannot be supplied for individual output mode" if options.key?(:resolution) and options[:output_mode] == :individual

# normalize opts so all keys are symbols and only include valid_opts
valid_opts = [ :name, :has_audio, :has_video, :output_mode, :resolution ]
valid_opts = [ :name, :has_audio, :has_video, :output_mode, :resolution, :layout ]
opts = options.inject({}) do |m,(k,v)|
if valid_opts.include? k.to_sym
m[k.to_sym] = v
Expand Down
2 changes: 0 additions & 2 deletions lib/opentok/sip.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ class Sip
# PSTN phones.
# @option opts [Hash] :headers This hash defines custom headers to be added
# to the SIP ​INVITE​ request initiated from OpenTok to the your SIP platform.
# Each of the custom headers must start with the ​"X-"​ prefix, or the call
# will result in a Bad Request (400) response.
# @option opts [Hash] :auth This object contains the username and password
# to be used in the the SIP INVITE​ request for HTTP digest authentication,
# if it is required by your SIP platform.
Expand Down
2 changes: 1 addition & 1 deletion lib/opentok/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module OpenTok
# @private
VERSION = '3.1.0'
VERSION = '4.0.0'
end
17 changes: 9 additions & 8 deletions opentok.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})

spec.add_development_dependency "bundler", "~> 1.5"
spec.add_development_dependency "rake", "~> 10.1.1"
spec.add_development_dependency "rspec", "~> 2.14.1"
spec.add_development_dependency "webmock", "~> 2.3.2"
spec.add_development_dependency "vcr", "~> 2.8.0"
spec.add_development_dependency "yard", "~> 0.9.11"
bundler_version = RUBY_VERSION < '2.1' ? '~> 1.5' : '>= 1.5'
spec.add_development_dependency "bundler", bundler_version
spec.add_development_dependency "rake", "~> 12.0.0"
spec.add_development_dependency "rspec", "~> 3.9.0"
spec.add_development_dependency "webmock", ">= 2.3.2"
spec.add_development_dependency "vcr", ">= 2.8.0"
spec.add_development_dependency "yard", ">= 0.9.11"
# TODO: exclude this for compatibility with rbx
# spec.add_development_dependency "debugger", "~> 1.6.6"

spec.add_dependency "addressable", "~> 2.3" # 2.3.0 <= version < 3.0.0
spec.add_dependency "httparty", "~> 0.15.5"
spec.add_dependency "httparty", ">= 0.15.5"
spec.add_dependency "activesupport", ">= 2.0"
spec.add_dependency "jwt", "~> 1.5.6"
spec.add_dependency "jwt", ">= 1.5.6"
end
4 changes: 4 additions & 0 deletions sample/Broadcast/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source "http://rubygems.org"

gem "sinatra", "~> 1.4.4"
gem "opentok", :path => "../../"
201 changes: 201 additions & 0 deletions sample/Broadcast/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# OpenTok Broadcasting Sample for Ruby

This is a simple demo app that shows how you can use the OpenTok Ruby SDK to broadcast
sessions and how to stop them, change the layout of the broadcast and/or the streams within.

## Running the App

First, download the dependencies using [Bundler](http://bundler.io)

```
$ bundle install
```

Next, add your OpenTok API key and API secret to the environment variables. There are a few ways to do
this but the simplest would be to do it right in your shell.

```
$ export API_KEY=0000000
$ export API_SECRET=abcdef1234567890abcdef01234567890abcdef
```

Finally, start the server using Bundler to handle dependencies

```
$ bundle exec ruby broadcast_sample.rb
```

Visit <http://localhost:4567> in your browser. You can now create new broadcast (with a host and
as a participant) and also view those broadcasts.

## Walkthrough

This demo application uses the same frameworks and libraries as the HelloWorld sample. If you have
not already gotten familiar with the code in that project, consider doing so before continuing.

The explanations below are separated by page. Each section will focus on a route handler within the
main application (broadcast_sample.rb).

### Creating Broadcasts – Host View

The Host view manages the broadcasting process. Visit the host page at <http://localhost:4567/host>.
Your browser will first ask you to approve permission to use the camera and microphone.
Once you've accepted, your image will appear inside the section titled 'Host'. To start broadcasting
the video stream, press the 'Start Broadcast' button. You can specify the maximum duration,
resolution, and layout of the broadcast. Once broadcasting has begun the button will turn
green and change to 'Stop Broadcast'. Click this button when you are done broadcasting.

The host page basically sets up the OpenTok session with the API key and secret you provided.
If a previously started broadcast exists, it defaults to it, along with the layout and the stream
that has the focus:

```ruby
get '/host' do
api_key = settings.api_key
session_id = settings.session.session_id
token = settings.opentok.generate_token(session_id, role: :publisher, initialLayoutClassList: ['focus'])

erb :host, locals: {
apiKey: api_key,
sessionId: session_id,
token: token,
initialBroadcastId: settings.broadcast_id,
focusStreamId: settings.focus_stream_id,
initialLayout: settings.broadcast_layout
}
end
```

This handler generates the three strings that the client (JavaScript) needs to connect
to the session: `apiKey`, `sessionId`, and `token`. The `initialBroadcastId` is the broadcast ID,
`focusStreamId` is the stream ID that has the current focus (if there is one), and
`initialLayout` is the initial layout for the current broadcast in progress (if there is one).
(We will discuss focus stream and broadcast layout below.)

In the host page, the user presses the 'Start Broadcast' button, which sends an XHR (or Ajax)
request to the <http://localhost:4567/start> URL. The route handler for this URL is shown below:

```ruby
post '/start' do
opts = {
:maxDuration => params.key?("maxDuration") ? params[:maxDuration] : 7200,
:resolution => params[:resolution],
:layout => params[:layout],
:outputs => {
:hls => {}
}
}
broadcast = settings.opentok.broadcasts.create(settings.session.session_id, opts)
settings.broadcast_id = broadcast.id
body broadcast.to_json
end
```

In this handler, `opentok.broadcasts.create` is called with the `session_id` for
the OpenTok session to broadcast. The optional second argument is a hash which defines
optional properties for the broadcast. It consists of `maxDuration` of the broadcast,
`resolution`, and broadcast `layout`. This sample app starts an HLS broadcast (not RTMP),
so it only specifies an `hls` property of the `outputs` property. See the
[Ruby SDK documentation](https://github.com/opentok/OpenTok-Ruby-SDK) for information
on adding RTMP broadcast streams. In this case, as in the HelloWorld sample app, there is
only one session created and it is used here and for the participant view.
This will trigger the broadcasting to begin. The response sent back to the client’s XHR request
will be the JSON representation of the broadcast, which is returned from the `to_json()` method.

You can view the HLS broadcast by opening the root URL (<http://localhost:4567/>) in
a different tab and clicking the `Broadcast URL` button. The code for handling this is as follows:

```ruby
get '/broadcast' do
return 'No broadcast id exists' if settings.broadcast_id.nil? || settings.broadcast_id.empty?
broadcast = settings.opentok.broadcasts.find settings.broadcast_id
redirect broadcast.broadcastUrls['hls'] if broadcast.status == 'started'
end
```

The route for Stop Broadcast has the following code:

```ruby
get '/stop/:broadcastId' do
broadcast = settings.opentok.broadcasts.stop settings.broadcast_id
settings.broadcast_id = nil
settings.focus_stream_id = ''
settings.broadcast_layout = 'horizontalPresentation'
body broadcast.to_json
end
```

The settings revert backs to the settings when you start the app.

The host page includes a `Toggle Layout` button, which toggles between
`verticalPresentation` and `horizontalPresentation`.

The route for `Toggle Layout` has the following code:

```ruby
post '/broadcast/:broadcastId/layout' do
layoutType = params[:type]
settings.opentok.broadcasts.layout(settings.broadcast_id, type: layoutType)
settings.broadcast_layout = layoutType
end
```

This calls the `opentok.broadcasts.layout()` method, setting the broadcast layout to
the layout type defined in the POST request's body. In this app, the layout type is
set to `horizontalPresentation` or `verticalPresentation`, two of the [predefined layout
types](https://tokbox.com/developer/guides/broadcast/live-streaming/#predefined-layout-types)
available to live streaming broadcasts.

### Creating Broadcast - Participant View

With the host view still open and publishing, open an additional tab and navigate to
<http://localhost:4567/participant> and allow the browser to use your camera and microphone.
You will now see the participant in the broadcast.

```ruby
get '/participant' do
api_key = settings.api_key
session_id = settings.session.session_id
token = settings.opentok.generate_token(session_id, role: :publisher)

erb :participant, locals: {
apiKey: api_key,
sessionId: session_id,
token: token,
focusStreamId: settings.focus_stream_id,
layout: settings.broadcast_layout
}
end
```

### Changing the layout classes for streams

In the host page, if you click on either the host or a participant video, that video gets
the `focus` layout in the broadcast. The host page sends the `focus` stream ID and
the other streams' layout class lists can be cleared, as shown below:

```ruby
post '/focus' do
hash = { items: [] }
hash[:items] << { id: params[:focus], layoutClassList: ['focus'] }
settings.focus_stream_id = params[:focus]
if params.key?('otherStreams')
params[:otherStreams].each do |stream|
hash[:items] << { id: stream, layoutClassList: [] }
end
end
settings.opentok.streams.layout(settings.session.session_id, hash)
end
```

The host client page also uses OpenTok signaling to notify other clients when the layout type and
focus stream changes, and they then update the local display of streams in the HTML DOM accordingly.
However, this is not necessary. The layout of the broadcast is unrelated to the layout of
streams in the web clients.

When you view the broadcast stream, the layout type and focus stream changes, based on calls
to the `OpenTok.setBroadcastLayout()` and `OpenTok.setStreamClassLists()` methods during
the broadcast.

For more information, see [Configuring video layout for OpenTok live streaming
broadcasts](https://tokbox.com/developer/guides/broadcast/live-streaming/#configuring-video-layout-for-opentok-live-streaming-broadcasts).
Loading

0 comments on commit 2426a37

Please sign in to comment.