Building A Twilio Powered Star Trek Communicator

February 11, 2014
Written by

StarTrekCommunicator

As a casual fan of the Star Trek series I tread lightly when discussing The Show or anything orbiting anywhere near The Show (see: fantasy nerd). It is not the wrath of the trekkie I fear, but rather getting trapped in a debate I am wholly unqualified to participate in. Don’t misunderstand me, as a child I loved TNG. My grandparents had a grove of avocado trees and I can remember building spaceships in the trees, commanding the star fleet that was my sister, my aunt and myself as we rescued whales and saved distressed planets from extinction. So if you love the show so much you built a life-sized replica of the Enterprise bridge in your garage, just rest assured all of my errors and newb-like terms come from a place of love.

A few weeks ago I heard a podcast episode about the influence of TV & Movies on the interfaces that surround us. It was a fascinating discussion with the authors of “Make It So: Interaction Design Lessons From Science Fiction”. What I remember most from this interview was a discussion about The Star Trek Communicator and how it affected the invention of mobile phones. It turns out that Dr. Martin Cooper, inventor of the first handheld mobile phone, designed the first prototype of the “flip phone” so that it more closely resembled the Star Trek Communicator.

I wanted to follow in Dr. Cooper’s footsteps and see if I could quickly build an in-browser version of The Communicator using Twilio Client. Why Client? Well I wanted to easily initiate a Twilio voice call in the browser without the use of any actual phone device. Plus there are a few added bonuses to using this method. First, I didn’t have to buy a Twilio Phone number since Client can simply point to a Twilio application when looking for Voice and Messaging URLs. Secondly I don’t need to manage a database since I can simply store my recordings in my Twilio account (free up to 10k minutes) and access them later via the REST API.

It just seemed too poetic to pass up, not to mention extremely simple. Here is how I did it.

Check out the Live Demo here

Twilio Recipe

TwiML: Record TwiML: Say Twilio PHP jQuery Twilio Client: TwilioJS

The Goal

A starship Captain visits a web page with a button labelled ‘Record’ and a series of lights indicating the status of the recording. When the captain clicks the button the red light will glow and she will hear instructions to leave a captain’s log after the beep. The recording will begin and the captain can talk until she clicks a ‘Stop’ button or the recording will timeout after 15 seconds. After the recording is complete, the captain’s log will be played back. The recordings will then be displayed on a separate page through the Twilio REST API.

Github Repo: jarodreyes/star-trek-twilio

Creative Assets: communicator – ai communicator – eps space.gif – psd

Checklist

  1. Create a Twilio Application
  2. Generate a Twilio Capability Token with outgoing permissions
  3. Write javascript to set up a Twilio.Device and HTML to initiate a connection
  4. Write TwiML instructions that prompt a Captain to record his log.
  5. Point our Twilio Application to the url of our TwiML instructions.
  6. Write HTML that displays the recordings from our account via Twilio Rest API.

Create A TwiML Application

A TwiML Application is just a named collection of URLs responsible for returning TwiML instructions to control phone calls and SMS.

Creating an app on Twilio is pretty simple. Log in to your account on Twilio.com and you’ll find TwiML apps underneath Dev Tools. Create a new App and name it whatever you want.

Creatinganapp.format-webp

Generate A Capability Token in PHP

In order to communicate with Twilio services without using a Twilio phone number we need to generate a Capability Token. You can think of Capability Tokens as temporary auth tokens for your application. Fortunately generating tokens is pretty easy when using a helper library.

In order to create your token you’ll need your Twilio account_sid and auth_token. You can find both of these on your Account Dashboard. While you’re there you should hop over a couple of tabs in your Twilio account and grab the SID of the Twilio Application we created in the last step.

Now you should be ready to create captains-log.php:

<!--?php include '../twilio-php-library/Services/Twilio/Capability.php'; $accountSid = $_ENV["TWILIO_ACCOUNT_SID"]; $authToken = $_ENV["TWILIO_AUTH_TOKEN"]; $token = new Services_Twilio_Capability($accountSid, $authToken); $token--->allowClientOutgoing($_ENV['CAPTAINS_LOG_SID']);
$deviceToken = $token->generateToken(); 
?>

With this snippet we created a Capability token using the helper object new Services_Twilio_Capability(). Lastly we enabled our Client token to allow outbound calls to our ‘Captains Log’ Application.

Add A Button And Some Javascript

Next we need to add some HTML and Javascript to this file we’re building. First we need a button the user can click to start recording.

<a class="record-btn btn" title="Record" href="#">Record</a>

Next we need some Javascript to fire off the call. Because I want to do some fun transitions later I am going to use jQuery for its convenience.

$(document).ready(function() {
        Twilio.Device.setup("<!--?php echo $deviceToken?-->",{"debug":true});
  $(".record-btn").click(function() {
    Twilio.Device.connect();
  });
  $(".hangup-btn").click(function(e) {
      connection.sendDigits("#");
  });
});

These 10 lines of code are the meat of the application. In order to make the communicator look right and change state we need to add a little front-end code, but not much. The entire file looks like so.

Write The TwiML Instructions

When the Client call is initiated it makes a request to the Voice URL specified in our Captain’s Log Application. That URL will return TwiML that will some instructions the audio and assign an action that will contain the TwiML that will playback the recording.
Record-twiML.php

<?php  
header("Content-type: text/xml");
echo "<?xml version='1.0' encoding='ISO-8859-1'?>";
?>
<Response>
    <Say>
        Record your captain's log after the beep. 
    </Say>
    <Record
        action="recording-goodbye.php"
        method="GET"
        finishOnKey="#"
        maxLength="15"
        />
    <Say>I did not hear a recording.  Goodbye.</Say>
</Response>

Point the Application to the TwiML

Once you’ve hosted your TwiML file (heroku, ngrok, etc) just add the url to the Voice field in the app dashboard.

CaptiansLog2.format-webp

Display Captain’s Logs

The last step to our Captain’s Log hack is to display a list of all of the recorded logs. Of course Twilio makes this extremely simple.

Whenever you use the verb Twilio automatically saves a Recording of that call to your account. So in order to display all of the Logs we simply need to look up all of the recordings for this account. Here is what that would look like in its simplest form:

// Instantiate a new Twilio Rest Client 
  $client = new Services_Twilio($accountSid, $authToken);
  foreach($client->account->recordings as $recording) { // do something with $recording };

show_logs.php (expanded)

<!DOCTYPE HTML>
<html>
  <head>
    <title>
      My recordings
    </title>
    <link rel='stylesheet' href='css/main.css' />
    <link href='img/favicon.png' rel='shortcut icon'>
  </head>
    <body>
      <div class="trekky"></div>
      <img class="hero-type" src="img/captains-type.png" />
      <div class="recordings">
        <?php
          // Include the PHP TwilioRest library 
          include 'helper/twilio-php-library/Services/Twilio.php';

          // Twilio REST API version 
          $ApiVersion = "2010-04-01";

          // Set our AccountSid and AuthToken 
          $accountSid = $_ENV["TWILIO_ACCOUNT_SID"];
          $authToken  = $_ENV["TWILIO_AUTH_TOKEN"];

          // @start snippet
          // Instantiate a new Twilio Rest Client 
          $client = new Services_Twilio($accountSid, $authToken);
          // Display each Log 
          foreach($client->account->recordings as $recording) {
              echo "<div class='log'><i>Captains Log: {$recording->date_created}</i>";
              echo "<p><audio src=\"https://api.twilio.com/2010-04-01/Accounts/$accountSid/Recordings/{$recording->sid}.mp3\" controls preload=\"auto\" autobuffer></audio></p></div>";

          }
          echo ("<table>");
          // @end snippet
        ?>
      </div>
  </body>
</html>