opentok 2.2.4 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +44 -17
  3. data/doc/OpenTok.html +20 -13
  4. data/doc/OpenTok/Archive.html +350 -68
  5. data/doc/OpenTok/ArchiveList.html +3 -3
  6. data/doc/OpenTok/Archives.html +114 -42
  7. data/doc/OpenTok/HashExtensions.html +184 -0
  8. data/doc/OpenTok/OpenTok.html +89 -44
  9. data/doc/OpenTok/OpenTokArchiveError.html +3 -3
  10. data/doc/OpenTok/OpenTokAuthenticationError.html +3 -3
  11. data/doc/OpenTok/OpenTokError.html +3 -3
  12. data/doc/OpenTok/Session.html +116 -24
  13. data/doc/_index.html +22 -7
  14. data/doc/class_list.html +6 -2
  15. data/doc/file.README.html +3 -3
  16. data/doc/file_list.html +5 -1
  17. data/doc/frames.html +1 -1
  18. data/doc/index.html +3 -3
  19. data/doc/js/full_list.js +4 -1
  20. data/doc/method_list.html +45 -11
  21. data/doc/top-level-namespace.html +3 -3
  22. data/lib/extensions/hash.rb +12 -0
  23. data/lib/opentok/archive.rb +22 -2
  24. data/lib/opentok/archives.rb +33 -6
  25. data/lib/opentok/client.rb +21 -4
  26. data/lib/opentok/constants.rb +1 -0
  27. data/lib/opentok/opentok.rb +25 -13
  28. data/lib/opentok/session.rb +6 -3
  29. data/lib/opentok/version.rb +1 -1
  30. data/sample/Archiving/README.md +16 -10
  31. data/sample/Archiving/archiving_sample.rb +6 -3
  32. data/sample/Archiving/public/js/host.js +25 -12
  33. data/sample/Archiving/views/host.erb +24 -0
  34. data/sample/HelloWorld/README.md +1 -1
  35. data/spec/cassettes/OpenTok_Archives/should_create_archives.yml +1 -1
  36. data/spec/cassettes/OpenTok_Archives/should_create_audio_only_archives.yml +50 -0
  37. data/spec/cassettes/OpenTok_Archives/should_create_individual_archives.yml +51 -0
  38. data/spec/cassettes/OpenTok_Archives/should_find_paused_archives_by_id.yml +46 -0
  39. data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_always_archived_sessions.yml +39 -0
  40. data/spec/opentok/archives_spec.rb +32 -0
  41. data/spec/opentok/opentok_spec.rb +27 -3
  42. data/spec/spec_helper.rb +1 -0
  43. metadata +36 -26
@@ -1,11 +1,16 @@
1
1
  require "opentok/exceptions"
2
+ require "extensions/hash"
2
3
 
4
+ require "active_support/inflector"
3
5
  require "httparty"
4
6
 
5
7
  module OpenTok
6
8
  # @private For internal use by the SDK.
7
9
  class Client
8
10
  include HTTParty
11
+
12
+ default_timeout 1 # Set HTTParty default timeout (open/read) to 1 second
13
+
9
14
  # TODO: expose a setting for http debugging for developers
10
15
  # debug_output $stdout
11
16
 
@@ -19,7 +24,8 @@ module OpenTok
19
24
  end
20
25
 
21
26
  def create_session(opts)
22
- response = self.class.post("/session/create", :body => opts)
27
+ opts.extend(HashExtensions)
28
+ response = self.class.post("/session/create", :body => opts.camelize_keys!)
23
29
  case response.code
24
30
  when (200..300)
25
31
  response
@@ -28,11 +34,13 @@ module OpenTok
28
34
  else
29
35
  raise OpenTokError, "Failed to create session. Response code: #{response.code}"
30
36
  end
37
+ rescue StandardError => e
38
+ raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
31
39
  end
32
40
 
33
41
  def start_archive(session_id, opts)
