opentok 0.1.3 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +16 -2
- data/.travis.yml +6 -0
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +47 -0
- data/DEVELOPING.md +91 -0
- data/LICENSE +19 -5
- data/README.md +170 -53
- data/Rakefile +10 -5
- data/doc/OpenTok.html +411 -0
- data/doc/OpenTok/Archive.html +1320 -0
- data/doc/OpenTok/ArchiveList.html +216 -0
- data/doc/OpenTok/Archives.html +1028 -0
- data/doc/OpenTok/Client.html +695 -0
- data/doc/OpenTok/OpenTok.html +1046 -0
- data/doc/OpenTok/OpenTokArchiveError.html +142 -0
- data/doc/OpenTok/OpenTokAuthenticationError.html +143 -0
- data/doc/OpenTok/OpenTokError.html +138 -0
- data/doc/OpenTok/Session.html +665 -0
- data/doc/OpenTok/TokenGenerator.html +204 -0
- data/doc/OpenTok/TokenGenerator/ClassMethods.html +187 -0
- data/doc/README.md +15 -0
- data/doc/_index.html +182 -0
- data/doc/class_list.html +54 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +339 -0
- data/doc/file.README.html +87 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +87 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +178 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +227 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/opentok.rb +3 -14
- data/lib/opentok/archive.rb +92 -0
- data/lib/opentok/archive_list.rb +17 -0
- data/lib/opentok/archives.rb +120 -0
- data/lib/opentok/client.rb +125 -0
- data/lib/opentok/constants.rb +5 -0
- data/lib/opentok/exceptions.rb +10 -0
- data/lib/opentok/opentok.rb +174 -0
- data/lib/opentok/session.rb +76 -0
- data/lib/opentok/token_generator.rb +101 -0
- data/lib/opentok/version.rb +4 -0
- data/opentok.gemspec +29 -22
- data/sample/Archiving/Gemfile +4 -0
- data/sample/Archiving/README.md +212 -0
- data/sample/Archiving/archiving_sample.rb +80 -0
- data/sample/Archiving/public/css/sample.css +22 -0
- data/sample/Archiving/public/img/archiving-off.png +0 -0
- data/sample/Archiving/public/img/archiving-on-idle.png +0 -0
- data/sample/Archiving/public/img/archiving-on-message.png +0 -0
- data/sample/Archiving/public/js/host.js +37 -0
- data/sample/Archiving/public/js/participant.js +13 -0
- data/sample/Archiving/views/history.erb +65 -0
- data/sample/Archiving/views/host.erb +69 -0
- data/sample/Archiving/views/index.erb +48 -0
- data/sample/Archiving/views/layout.erb +29 -0
- data/sample/Archiving/views/participant.erb +55 -0
- data/sample/HelloWorld/Gemfile +4 -0
- data/sample/HelloWorld/README.md +123 -0
- data/sample/HelloWorld/hello_world.rb +27 -0
- data/sample/HelloWorld/public/js/helloworld.js +32 -0
- data/sample/HelloWorld/views/index.erb +21 -0
- data/spec/cassettes/OpenTok_Archives/should_create_archives.yml +48 -0
- data/spec/cassettes/OpenTok_Archives/should_create_named_archives.yml +49 -0
- data/spec/cassettes/OpenTok_Archives/should_delete_an_archive_by_id.yml +32 -0
- data/spec/cassettes/OpenTok_Archives/should_find_archives_by_id.yml +46 -0
- data/spec/cassettes/OpenTok_Archives/should_stop_archives.yml +48 -0
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_all_archives.yml +104 -0
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_archives_with_an_offset.yml +71 -0
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_count_number_of_archives.yml +60 -0
- data/spec/cassettes/OpenTok_Archives/when_many_archives_are_created/should_return_part_of_the_archives_when_using_offset_and_count.yml +82 -0
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_default_sessions.yml +39 -0
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions.yml +39 -0
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_relayed_media_sessions_with_a_location_hint.yml +39 -0
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions.yml +39 -0
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_for_invalid_media_modes.yml +39 -0
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_routed_media_sessions_with_a_location_hint.yml +39 -0
- data/spec/cassettes/OpenTok_OpenTok/when_initialized_properly/_create_session/creates_sessions_with_a_location_hint.yml +39 -0
- data/spec/matchers/token.rb +48 -0
- data/spec/opentok/archives_spec.rb +91 -0
- data/spec/opentok/opentok_spec.rb +144 -0
- data/spec/opentok/session_spec.rb +71 -0
- data/spec/shared/opentok_generates_tokens.rb +62 -0
- data/spec/shared/session_generates_tokens.rb +63 -0
- data/spec/spec_helper.rb +6 -7
- metadata +197 -59
- data/.rspec +0 -3
- data/CHANGES +0 -33
- data/doc/reference.md +0 -122
- data/lib/open_tok/archive.rb +0 -53
- data/lib/open_tok/archive_timeline_event.rb +0 -22
- data/lib/open_tok/archive_video_resource.rb +0 -28
- data/lib/open_tok/exception.rb +0 -50
- data/lib/open_tok/open_tok_sdk.rb +0 -198
- data/lib/open_tok/request.rb +0 -63
- data/lib/open_tok/role_constants.rb +0 -18
- data/lib/open_tok/session.rb +0 -25
- data/lib/open_tok/session_property_constants.rb +0 -30
- data/lib/open_tok/utils.rb +0 -10
- data/lib/open_tok/version.rb +0 -5
- data/sample/sample.rb +0 -26
- data/spec/cassettes/archives.yml +0 -83
- data/spec/cassettes/deleteArchive.yml +0 -91
- data/spec/cassettes/invalidSession.yml +0 -41
- data/spec/cassettes/session.yml +0 -46
- data/spec/cassettes/stitchArchive.yml +0 -42
- data/spec/opentok_exception_spec.rb +0 -38
- data/spec/opentok_spec.rb +0 -135
@@ -0,0 +1,80 @@
|
|
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 ArchivingSample < 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
|
11
|
+
set :erb, :layout => :layout
|
12
|
+
|
13
|
+
get '/' do
|
14
|
+
erb :index
|
15
|
+
end
|
16
|
+
|
17
|
+
get '/host' do
|
18
|
+
api_key = settings.api_key
|
19
|
+
session_id = settings.session.session_id
|
20
|
+
token = settings.opentok.generate_token(session_id, :role => :moderator)
|
21
|
+
|
22
|
+
erb :host, :locals => {
|
23
|
+
:api_key => api_key,
|
24
|
+
:session_id => session_id,
|
25
|
+
:token => token
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
get '/participant' do
|
30
|
+
api_key = settings.api_key
|
31
|
+
session_id = settings.session.session_id
|
32
|
+
token = settings.opentok.generate_token(session_id, :role => :moderator)
|
33
|
+
|
34
|
+
erb :participant, :locals => {
|
35
|
+
:api_key => api_key,
|
36
|
+
:session_id => session_id,
|
37
|
+
:token => token
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
get '/history' do
|
42
|
+
page = (params[:page] || "1").to_i
|
43
|
+
offset = (page - 1) * 5
|
44
|
+
archives = settings.opentok.archives.all(:offset => offset, :count => 5)
|
45
|
+
|
46
|
+
show_previous = page > 1 ? '/history?page=' + (page-1).to_s : nil
|
47
|
+
show_next = archives.total > (offset + 5) ? '/history?page=' + (page+1).to_s : nil
|
48
|
+
|
49
|
+
erb :history, :locals => {
|
50
|
+
:archives => archives,
|
51
|
+
:show_previous => show_previous,
|
52
|
+
:show_next => show_next
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
get '/download/:archive_id' do
|
57
|
+
archive = settings.opentok.archives.find(params[:archive_id])
|
58
|
+
redirect archive.url
|
59
|
+
end
|
60
|
+
|
61
|
+
get '/start' do
|
62
|
+
archive = settings.opentok.archives.create settings.session.session_id, {
|
63
|
+
:name => "Ruby Archiving Sample App"
|
64
|
+
}
|
65
|
+
body archive.to_json
|
66
|
+
end
|
67
|
+
|
68
|
+
get '/stop/:archive_id' do
|
69
|
+
archive = settings.opentok.archives.stop_by_id(params[:archive_id])
|
70
|
+
body archive.to_json
|
71
|
+
end
|
72
|
+
|
73
|
+
get '/delete/:archive_id' do
|
74
|
+
settings.opentok.archives.delete_by_id(params[:archive_id])
|
75
|
+
redirect '/history'
|
76
|
+
end
|
77
|
+
|
78
|
+
# start the server if ruby file executed directly
|
79
|
+
run! if app_file == $0
|
80
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/* Move down content because we have a fixed navbar that is 50px tall */
|
2
|
+
body {
|
3
|
+
padding-top: 50px;
|
4
|
+
padding-bottom: 20px;
|
5
|
+
background-color: #F2F2F2;
|
6
|
+
}
|
7
|
+
|
8
|
+
/* Responsive: Portrait tablets and up */
|
9
|
+
@media screen and (min-width: 768px) {
|
10
|
+
/* Remove padding from wrapping element since we kick in the grid classes here */
|
11
|
+
.body-content {
|
12
|
+
padding: 0;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
#subscribers div {
|
17
|
+
float: left;
|
18
|
+
}
|
19
|
+
|
20
|
+
.bump-me {
|
21
|
+
padding-top: 40px;
|
22
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,37 @@
|
|
1
|
+
var session = OT.initSession(sessionId),
|
2
|
+
publisher = OT.initPublisher("publisher"),
|
3
|
+
archiveID = null;
|
4
|
+
|
5
|
+
session.connect(apiKey, token, function(err, info) {
|
6
|
+
if(err) {
|
7
|
+
alert(err.message || err);
|
8
|
+
}
|
9
|
+
session.publish(publisher);
|
10
|
+
});
|
11
|
+
|
12
|
+
session.on('streamCreated', function(event) {
|
13
|
+
session.subscribe(event.stream, "subscribers", { insertMode: "append" });
|
14
|
+
});
|
15
|
+
|
16
|
+
session.on('archiveStarted', function(event) {
|
17
|
+
archiveID = event.id;
|
18
|
+
console.log("ARCHIVE STARTED");
|
19
|
+
$(".start").hide();
|
20
|
+
$(".stop").show();
|
21
|
+
});
|
22
|
+
|
23
|
+
session.on('archiveStopped', function(event) {
|
24
|
+
archiveID = null;
|
25
|
+
console.log("ARCHIVE STOPPED");
|
26
|
+
$(".start").show();
|
27
|
+
$(".stop").hide();
|
28
|
+
});
|
29
|
+
|
30
|
+
$(document).ready(function() {
|
31
|
+
$(".start").click(function(event){
|
32
|
+
$.get("start");
|
33
|
+
}).show();
|
34
|
+
$(".stop").click(function(event){
|
35
|
+
$.get("stop/" + archiveID);
|
36
|
+
}).hide();
|
37
|
+
});
|
@@ -0,0 +1,13 @@
|
|
1
|
+
var session = OT.initSession(sessionId),
|
2
|
+
publisher = OT.initPublisher("publisher");
|
3
|
+
|
4
|
+
session.connect(apiKey, token, function(err, info) {
|
5
|
+
if(err) {
|
6
|
+
alert(err.message || err);
|
7
|
+
}
|
8
|
+
session.publish(publisher);
|
9
|
+
});
|
10
|
+
|
11
|
+
session.on('streamCreated', function(event) {
|
12
|
+
session.subscribe(event.stream, "subscribers", { insertMode : "append" });
|
13
|
+
});
|
@@ -0,0 +1,65 @@
|
|
1
|
+
<div class="container bump-me">
|
2
|
+
|
3
|
+
<div class="body-content">
|
4
|
+
|
5
|
+
<div class="panel panel-default">
|
6
|
+
<div class="panel-heading">
|
7
|
+
<h3 class="panel-title">Past Recordings</h3>
|
8
|
+
</div>
|
9
|
+
<div class="panel-body">
|
10
|
+
<% if archives.count > 0 %>
|
11
|
+
<table class="table">
|
12
|
+
<thead>
|
13
|
+
<tr>
|
14
|
+
<th> </th>
|
15
|
+
<th>Created</th>
|
16
|
+
<th>Duration</th>
|
17
|
+
<th>Status</th>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody>
|
21
|
+
<% for item in archives %>
|
22
|
+
|
23
|
+
<tr data-item-id="<%= item.id %>">
|
24
|
+
<td>
|
25
|
+
<% if (item.status == "available") && item.url && (item.url.length > 0) %>
|
26
|
+
<a href="/download/<%= item.id %>">
|
27
|
+
<% end %>
|
28
|
+
<%= item.name || "Untitled" %>
|
29
|
+
<% if (item.status == "available") && item.url && (item.url.length > 0) %>
|
30
|
+
</a>
|
31
|
+
<% end %>
|
32
|
+
</td>
|
33
|
+
<td><%= Time.at(item.created_at/1000).strftime("%B %e, %Y at %I:%M %p") %></td>
|
34
|
+
<td><%= item.duration %> seconds</td>
|
35
|
+
<td><%= item.status %></td>
|
36
|
+
<td>
|
37
|
+
<% if item.status == "available" %>
|
38
|
+
<a href="/delete/<%= item.id %>">Delete</a>
|
39
|
+
<% else %>
|
40
|
+
|
41
|
+
<% end %>
|
42
|
+
</td>
|
43
|
+
</tr>
|
44
|
+
|
45
|
+
<% end %>
|
46
|
+
</tbody>
|
47
|
+
</table>
|
48
|
+
<% else %>
|
49
|
+
<p>
|
50
|
+
There are no archives currently. Try making one in the <a href="/host">host view</a>.
|
51
|
+
</p>
|
52
|
+
<% end %>
|
53
|
+
</div>
|
54
|
+
<div class="panel-footer">
|
55
|
+
<% if show_previous %>
|
56
|
+
<a href="<%= show_previous %>" class="pull-left">← Newer</a>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
<% if show_next %>
|
60
|
+
<a href="<%= show_next %>" class="pull-right">Older →</a>
|
61
|
+
<% end %>
|
62
|
+
</div>
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
</div>
|
@@ -0,0 +1,69 @@
|
|
1
|
+
<script src="//static.opentok.com/webrtc/v2.2/js/opentok.min.js"></script>
|
2
|
+
|
3
|
+
<div class="container bump-me">
|
4
|
+
|
5
|
+
<div class="body-content">
|
6
|
+
|
7
|
+
<div class="panel panel-default">
|
8
|
+
<div class="panel-heading">
|
9
|
+
<h3 class="panel-title">Host</h3>
|
10
|
+
</div>
|
11
|
+
<div class="panel-body">
|
12
|
+
<div id="subscribers"><div id="publisher"></div></div>
|
13
|
+
</div>
|
14
|
+
<div class="panel-footer">
|
15
|
+
<button class="btn btn-danger start">Start archiving</button>
|
16
|
+
<button class="btn btn-success stop">Stop archiving</button>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class="panel panel-default">
|
22
|
+
<div class="panel-heading">
|
23
|
+
<h3 class="panel-title">Instructions</h3>
|
24
|
+
</div>
|
25
|
+
<div class="panel-body">
|
26
|
+
<p>
|
27
|
+
Click <strong>Start archiving</strong> to begin archiving this session.
|
28
|
+
All publishers in the session will be included, and all publishers that
|
29
|
+
join the session will be included as well.
|
30
|
+
</p>
|
31
|
+
<p>
|
32
|
+
Click <strong>Stop archiving</strong> to end archiving this session.
|
33
|
+
You can then go to <a href="/history">past archives</a> to
|
34
|
+
view your archive (once its status changes to available).
|
35
|
+
</p>
|
36
|
+
<table class="table">
|
37
|
+
<thead>
|
38
|
+
<tr>
|
39
|
+
<th>When</th>
|
40
|
+
<th>You will see</th>
|
41
|
+
</tr>
|
42
|
+
</thead>
|
43
|
+
<tbody>
|
44
|
+
<tr>
|
45
|
+
<td style="vertical-align: middle;">Archiving is started</td>
|
46
|
+
<td><img src="img/archiving-on-message.png"></td>
|
47
|
+
</tr>
|
48
|
+
<tr>
|
49
|
+
<td style="vertical-align: middle;">Archiving remains on</td>
|
50
|
+
<td><img src="img/archiving-on-idle.png"></td>
|
51
|
+
</tr>
|
52
|
+
<tr>
|
53
|
+
<td style="vertical-align: middle;">Archiving is stopped</td>
|
54
|
+
<td><img src="img/archiving-off.png"></td>
|
55
|
+
</tr>
|
56
|
+
</tbody>
|
57
|
+
</table>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<script>
|
63
|
+
var sessionId = "<%= session_id %>";
|
64
|
+
var apiKey = "<%= api_key %>";
|
65
|
+
var token = "<%= token %>";
|
66
|
+
</script>
|
67
|
+
<script src="/js/host.js"></script>
|
68
|
+
|
69
|
+
</div>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<div class="container bump-me">
|
2
|
+
|
3
|
+
|
4
|
+
<div class="body-content">
|
5
|
+
|
6
|
+
|
7
|
+
<div class="row">
|
8
|
+
<div class="col-lg-6 col-offset-1">
|
9
|
+
|
10
|
+
<div class="panel panel-default">
|
11
|
+
<div class="panel-heading">Create an archive</div>
|
12
|
+
<div class="panel-body">
|
13
|
+
<p>
|
14
|
+
Everyone who joins either the Host View or Participant View
|
15
|
+
joins a single OpenTok session. Anyone with the Host View
|
16
|
+
open can click Start Archive or Stop Archive to control
|
17
|
+
recording of the entire session.
|
18
|
+
</p>
|
19
|
+
</div>
|
20
|
+
<div class="panel-footer">
|
21
|
+
<a class="btn btn-danger" href="host">Host View</a>
|
22
|
+
<a class="btn btn-danger" href="participant">Participant View</a>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
</div>
|
27
|
+
<div class="col-lg-6 col-offset-1">
|
28
|
+
|
29
|
+
<div class="panel panel-default">
|
30
|
+
<div class="panel-heading">Play an archive</div>
|
31
|
+
<div class="panel-body">
|
32
|
+
<p>
|
33
|
+
Click through to Past Archives to see examples of using the
|
34
|
+
Archiving REST API to list archives showing status (started,
|
35
|
+
stopped, available) and playback (for available archives).
|
36
|
+
</p>
|
37
|
+
</div>
|
38
|
+
<div class="panel-footer">
|
39
|
+
<a class="btn btn-success" href="history">Past Archives</a>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
|
46
|
+
</div>
|
47
|
+
|
48
|
+
</div>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
6
|
+
<title>Archiving Sample</title>
|
7
|
+
<meta name="description" content="">
|
8
|
+
<meta name="viewport" content="width=device-width">
|
9
|
+
|
10
|
+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css">
|
11
|
+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap-theme.min.css">
|
12
|
+
<link rel="stylesheet" href="css/sample.css">
|
13
|
+
|
14
|
+
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
15
|
+
</head>
|
16
|
+
<body>
|
17
|
+
|
18
|
+
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
19
|
+
<!-- Brand and toggle get grouped for better mobile display -->
|
20
|
+
<div class="navbar-header">
|
21
|
+
<a class="navbar-brand" href="./">Archiving Sample App</a>
|
22
|
+
</div>
|
23
|
+
</nav>
|
24
|
+
|
25
|
+
<%= yield %>
|
26
|
+
|
27
|
+
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/js/bootstrap.min.js"></script>
|
28
|
+
</body>
|
29
|
+
</html>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<script src="//static.opentok.com/webrtc/v2.2/js/opentok.min.js"></script>
|
2
|
+
|
3
|
+
<div class="container bump-me">
|
4
|
+
|
5
|
+
<div class="body-content">
|
6
|
+
|
7
|
+
<div class="panel panel-default">
|
8
|
+
<div class="panel-heading">
|
9
|
+
<h3 class="panel-title">Participant</h3>
|
10
|
+
</div>
|
11
|
+
<div class="panel-body">
|
12
|
+
<div id="subscribers"><div id="publisher"></div></div>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div class="panel panel-default">
|
18
|
+
<div class="panel-heading">
|
19
|
+
<h3 class="panel-title">Instructions</h3>
|
20
|
+
</div>
|
21
|
+
<div class="panel-body">
|
22
|
+
<table class="table">
|
23
|
+
<thead>
|
24
|
+
<tr>
|
25
|
+
<th>When</th>
|
26
|
+
<th>You will see</th>
|
27
|
+
</tr>
|
28
|
+
</thead>
|
29
|
+
<tbody>
|
30
|
+
<tr>
|
31
|
+
<td style="vertical-align: middle;">Archiving is started</td>
|
32
|
+
<td><img src="img/archiving-on-message.png"></td>
|
33
|
+
</tr>
|
34
|
+
<tr>
|
35
|
+
<td style="vertical-align: middle;">Archiving remains on</td>
|
36
|
+
<td><img src="img/archiving-on-idle.png"></td>
|
37
|
+
</tr>
|
38
|
+
<tr>
|
39
|
+
<td style="vertical-align: middle;">Archiving is stopped</td>
|
40
|
+
<td><img src="img/archiving-off.png"></td>
|
41
|
+
</tr>
|
42
|
+
</tbody>
|
43
|
+
</table>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
|
48
|
+
<script>
|
49
|
+
var sessionId = "<%= session_id %>";
|
50
|
+
var apiKey = "<%= api_key %>";
|
51
|
+
var token = "<%= token %>";
|
52
|
+
</script>
|
53
|
+
<script src="/js/participant.js"></script>
|
54
|
+
|
55
|
+
</div>
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# OpenTok Hello World Ruby
|
2
|
+
|
3
|
+
This is a simple demo app that shows how you can use the OpenTok-Ruby-SDK to create Sessions,
|
4
|
+
generate Tokens with those Sessions, and then pass these values to a JavaScript client that can
|
5
|
+
connect and conduct a group chat.
|
6
|
+
|
7
|
+
## Running the App
|
8
|
+
|
9
|
+
First, download the dependencies using [Bundler](http://bundler.io)
|
10
|
+
|
11
|
+
```
|
12
|
+
$ bundle install
|
13
|
+
```
|
14
|
+
|
15
|
+
Next, add your own API Key and API Secret to the environment variables. There are a few ways to do
|
16
|
+
this but the simplest would be to do it right in your shell.
|
17
|
+
|
18
|
+
```
|
19
|
+
$ export API_KEY=0000000
|
20
|
+
$ export API_SECRET=abcdef1234567890abcdef01234567890abcdef
|
21
|
+
```
|
22
|
+
|
23
|
+
Finally, start the server using Bundler to handle dependencies
|
24
|
+
|
25
|
+
```
|
26
|
+
$ bundle exec ruby hello_world.rb
|
27
|
+
```
|
28
|
+
|
29
|
+
Visit <http://localhost:9393> in your browser. Open it again in a second window. Smile! You've just
|
30
|
+
set up a group chat.
|
31
|
+
|
32
|
+
## Walkthrough
|
33
|
+
|
34
|
+
This demo application uses the [Sinatra web framework](http://www.sinatrarb.com/). It is similar to
|
35
|
+
many other popular web frameworks, such as [Rails](http://rubyonrails.org/), but more light-weight.
|
36
|
+
We are only covering the very basics of the framework, but you can learn more by following the links
|
37
|
+
above.
|
38
|
+
|
39
|
+
### Main Application (hello_world.rb)
|
40
|
+
|
41
|
+
The first thing done in this file is to require the dependencies we will be using. In this case that
|
42
|
+
is the Sinatra web framework and most importantly the OpenTok SDK. By running the application with
|
43
|
+
the `bundle exec` command, we allow Bundler to select the right versions of these gems from the
|
44
|
+
right place.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
require 'sinatra/base'
|
48
|
+
require 'opentok'
|
49
|
+
```
|
50
|
+
|
51
|
+
Next this file performs some basic checks on the environment. If it cannot find the `API_KEY`and
|
52
|
+
`API_SECRET` environment variables, there is no point in continuing.
|
53
|
+
|
54
|
+
The class `HelloWorld` is our application. The first thing it does is to initialize an instance of
|
55
|
+
OpenTok and also store it using Sinatra's `set` method so it can be accessed in other parts of the
|
56
|
+
application. At the same time, we also `set` the `api_key` separately so that we can access
|
57
|
+
it on its own.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
set :api_key, ENV['API_KEY']
|
61
|
+
set :opentok, OpenTok::OpenTok.new(api_key, ENV['API_SECRET'])
|
62
|
+
```
|
63
|
+
|
64
|
+
Now, lets discuss the Hello World application's functionality. We want to set up a group chat so
|
65
|
+
that any client that visits a page will connect to the same OpenTok Session. Once they are connected
|
66
|
+
they can Publish a Stream and Subscribe to all the other streams in that Session. So we just need
|
67
|
+
one Session object, and it needs to be accessible every time a request is made. The next line of our
|
68
|
+
application simply calls the `OpenTok` instance's `create_session` method and once again uses `set`
|
69
|
+
to store it. Alternatively, `session_id`s are commonly stored in databses for applications that have
|
70
|
+
many of them.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
set :session, opentok.create_session
|
74
|
+
```
|
75
|
+
|
76
|
+
We only need one page, so we create one route handler for any HTTP GET requests to trigger.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
get '\' do
|
80
|
+
# ...
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
Now all we have to do is serve a page with the three values the client will need to connect to the
|
85
|
+
session: `api_key`, `session_id`, and `token`. The first two are right on the `settings` object
|
86
|
+
because we called `set` earlier. Note that the we call the `session_id` method to get just that
|
87
|
+
value from the `session` object. The `token` is generated freshly on this request by calling the
|
88
|
+
`generate_token` method of the `opentok` instance, and passing in the `session_id`. This is because
|
89
|
+
a Token is a piece of information that carries a specific client's permissions in a certain Session.
|
90
|
+
Ideally, as we've done here, you generate a unique token for each client that will connect.
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
api_key = settings.api_key
|
94
|
+
session_id = settings.session.session_id
|
95
|
+
token = settings.opentok.generate_token(session_id)
|
96
|
+
```
|
97
|
+
|
98
|
+
Now all we have to do is serve a page with those three values. Lets call our `erb` helper that will
|
99
|
+
pick up a template called `index.erb` from the `views/` directory in our application and pass in
|
100
|
+
the local variables for it to print using the `:locals` hash.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
erb :index, :locals => {
|
104
|
+
:api_key => api_key,
|
105
|
+
:session_id => session_id,
|
106
|
+
:token => token
|
107
|
+
}
|
108
|
+
```
|
109
|
+
|
110
|
+
### Main Template (views/index.rb)
|
111
|
+
|
112
|
+
This file simply sets up the HTML page for the JavaScript application to run, imports the
|
113
|
+
JavaScript library, and passes the values created by the server into the JavaScript application
|
114
|
+
inside `public/js/helloworld.js`
|
115
|
+
|
116
|
+
### JavaScript Applicaton (public/js/helloworld.js)
|
117
|
+
|
118
|
+
The group chat is mostly implemented in this file. At a high level, we connect to the given
|
119
|
+
Session, publish a stream from our webcam, and listen for new streams from other clients to
|
120
|
+
subscribe to.
|
121
|
+
|
122
|
+
For more details, read the comments in the file or go to the
|
123
|
+
[JavaScript Client Library](http://tokbox.com/opentok/libraries/client/js/) for a full reference.
|