Skip to content

Commit 7573f63

Browse files
authored
Merge pull request #247 from opentok/devx-5908-audio-streamer-lite
DEVX-5908 Implement Audio Connector functionality
2 parents 876b027 + 45ed2dd commit 7573f63

File tree

7 files changed

+146
-2
lines changed

7 files changed

+146
-2
lines changed

README.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The OpenTok Ruby SDK provides methods for:
1818
* [Disconnecting clients from sessions](https://tokbox.com/developer/guides/moderation/rest/)
1919
* [Forcing clients in a session to disconnect or mute published audio](https://tokbox.com/developer/guides/moderation/)
2020
* Working with OpenTok [Experience Composers](https://tokbox.com/developer/guides/experience-composer)
21+
* Working with OpenTok [Audio Connector](https://tokbox.com/developer/guides/audio-connector)
2122

2223
## Installation
2324

@@ -188,7 +189,10 @@ archive = opentok.archives.create session_id :output_mode => :individual
188189
The `:output_mode => :composed` setting (the default) causes all streams in the archive to be
189190
recorded to a single (composed) file.
190191

191-
For composed archives you can set the resolution of the archive, either "640x480" (SD landscape, the default), "1280x720" (HD landscape), "1920x1080" (FHD landscape), "480x640" (SD portrait), "720x1280" (HD portrait), or "1080x1920" (FHD portrait).. The `resolution` parameter is optional and could be included in the options
192+
For composed archives you can set the resolution of the archive, either "640x480"
193+
(SD landscape, the default), "1280x720" (HD landscape), "1920x1080" (FHD landscape),
194+
"480x640" (SD portrait), "720x1280" (HD portrait), or "1080x1920" (FHD portrait).
195+
The `resolution` parameter is optional and could be included in the options
192196
hash (second argument) of the `opentok.archives.create()` method.
193197

194198
```ruby
@@ -495,6 +499,11 @@ You can stop an Experience Composer by calling the `opentok.renders.stop(render_
495499
You can get information about Experience Composers by calling the `opentok.renders.find(render_id)`
496500
and `opentok.renders.list(options)` methods.
497501

502+
### Working with Audio Connector
503+
504+
You can start an [Audio Connector](https://tokbox.com/developer/guides/audio-connect) WebSocket
505+
by calling the `opentok.websocket.connect()` method.
506+
498507
## Samples
499508

500509
There are three sample applications included in this repository. To get going as fast as possible, clone the whole

lib/opentok/client.rb

+29
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,35 @@ def signal(session_id, connection_id, opts)
298298
raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
299299
end
300300

301+
def connect_websocket(session_id, token, websocket_uri, opts)
302+
opts.extend(HashExtensions)
303+
body = { "sessionId" => session_id,
304+
"token" => token,
305+
"websocket" => { "uri" => websocket_uri }.merge(opts.camelize_keys!)
306+
}
307+
308+
response = self.class.post("/v2/project/#{@api_key}/connect", {
309+
:body => body.to_json,
310+
:headers => generate_headers("Content-Type" => "application/json")
311+
})
312+
case response.code
313+
when 200
314+
response
315+
when 400
316+
raise ArgumentError, "One of the properties is invalid."
317+
when 403
318+
raise OpenTokAuthenticationError, "You are not authorized to start the call, check your authentication information."
319+
when 409
320+
raise OpenTokWebSocketError, "Conflict. Only routed sessions are allowed to initiate Connect Calls."
321+
when 500
322+
raise OpenTokError, "OpenTok server error."
323+
else
324+
raise OpenTokWebSocketError, "The WebSocket could not be connected"
325+
end
326+
rescue StandardError => e
327+
raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
328+
end
329+
301330
def dial(session_id, token, sip_uri, opts)
302331
opts.extend(HashExtensions)
303332
body = { "sessionId" => session_id,

lib/opentok/exceptions.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ class OpenTokConnectionError < OpenTokError; end
1414
class OpenTokStreamLayoutError < OpenTokError; end
1515
# Defines errors raised when you perform Broadcast operations.
1616
class OpenTokBroadcastError < OpenTokError; end
17+
# Defines errors raised when connecting to WebSocket URIs.
18+
class OpenTokWebSocketError < OpenTokError; end
1719
# Defines errors raised when you perform Experience Composer render operations.
1820
class OpenTokRenderError < OpenTokError; end
19-
2021
end

lib/opentok/opentok.rb

+5
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ def connections
218218
@connections ||= Connections.new client
219219
end
220220

221+
# A WebSocket object, which lets you connect OpenTok streams to a WebSocket URI.
222+
def websocket
223+
@websocket ||= WebSocket.new client
224+
end
225+
221226
protected
222227
def client
223228
@client ||= Client.new api_key, api_secret, api_url, ua_addendum, timeout_length: @timeout_length

lib/opentok/websocket.rb

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
require "opentok/client"
2+
3+
# An object that lets you work with Audio Connector WebSocket connections.
4+
module OpenTok
5+
class WebSocket
6+
# Starts an Audio Connector WebSocket connection to send audio from a Vonage Video API session to a WebSocket URI.
7+
# See the {https://tokbox.com/developer/guides/audio-connector/ OpenTok Audio Connector developer guide}.
8+
#
9+
# @example
10+
# opts = {
11+
# "streams" => ["STREAMID1", "STREAMID2"],
12+
# "headers" => {
13+
# "key1" => "val1",
14+
# "key2" => "val2"
15+
# }
16+
# }
17+
# response = opentok.websocket.connect(SESSIONID, TOKEN, "ws://service.com/wsendpoint", opts)
18+
#
19+
# @param [String] session_id (required) The OpenTok session ID that includes the OpenTok streams you want to include in
20+
# the WebSocket stream.
21+
# @param [String] token (required) The OpenTok token to be used for the Audio Connector connection to the. OpenTok session.
22+
# @param [String] websocket_uri (required) A publicly reachable WebSocket URI to be used for the destination of the audio
23+
# stream (such as "wss://service.com/ws-endpoint").
24+
# @param [Hash] opts (optional) A hash defining options for the Audio Connector WebSocket connection. For example:
25+
# @option opts [Array] :streams (optional) An array of stream IDs for the OpenTok streams you want to include in the WebSocket stream.
26+
# If you omit this property, all streams in the session will be included.
27+
# @option opts [Hash] :headers (optional) A hash of key-value pairs of headers to be sent to your WebSocket server with each message,
28+
# with a maximum length of 512 bytes.
29+
def connect(session_id, token, websocket_uri, opts = {})
30+
response = @client.connect_websocket(session_id, token, websocket_uri, opts)
31+
end
32+
33+
def initialize(client)
34+
@client = client
35+
end
36+
end
37+
end

spec/cassettes/OpenTok_WebSocket/receives_a_valid_response.yml

+37
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/opentok/websocket_spec.rb

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
require "opentok/opentok"
2+
require "opentok/websocket"
3+
require "opentok/version"
4+
require "spec_helper"
5+
6+
describe OpenTok::WebSocket do
7+
before(:each) do
8+
now = Time.parse("2017-04-18 20:17:40 +1000")
9+
allow(Time).to receive(:now) { now }
10+
end
11+
12+
let(:api_key) { "123456" }
13+
let(:api_secret) { "1234567890abcdef1234567890abcdef1234567890" }
14+
let(:session_id) { "SESSIONID" }
15+
let(:connection_id) { "CONNID" }
16+
let(:expiring_token) { "TOKENID" }
17+
let(:websocket_uri) { "ws://service.com/wsendpoint" }
18+
let(:opentok) { OpenTok::OpenTok.new api_key, api_secret }
19+
let(:websocket) { opentok.websocket }
20+
subject { websocket }
21+
22+
it "receives a valid response", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do
23+
response = websocket.connect(session_id, expiring_token, websocket_uri)
24+
expect(response).not_to be_nil
25+
end
26+
end

0 commit comments

Comments
 (0)