34
- body = { "sessionId" => session_id }
35
- body["name"] = opts[:name] unless opts[:name].nil?
42
+ opts.extend(HashExtensions)
43
+ body = { "sessionId" => session_id }.merge(opts.camelize_keys!)
36
44
  response = self.class.post("/v2/partner/#{@api_key}/archive", {
37
45
  :body => body.to_json,
38
46
  :headers => { "Content-Type" => "application/json" }
@@ -51,6 +59,8 @@ module OpenTok
51
59
  else
52
60
  raise OpenTokArchiveError, "The archive could not be started"
53
61
  end
62
+ rescue StandardError => e
63
+ raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
54
64
  end
55
65
 
56
66
  def get_archive(archive_id)
@@ -65,6 +75,8 @@ module OpenTok
65
75
  else
66
76
  raise OpenTokArchiveError, "The archive could not be retrieved."
67
77
  end
78
+ rescue StandardError => e
79
+ raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
68
80
  end
69
81
 
70
82
  def list_archives(offset, count)
@@ -82,6 +94,8 @@ module OpenTok
82
94
  else
83
95
  raise OpenTokArchiveError, "The archives could not be retrieved."
84
96
  end
97
+ rescue StandardError => e
98
+ raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
85
99
  end
86
100
 
87
101
  def stop_archive(archive_id)
@@ -102,6 +116,8 @@ module OpenTok
102
116
  else
103
117
  raise OpenTokArchiveError, "The archive could not be stopped."
104
118
  end
119
+ rescue StandardError => e
120
+ raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
105
121
  end
106
122
 
107
123
  def delete_archive(archive_id)
@@ -118,7 +134,8 @@ module OpenTok
118
134
  else
119
135
  raise OpenTokArchiveError, "The archive could not be deleted."
120
136
  end
137
+ rescue StandardError => e
138
+ raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}"
121
139
  end
122
-
123
140
  end
124
141
  end
@@ -2,4 +2,5 @@ module OpenTok
2
2
  API_URL = "https://api.opentok.com"
3
3
  TOKEN_SENTINEL = "T1=="
4
4
  ROLES = { subscriber: "subscriber", publisher: "publisher", moderator: "moderator" }
5
+ ARCHIVE_MODES = Set.new([:manual, :always])
5
6
  end
@@ -5,6 +5,7 @@ require "opentok/token_generator"
5
5
  require "opentok/archives"
6
6
 
7
7
  require "resolv"
8
+ require "set"
8
9
 
9
10
  module OpenTok
10
11
  # Contains methods for creating OpenTok sessions, generating tokens, and working with archives.
@@ -21,11 +22,11 @@ module OpenTok
21
22
  # @!method generate_token(options)
22
23
  # Generates a token for a given session.
23
24
  #
24
- # @param [String] sessioin_id The session ID of the session to be accessed by the client using
25
+ # @param [String] session_id The session ID of the session to be accessed by the client using
25
26
  # the token.
26
27
  #
27
28
  # @param [Hash] options A hash defining options for the token.
28
- # @option options [String] :role The role for the token. Set this to one of the following
29
+ # @option options [Symbol] :role The role for the token. Set this to one of the following
29
30
  # values:
30
31
  # * <code>:subscriber</code> -- A subscriber can only subscribe to streams.
31
32
  #
@@ -64,7 +65,7 @@ module OpenTok
64
65
  # (https://dashboard.tokbox.com).
65
66
  # @param [String] api_secret Your OpenTok API key.
66
67
  # @param [String] api_url Do not set this parameter. It is for internal use by TokBox.
67
- def initialize(api_key, api_secret , api_url = ::OpenTok::API_URL)
68
+ def initialize(api_key, api_secret, api_url=::OpenTok::API_URL)
68
69
  @api_key = api_key.to_s()
69
70
  @api_secret = api_secret
70
71
  # TODO: do we really need a copy of this in the instance or should we overwrite the module
@@ -92,41 +93,46 @@ module OpenTok
92
93
  #
93
94
  # @param [Hash] opts (Optional) This hash defines options for the session.
94
95
  #
95
- # @option opts [String] :media_mode Determines whether the session will transmit streams the
96
+ # @option opts [Symbol] :media_mode Determines whether the session will transmit streams the
96
97
  # using OpenTok Media Router (<code>:routed</code>) or not (<code>:relayed</code>).
97
98
  # By default, this property is set to <code>:relayed</code>.
98
99
  #
99
- # With the <code>mediaMode</code> property set to <code>:relayed</code>, the session
100
+ # With the <code>media_mode</code> property set to <code>:relayed</code>, the session
100
101
  # will attempt to transmit streams directly between clients. If clients cannot connect due to
101
102
  # firewall restrictions, the session uses the OpenTok TURN server to relay audio-video
102
103
  # streams.
103
104
  #
104
- # With the <code>mediaMode</code> property set to <code>:routed</code>, the session
105
- # will use the {http://tokbox.com/#multiparty OpenTok Media Router}.
105
+ # With the <code>media_mode</code> property set to <code>:routed</code>, the session will use
106
+ # the {https://tokbox.com/opentok/tutorials/create-session/#media-mode OpenTok Media Router}.
106
107
  # The OpenTok Media Router provides the following benefits:
107
108
  #
108
109
  # * The OpenTok Media Router can decrease bandwidth usage in multiparty sessions.
109
- # (When the <code>mediaMode</code> property is set to <code>:relayed</code>,
110
+ # (When the <code>media_mode</code> property is set to <code>:relayed</code>,
110
111
  # each client must send a separate audio-video stream to each client subscribing to
111
112
  # it.)
112
113
  # * The OpenTok Media Router can improve the quality of the user experience through
113
- # {http://tokbox.com/#iqc Intelligent Quality Control}. With
114
- # Intelligent Quality Control, if a client's connectivity degrades to a degree that
114
+ # {https://tokbox.com/platform/fallback audio fallback and video recovery}. With
115
+ # these features, if a client's connectivity degrades to a degree that
115
116
  # it does not support video for a stream it's subscribing to, the video is dropped on
116
117
  # that client (without affecting other clients), and the client receives audio only.
117
118
  # If the client's connectivity improves, the video returns.
118
- # * The OpenTok Media Router supports the {http://tokbox.com/platform/archiving archiving}
119
+ # * The OpenTok Media Router supports the
120
+ # {https://tokbox.com/opentok/tutorials/archiving archiving}
119
121
  # feature, which lets you record, save, and retrieve OpenTok sessions.
120
122
  #
121
123
  # @option opts [String] :location An IP address that the OpenTok servers will use to
122
124
  # situate the session in its global network. If you do not set a location hint,
123
125
  # the OpenTok servers will be based on the first client connecting to the session.
124
126
  #
127
+ # @option opts [Symbol] :archive_mode Determines whether the session will be archived
128
+ # automatically (<code>:always</code>) or not (<code>:manual</code>). When using automatic
129
+ # archiving, the session must use the <code>:routed</code> media mode.
130
+ #
125
131
  # @return [Session] The Session object. The session_id property of the object is the session ID.
126
132
  def create_session(opts={})
127
133
 
128
134
  # normalize opts so all keys are symbols and only include valid_opts
129
- valid_opts = [ :media_mode, :location ]
135
+ valid_opts = [ :media_mode, :location, :archive_mode ]
130
136
  opts = opts.inject({}) do |m,(k,v)|
131
137
  if valid_opts.include? k.to_sym
132
138
  m[k.to_sym] = v
@@ -150,12 +156,18 @@ module OpenTok
150
156
  unless params[:location].nil?
151
157
  raise "location must be an IPv4 address" unless params[:location] =~ Resolv::IPv4::Regex
152
158
  end
159
+ # archive mode is optional, but it has to be one of the valid values if present
160
+ unless params[:archive_mode].nil?
161
+ raise "archive mode must be either always or manual" unless ARCHIVE_MODES.include? params[:archive_mode].to_sym
162
+ end
163
+
164
+ raise "A session with always archive mode must also have the routed media mode." if (params[:archive_mode] == :always && params[:media_mode] == :relayed)
153
165
 
154
166
  response = client.create_session(params)
155
167
  Session.new api_key, api_secret, response['sessions']['Session']['session_id'], opts
156
168
  end
157
169
 
158
- # An Archives object, which lets you work with OpenTok 2.0 archives.
170
+ # An Archives object, which lets you work with OpenTok archives.
159
171
  def archives
160
172
  @archives ||= Archives.new client
161
173
  end
@@ -17,11 +17,14 @@ module OpenTok
17
17
  # @attr_reader [String] location The location hint IP address. See the OpenTok.createSession()
18
18
  # method.
19
19
  #
20
+ # @attr_reader [String] archive_mode Whether the session will be archived automatically
21
+ # (<code>:always</code>) or not (<code>:manual</code>).
22
+ #
20
23
  # @!method generate_token(options)
21
24
  # Generates a token.
22
25
  #
23
26
  # @param [Hash] options
24
- # @option options [String] :role The role for the token. Set this to one of the following
27
+ # @option options [Symbol] :role The role for the token. Set this to one of the following
25
28
  # values:
26
29
  # * <code>:subscriber</code> -- A subscriber can only subscribe to streams.
27
30
  #
@@ -49,7 +52,7 @@ module OpenTok
49
52
  :session_id => ->(instance) { instance.session_id }
50
53
  })
