Adding Life to your Chatbot

Ben James

January 05th, 2017

In the previous post we looked at getting your new bot off the ground with the SuperScript package. Today, we'll take this a step further and write your own personal assistant to find music videos, complete with its own voice using IVONA's text-to-speech platform.

Giving your bot a voice

To get started with IVONA, visit here and go to Speech Cloud > Sign Up. After a quick sign-up process, you'll be pointed to your dashboard, where you'll be able to get the API key needed to use their services. Go ahead and do so, and ensure you download the key file, as we'll need it later.

We'll need to add a couple more packages to your SuperScript bot to integrate IVONA into it, so run the following:

npm install --save ivona-node
npm install --save play-sound

ivona-node is a library for easily interfacing with the IVONA API without having to set things like custom headers yourself, while play-sound will let you play sound directly from your terminal, so you can hear what your bot says without having to locate the mp3 file and play it yourself!

Now we need to write some code to get these two things working together. Open up src/server.js in your SuperScript directory, and at the top, add:

import Ivona from 'ivona-node';
import Player from 'play-sound';
import fs from 'fs';

We'll need fs to be able to write the voice files to our system. Now, find your IVONA access and secret keys, and set up a new IVONA instance by adding the following:

const ivona = new Ivona({
  accessKey: 'YOUR_ACCESS_KEY',
  secretKey: 'YOUR_SECRET_KEY',
});

We also need to create an instance of the player:

const player = Player();

Great! We can double-check that we can access the IVONA servers by asking for a full list of voices that IVONA provides.

ivona.listVoices()
  .on('complete', (voices) => {
    console.log(voices);
  });

These are available to sample on the IVONA home page, so if you haven't already, go and check it out. And find one you like!

Now it's time for the magic to happen. Inside the bot.reply callback, we need to ask IVONA to turn our bot response into a speech before outputting it in our terminal. We can do that in just a few lines:

bot.reply(..., (err, reply) => {
  // ... Other code to output text to the terminal
  //
  const stream = fs.createWriteStream('text.mp3');

  ivona.createVoice(reply.string, {
    body: {
      voice: {
        name: 'Justin',
        language: 'en-US',
        gender: 'Male',
      },
    },
  }).pipe(stream);

  stream.on('finish', () => {
    player.play('text.mp3', (err) => {
      if (err) {
        console.error(err);
      }
    });
  });
});

Run your bot again by running npm run start, and watch the magic unfurl as your bot speaks to you!

Getting your bot to do your bidding

Now that your bot has a human-like voice, it's time to get it to do something useful for you. After all, you are its master.

We're going to write a simple script to find music videos for you. So let's open up chat/main.ss and add an additional trigger:

+ find a music video for (*) by (*)
- Okay, here's your music video for <cap1> by <cap2>. ^findMusicVideo(<cap1>, <cap2>)

Here, whenever we ask the bot for a music video, we just go off to our function findMusicVideo that finds a relevant video on YouTube. We'll write that SuperScript plugin now. First, we'll need to install the request library to make HTTP requests to YouTube.

npm install --save request

You'll also need to get a Google API key to search YouTube and get back some results in JSON form. To do this, you can go to here and follow the instructions to get a new key for the 'YouTube Data API'.

Then, inside plugins/musicVideo.js, we can write:

import request from 'request';

const YOUTUBE_API_BASE = 'https://www.googleapis.com/youtube/v3/search';
const GOOGLE_API_KEY = 'YOUR_KEY_HERE';

const findMusicVideo = function findMusicVideo(song, artist, callback) {
  request({
    url: YOUTUBE_API_BASE,
    qs: {
      part: 'snippet',
      key: GOOGLE_API_KEY,
      q: `${song} ${artist}`,
    },
  }, (error, response, body) => {
    if (!error && response.statusCode === 200) {
      try {
        const parsedJSON = JSON.parse(body);
        if (parsedJSON.items[0]) {
          return callback(`https://youtu.be/${parsedJSON.items[0].id.videoId}`);
        }
      } catch (err) {
        console.error(err);
      }
      return callback('');
    }
    return callback('');
  });
};

All we're doing here is making a request to the YouTube API for the relevant song and artist. We then take the first one that YouTube found, and stick it in a nice link to give back to the user.

Now, parse and run your bot again, and you'll see that not only does your bot talk to you with a voice, but now you can ask it to find a YouTube video for you.

About the author

Ben is currently the technical director at To Play For, creating games, interactive stories and narratives using artificial intelligence. Follow him at @ToPlayFor.

comments powered by Disqus