Skip to content

Commit 1c947e6

Browse files
committed
add archiving sample walkthrough
1 parent 9b888bf commit 1c947e6

File tree

2 files changed

+119
-68
lines changed

2 files changed

+119
-68
lines changed

sample/Archiving/README.md

Lines changed: 117 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
# OpenTok Hello World Python
1+
# OpenTok Archiving Sample for Python
22

3-
This is a simple demo app that shows how you can use the OpenTok-Python-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.
3+
This is a simple demo app that shows how you can use the OpenTok Python SDK to archive (or record)
4+
Sessions, list archives that have been created, download the recordings, and delete the recordings.
65

76
## Running the App
87

@@ -31,99 +30,151 @@ this but the simplest would be to do it right in your shell.
3130
Finally, start the server.
3231

3332
```
34-
(venv)$ python helloworld.py
33+
(venv)$ python archiving.py
3534
```
3635

37-
Visit <http://127.0.0.1:5000/> in your browser. Open it again in a second window. Smile! You've just
36+
Visit <http://localhost:5000/> in your browser. Open it again in a second window. Smile! You've just
3837
set up a group chat.
3938

4039
## Walkthrough
4140

42-
This demo application uses the [Flask web microframework](http://flask.pocoo.org/). It is similar to
43-
many other popular web frameworks. We are only covering the very basics of the framework, but you can
44-
learn more by following the links above.
41+
This demo application uses the same frameworks and libraries as the HelloWorld sample. If you have
42+
not already gotten familiar with the code in that project, consider doing so before continuing.
4543

46-
### Main Application (helloworld.py)
44+
The explanations below are separated by page. Each section will focus on a route handler within the
45+
main application (archiving.py).
4746

48-
The first thing done in this file is to import the dependencies we will be using. In this case that
49-
is the Flask web framework, the os module, and most importantly the OpenTok SDK.
47+
### Creating Archives – Host View
5048

51-
```python
52-
from flask import Flask, render_template
53-
from opentok import OpenTok
54-
import os
55-
```
56-
57-
Next this file performs some basic checks on the environment. If it cannot find the `API_KEY`and
58-
`API_SECRET` environment variables, there is no point in continuing.
49+
Start by visiting the host page at <http://localhost:5000/host> and using the application to record
50+
an archive. Your browser will first ask you to approve permission to use the camera and microphone.
51+
Once you've accepted, your image will appear inside the section titled 'Host'. To start recording
52+
the video stream, press the 'Start Archiving' button. Once archiving has begun the button will turn
53+
green and change to 'Stop Archiving'. You should also see a red blinking indicator that you are
54+
being recorded. Wave and say hello! Stop archiving when you are done.
5955

60-
The object `app` is our application and its initialized by instantiating an object from Flask.
61-
Then we initialize an instance of OpenTok as `opentok`. If this file is run as the main file,
62-
we should start running the app.
56+
Next we will see how the host view is implemented on the server. The route handler for this page is
57+
shown below:
6358

6459
```python
65-
app = Flask(__name__)
66-
opentok = OpenTok(api_key, api_secret)
67-
68-
# ...
69-
70-
if __name__ == "__main__":
71-
app.run()
60+
@app.route("/host")
61+
def host():
62+
key = api_key
63+
session_id = session.session_id
64+
token = opentok.generate_token(session_id)
65+
return render_template('host.html', api_key=key, session_id=session_id, token=token)
7266
```
7367

74-
Now, lets discuss the Hello World application's functionality. We want to set up a group chat so
75-
that any client that visits a page will connect to the same OpenTok Session. Once they are connected
76-
they can Publish a Stream and Subscribe to all the other streams in that Session. So we just need
77-
one Session object, and it needs to be accessible every time a request is made. On the next line we
78-
simply call the `OpenTok` instance's `create_session` method to get a Session and store it in the
79-
`session` variable. Alternatively, `session_id`s are commonly stored in databses for applications
80-
that have many of them.
68+
If you've completed the HelloWorld walkthrough, this should look familiar. This handler simply
69+
generates the three strings that the client (JavaScript) needs to connect to the session: `api_key`,
70+
`session_id` and `token`. After the user has connected to the session, they press the
71+
'Start Archiving' button, which sends an XHR (or Ajax) request to the <http://localhost:5000/start>
72+
URL. The route handler for this URL is shown below:
8173

8274
```python
83-
session = opentok.create_session()
75+
@app.route("/start")
76+
def start():
77+
archive = opentok.start_archive(session.session_id, name="Python Archiving Sample App")
78+
return archive.json()
8479
```
8580

86-
We only need one page, so we create one route handler for any HTTP GET requests to trigger.
81+
In this handler, the `start_archive()` method of the `opentok` instance is called with the `session_id`
82+
for the session that needs to be archived. The optional second argument is `name`, which is stored with
83+
the archive and can be read later. In this case, as in the HelloWorld sample app, there is
84+
only one session created and it is used here and for the participant view. This will trigger the
85+
recording to begin. The response sent back to the client's XHR request will be the JSON
86+
representation of the archive, which is returned from the `json()` method. The client is also
87+
listening for the `archiveStarted` event, and uses that event to change the 'Start Archiving' button
88+
to show 'Stop Archiving' instead. When the user presses the button this time, another XHR request
89+
is sent to the <http://localhost:5000/stop/<archive_id>> URL where `<archive_id>` represents the ID the
90+
client receives in the 'archiveStarted' event. The route handler for this request is shown below:
8791

8892
```python
89-
@app.route("/")
90-
def hello():
91-
# ...
93+
@app.route("/stop/<archive_id>")
94+
def stop(archive_id):
95+
archive = opentok.stop_archive(archive_id)
96+
return archive.json()
9297
```
9398

94-
Now all we have to do is serve a page with the three values the client will need to connect to the
95-
session: `api_key`, `session_id`, and `token`. The `api_key` is available in the outer scope so we
96-
can just assign it. The `session_id` is available as the `session.session_id` attribute. The `token`
97-
is generated freshly on this request by calling the `generate_token` method of the `opentok`
98-
instance, and passing in the `session_id`. This is because a Token is a piece of information that
99-
carries a specific client's permissions in a certain Session. Ideally, as we've done here, you
100-
generate a unique token for each client that will connect.
99+
This handler is very similar to the previous one. Instead of calling the `start_archive()` method,
100+
the `stop_archive()` method is called. This method takes an `archive_id` as its parameter, which
101+
is different for each time a session starts recording. But the client has sent this to the server
102+
as part of the URL, so the `archive_id` argument from the route matcher is used to retrieve it.
103+
104+
Now you have understood the three main routes that are used to create the Host experience of
105+
creating an archive. Much of the functionality is done in the client with JavaScript. That code can
106+
be found in the `public/js/host.js` file. Read about the
107+
[OpenTok.js JavaScript](http://tokbox.com/opentok/libraries/client/js/) library to learn more.
108+
109+
### Past Archives
110+
111+
Start by visiting the history page at <http://localhost:5000/history>. You will see a table that
112+
displays all the archives created with your API Key. If there are more than five, the older ones
113+
can be seen by clicking the "Older →" link. If you click on the name of an archive, your browser
114+
will start downloading the archive file. If you click the "Delete" link in the end of the row
115+
for any archive, that archive will be deleted and no longer available. Some basic information like
116+
when the archive was created, how long it is, and its status is also shown. You should see the
117+
archives you created in the previous sections here.
118+
119+
We begin to see how this page is created by looking at the route handler for this URL:
101120

102121
```python
103-
key = api_key
104-
session_id = session.session_id
105-
token = opentok.generate_token(session_id)
122+
@app.route("/history")
123+
def history():
124+
page = int(request.args.get('page', '1'))
125+
offset = (page - 1) * 5
126+
archives = opentok.get_archives(offset=offset, count=5)
127+
128+
show_previous = '/history?page=' + str(page-1) if page > 1 else None
129+
show_next = '/history?page=' + str(page+1) if archives.count > (offset + 5) else None
130+
131+
return render_template('history.html', archives=archives, show_previous=show_previous,
132+
show_next=show_next)
106133
```
107134

108-
Now all we have to do is serve a page with those three values. Lets call our `render_template`
109-
helper that will pick up a template called `index.html` from the `templates/` directory in our
110-
application and pass in the variables for it to include on the page.
135+
This view is paginated so that we don't potentially show hundreds of rows on the table, which would
136+
be difficult for the user to navigate. So this code starts by figuring out which page needs to be
137+
shown, where each page is a set of 5 archives. The `page` number is read from the request's query
138+
string parameters as a string (defaulting to 1 if its not present) and then casted into an `int`.
139+
The `offset`, which represents how many archives are being skipped is always calculated as five
140+
times as many pages that are less than the current page, which is `(page - 1) * 5`. Now there is
141+
enough information to ask for a list of archives from OpenTok, which we do by calling the
142+
`get_archives()` method of the `opentok` instance. This method optionally takes the offset and count
143+
that was just calculated. If we are not at the first page, we can pass the view a string that
144+
contains the relative URL for the previous page. Similarly, we can also include one for the next
145+
page. Now the application renders the view using that information and the partial list of archives.
146+
147+
At this point the template file `templates/history.html` handles
148+
looping over the array of archives and outputting the proper information for each column in the
149+
table. It also places a link to the download and delete routes around the archive's name and
150+
its delete button, respectively.
151+
152+
The code for the download route handler is shown below:
111153

112154
```python
113-
return render_template('index.html', api_key=key, session_id=session_id, token=token)
155+
@app.route("/download/<archive_id>")
156+
def download(archive_id):
157+
archive = opentok.get_archive(archive_id)
158+
return redirect(archive.url)
114159
```
115160

116-
### Main Template (templates/index.html)
161+
The download URL for an archive is available as a property of an `Archive` instance. In order to get
162+
an instance to this archive, the `get_archive()` method of the `opentok` instance is used. The only
163+
parameter it needs is the `archive_id`. We use the same technique as above to read that `archive_id`
164+
from the URL. Lastly, we send a redirect response back to the browser so the download begins.
117165

118-
This file simply sets up the HTML page for the JavaScript application to run, imports the
119-
JavaScript library, and passes the values created by the server into the JavaScript application
120-
inside `public/js/helloworld.js`
166+
The code for the delete route handler is shown below:
121167

122-
### JavaScript Applicaton (static/js/helloworld.js)
168+
```python
169+
@app.route("/delete/<archive_id>")
170+
def delete(archive_id):
171+
opentok.delete_archive(archive_id)
172+
return redirect(url_for('history'))
173+
```
123174

124-
The group chat is mostly implemented in this file. At a high level, we connect to the given
125-
Session, publish a stream from our webcam, and listen for new streams from other clients to
126-
subscribe to.
175+
Once again the `archive_id` is retrieved from the URL of the request. This value is then passed the
176+
`delete_archive()` method of the `opentok` instance. Now that the archive has been deleted, a
177+
redirect response back to the first page of the history is sent back to the browser.
127178

128-
For more details, read the comments in the file or go to the
129-
[JavaScript Client Library](http://tokbox.com/opentok/libraries/client/js/) for a full reference.
179+
That completes the walkthrough for this Archiving sample application. Feel free to continue to use
180+
this application to browse the archives created for your API Key.

sample/HelloWorld/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Finally, start the server.
3434
(venv)$ python helloworld.py
3535
```
3636

37-
Visit <http://127.0.0.1:5000/> in your browser. Open it again in a second window. Smile! You've just
37+
Visit <http://localhost:5000/> in your browser. Open it again in a second window. Smile! You've just
3838
set up a group chat.
3939

4040
## Walkthrough
@@ -58,7 +58,7 @@ Next this file performs some basic checks on the environment. If it cannot find
5858
`API_SECRET` environment variables, there is no point in continuing.
5959

6060
The object `app` is our application and its initialized by instantiating an object from Flask.
61-
Then we initialize an instance of OpenTok as `opentok`. If this file is run as the main file,
61+
Then we initialize an instance of OpenTok as `opentok`. If this file is run as the main file,
6262
we should start running the app.
6363

6464
```python

0 commit comments

Comments
 (0)