51
54
 
52
- attr_reader :session_id, :media_mode, :location, :api_key, :api_secret
55
+ attr_reader :session_id, :media_mode, :location, :archive_mode, :api_key, :api_secret
53
56
 
54
57
  # @private
55
58
  # this implementation doesn't completely understand the format of a Session ID
@@ -65,7 +68,7 @@ module OpenTok
65
68
  # @private
66
69
  def initialize(api_key, api_secret, session_id, opts={})
67
70
  @api_key, @api_secret, @session_id = api_key, api_secret, session_id
68
- @media_mode, @location = opts.fetch(:media_mode, :relayed), opts[:location]
71
+ @media_mode, @location, @archive_mode = opts.fetch(:media_mode, :relayed), opts[:location], opts.fetch(:archive_mode, :manual)
69
72
  end
70
73
 
71
74
  # @private
@@ -1,4 +1,4 @@
1
1
  module OpenTok
2
2
  # @private
3
- VERSION = '2.2.4'
3
+ VERSION = '2.3.0'
4
4
  end
@@ -25,7 +25,7 @@ Finally, start the server using Bundler to handle dependencies
25
25
  $ bundle exec ruby archiving_sample.rb
26
26
  ```
27
27
 
28
- Visit <http://localhost:9393> in your browser. You can now create new archives (either as a host or
28
+ Visit <http://localhost:4567> in your browser. You can now create new archives (either as a host or
29
29
  as a participant) and also play archives that have already been created.
30
30
 
31
31
  ## Walkthrough
@@ -38,7 +38,7 @@ main application (archiving_sample.rb).
38
38
 
39
39
  ### Creating Archives – Host View
40
40
 
41
- Start by visiting the host page at <http://localhost:9393/host> and using the application to record
41
+ Start by visiting the host page at <http://localhost:4567/host> and using the application to record
42
42
  an archive. Your browser will first ask you to approve permission to use the camera and microphone.
43
43
  Once you've accepted, your image will appear inside the section titled 'Host'. To start recording
44
44
  the video stream, press the 'Start Archiving' button. Once archiving has begun the button will turn
@@ -65,27 +65,33 @@ end
65
65
  If you've completed the HelloWorld walkthrough, this should look familiar. This handler simply
66
66
  generates the three strings that the client (JavaScript) needs to connect to the session: `api_key`,
67
67
  `session_id` and `token`. After the user has connected to the session, they press the
68
- 'Start Archiving' button, which sends an XHR (or Ajax) request to the <http://localhost:9393/start>
68
+ 'Start Archiving' button, which sends an XHR (or Ajax) request to the <http://localhost:4567/start>
69
69
  URL. The route handler for this URL is shown below:
70
70
 
71
71
  ```ruby
