Daniel Doubrovkine bio photo

Daniel Doubrovkine

aka dB., @awscloud, former CTO @artsy, +@vestris, NYC

Email Twitter LinkedIn Github Strava
Creative Commons License

If you’ve never listened to the Artsy podcast, I highly recommend it. Available on iTunes and Soundcloud and now on your Amazon Echo.

First, enable Artsy, then ask artsy to play the latest podcast or ask Artsy for a summary of the latest podcast. The code uses the audio player functionality introduced in alexa-app 2.4.0 and is artsy/elderfield#56.

The Artsy editorial team uploads the podcast to SoundCloud, which exposes an RSS feed that is used to publish to iTunes. YMMV wrt how you generate an RSS feed - when I was new to podcasting with Pod5, I had settled on a Jekyll-based system.

The intent retrieves the podcast, extracts the MP3 URL and calls audioPlayerPlayStream.

app.intent('PodcastIntent', {},
    "utterances": [
      "to play the latest podcast"
    ]
  },
  function(req, res) {
    // retrieve the podcast Mpeg enclosure from the RSS feed
    var podcastStream = ...;
    return podcastStream.then(function(audioMpegEnclosure) {
      // SSL required by Amazon, available on SoundCloud
      var streamUrl = audioMpegEnclosure.url.replace('https://', 'https://');
      var stream = {
        url: streamUrl,
        token: streamUrl,
        offsetInMilliseconds: 0
      }
      res.audioPlayerPlayStream('REPLACE_ALL', stream);
      res.send();
    });
  }
);

Note that we set the value of token to the MP3 stream URL. This is supposed to be a unique opaque identifier, but the URL works well and allows to pause the playback with audioPlayerStop and resume the podcast with audioPlayerPlayStream without having to lookup the MP3 location.

app.intent('AMAZON.PauseIntent', {},
  function(req, res) {
    console.log('app.AMAZON.PauseIntent');
    res.audioPlayerStop();
    res.send();
  }
);

app.intent('AMAZON.ResumeIntent', {},
  function(req, res) {
    console.log('app.AMAZON.ResumeIntent');
    if (req.context.AudioPlayer.offsetInMilliseconds > 0 &&
      req.context.AudioPlayer.playerActivity === 'STOPPED') {
        res.audioPlayerPlayStream('REPLACE_ALL', {
          // hack: use token to remember the URL of the stream
          token: req.context.AudioPlayer.token,
          url: req.context.AudioPlayer.token,
          offsetInMilliseconds: req.context.AudioPlayer.offsetInMilliseconds
      });
    }
    res.send();
  }
);

There’s not much more to it.