72
- get '/start' do
72
+ post '/start' do
73
73
  archive = settings.opentok.archives.create settings.session.session_id, {
74
- :name => "Ruby Archiving Sample App"
74
+ :name => "Ruby Archiving Sample App",
75
+ :output_mode => params[:output_mode],
76
+ :has_audio => params[:has_audio] == "on",
77
+ :has_video => params[:has_video] == "on"
75
78
  }
76
79
  body archive.to_json
77
80
  end
78
81
  ```
79
82
 
80
83
  In this handler, `opentok.archives.create` is called with the `session_id` for the session that
81
- needs to be archived. The optional second argument is a hash which contains a `:name` key. The value
82
- is a string that will be stored with the archive and can be read later. In this case, as in the
84
+ needs to be archived. The optional second argument is a hash which defines optional properties
85
+ for the archive. The `:name` value defines the archive's name, which is stored with the archive and
86
+ can be read later. The `:has_audio`, `:has_video`, and `:output_mode` values are read from the
87
+ request body; these define whether the archive will record audio and video, and whether it will
88
+ record streams individually or to a single file composed of all streams. In this case, as in the
83
89
  HelloWorld sample app, there is only one session created and it is used here and for the participant
84
90
  view. This will trigger the recording to begin. The response sent back to the client's XHR request
85
91
  will be the JSON representation of the archive, which is returned from the `to_json()` method. The
86
92
  client is also listening for the `archiveStarted` event, and uses that event to change the
87
93
  'Start Archiving' button to show 'Stop Archiving' instead. When the user presses the button this
88
- time, another XHR request is sent to the <http://localhost:9393/stop/:archiveId> URL where
94
+ time, another XHR request is sent to the <http://localhost:4567/stop/:archiveId> URL where
89
95
  `:archiveId` represents the ID the client receives in the 'archiveStarted' event. The route handler
90
96
  for this request is shown below:
91
97
 
@@ -109,7 +115,7 @@ be found in the `public/js/host.js` file. Read about the
109
115
  ### Creating Archives - Participant View
110
116
 
111
117
  With the host view still open and publishing, open an additional window or tab and navigate to
112
- <http://localhost:9393/participant> and allow the browser to use your camera and microphone. Once
118
+ <http://localhost:4567/participant> and allow the browser to use your camera and microphone. Once
113
119
  again, start archiving in the host view. Back in the participant view, notice that the red blinking
114
120
  indicator has been shown so that the participant knows his video is being recorded. Now stop the
115
121
  archiving in the host view. Notice that the indicator has gone away in the participant view too.
@@ -137,7 +143,7 @@ in the client, in code that can be found in the `public/js/participant.js` file.
137
143
 
138
144
  ### Past Archives
139
145
 
140
- Start by visiting the history page at <http://localhost:9393/history>. You will see a table that
146
+ Start by visiting the history page at <http://localhost:4567/history>. You will see a table that
141
147
  displays all the archives created with your API Key. If there are more than five, the older ones
142
148
  can be seen by clicking the "Older →" link. If you click on the name of an archive, your browser
143
149
  will start downloading the archive file. If you click the "Delete" link in the end of the row
@@ -7,7 +7,7 @@ class ArchivingSample < Sinatra::Base
7
7
 
8
8
  set :api_key, ENV['API_KEY']
9
9
  set :opentok, OpenTok::OpenTok.new(api_key, ENV['API_SECRET'])
10
- set :session, opentok.create_session :media_mode => :routed
10
+ set :session, opentok.create_session(:media_mode => :routed)
11
11
  set :erb, :layout => :layout
12
12
 
13
13
  get '/' do
@@ -58,9 +58,12 @@ class ArchivingSample < Sinatra::Base
58
58
  redirect archive.url
59
59
  end
60
60
 
61
- get '/start' do
61
+ post '/start' do
62
62
  archive = settings.opentok.archives.create settings.session.session_id, {
63
- :name => "Ruby Archiving Sample App"
63
+ :name => "Ruby Archiving Sample App",
64
+ :output_mode => params[:output_mode],
65
+ :has_audio => params[:has_audio] == "on",
66
+ :has_video => params[:has_video] == "on"
64
67
  }
65
68
  body archive.to_json
66
69
  end
@@ -1,5 +1,5 @@
1
1
  var session = OT.initSession(sessionId),
2
- publisher = OT.initPublisher("publisher"),
2
+ publisher = OT.initPublisher('publisher'),
3
3
  archiveID = null;
4
4
 
5
5
  session.connect(apiKey, token, function(err, info) {
@@ -10,28 +10,41 @@ session.connect(apiKey, token, function(err, info) {
10
10
  });
11
11
 
12
12
  session.on('streamCreated', function(event) {
13
- session.subscribe(event.stream, "subscribers", { insertMode: "append" });
13
+ session.subscribe(event.stream, 'subscribers', { insertMode: 'append' });
14
14
  });
15
15
 
16
16
  session.on('archiveStarted', function(event) {
17
17
  archiveID = event.id;
18
- console.log("ARCHIVE STARTED");
19
- $(".start").hide();
20
- $(".stop").show();
18
+ console.log('ARCHIVE STARTED');
19
+ $('.start').hide();
20
+ $('.stop').show();
21
+ disableForm();
21
22
  });
22
23
 
23
24
  session.on('archiveStopped', function(event) {
24
25
  archiveID = null;
25
- console.log("ARCHIVE STOPPED");
26
- $(".start").show();
27
- $(".stop").hide();
26
+ console.log('ARCHIVE STOPPED');
27
+ $('.start').show();
28
+ $('.stop').hide();
29
+ enableForm();
28
30
  });
29
31
 
30
32
  $(document).ready(function() {
31
- $(".start").click(function(event){
32
- $.get("start");
33
+ $('.start').click(function (event) {
34
+ var options = $('.archive-options').serialize();
35
+ disableForm();
36
+ $.post('/start', options).fail(enableForm);
33
37
  }).show();
34
- $(".stop").click(function(event){
35
- $.get("stop/" + archiveID);
38
+ $('.stop').click(function(event){
39
+ $.get('stop/' + archiveID);
36
40
  }).hide();
37
41
  });
42
+
43
+
44
+ function disableForm() {
45
+ $('.archive-options-fields').attr('disabled', 'disabled');
46
+ }
47
+
48
+ function enableForm() {
49
+ $('.archive-options-fields').removeAttr('disabled');
50
+ }
@@ -12,6 +12,30 @@
12
12
  <div id="subscribers"><div id="publisher"></div></div>
13
13
  </div>
14
14
  <div class="panel-footer">
15
+ <form class="archive-options">
16
+ <fieldset class="archive-options-fields">
17
+ <div class="form-group">
18
+ <p class="help-block">Archive Options:</p>
19
+ <label class="checkbox-inline">
20
+ <input type="checkbox" name="has_audio" checked> Audio
21
+ </label>
22
+ <label class="checkbox-inline">
23
+ <input type="checkbox" name="has_video" checked> Video
24
+ </label>
25
+ </div>
26
+
27
+ <div class="form-group">
28
+ <p class="help-block">Output Mode:</p>
29
+ <label class="radio-inline">
30
+ <input type="radio" name="output_mode" value="composed" checked> Composed
31
+ </label>
32
+ <label class="radio-inline">
33
+ <input type="radio" name="output_mode" value="individual"> Individual
34
+ </label>
35
+ </div>
36
+ </fieldset>
37
+ </form>
38
+ <br>
15
39
  <button class="btn btn-danger start">Start archiving</button>
16
40
  <button class="btn btn-success stop">Stop archiving</button>
17
41
  </div>
@@ -26,7 +26,7 @@ Finally, start the server using Bundler to handle dependencies
26
26
  $ bundle exec ruby hello_world.rb
27
27
  ```
28
28
 
29
- Visit <http://localhost:9393> in your browser. Open it again in a second window. Smile! You've just
29
+ Visit <http://localhost:4567> in your browser. Open it again in a second window. Smile! You've just
30
30
  set up a group chat.
31
31
 
32
32
  ## Walkthrough
@@ -5,7 +5,7 @@ http_interactions:
5
5
  uri: https://api.opentok.com/v2/partner/123456/archive
6
6
  body:
7
7
  encoding: UTF-8
8
- string: '{"sessionId":"SESSIONID","name":""}'
8
+ string: '{"sessionId":"SESSIONID"}'
9
9
  headers:
10
10
  X-Tb-Partner-Auth:
11
11
  - 123456:1234567890abcdef1234567890abcdef1234567890
@@ -0,0 +1,50 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.opentok.com/v2/partner/123456/archive
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"sessionId":"SESSIONID","hasVideo":false}'
9
+ headers:
10
+ X-Tb-Partner-Auth:
11
+ - 123456:1234567890abcdef1234567890abcdef1234567890
12
+ User-Agent:
13
+ - OpenTok-Ruby-SDK/<%= version %>
14
+ Content-Type:
15
+ - application/json
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Server:
22
+ - nginx
23
+ Date:
24
+ - Wed, 19 Mar 2014 01:49:22 GMT
25
+ Content-Type:
26
+ - application/json
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ body:
32
+ encoding: UTF-8
33
+ string: |-
34
+ {
35
+ "createdAt" : 1395193762293,
36
+ "duration" : 0,
37
+ "id" : "d7f4d2a3-da74-414d-868a-190532a835bc",
38
+ "name" : "ARCHIVE NAME",
39
+ "partnerId" : 123456,
40
+ "reason" : "",
41
+ "sessionId" : "SESSIONID",
42
+ "size" : 0,
43
+ "status" : "started",
44
+ "url" : null,
45
+ "hasAudio" : true,
46
+ "hasVideo" : false
47
+ }
48
+ http_version:
49
+ recorded_at: Wed, 19 Mar 2014 01:49:22 GMT
50
+ recorded_with: VCR 2.8.0