Kiri and


Playing a podcast over the phone

April 10th, 2020 (by Steve)

Coronavirus. An uncomfortable time for all of us, in different ways. But some great things are coming out of the crisis – the incredible sense of community and the way that people are serving others. We’ve tried to do our own little bit and part of that has involved helping to move a lot of our church communications online. Nearly a year ago now, I set up a system in our church to record sermons – pretty simple, a line out from the sound desk into a laptop with a program to record the audio. We then upload it to our church website. Simples! But what about those members of our congregation who don’t have access to a computer?

On 26 March I read a really interesting blog post about how you could use a service called Twilio to allow people to call a phone number and listen to an online audio file. I dropped an email to our vicar to ask whether there was a need for something similar in our church… and the response was positive; over 20 members of our congregation without access to email or the internet.

So, it was worthwhile doing, but I’m lazy and the method cited in the blog post involved changing an audio file every week. I don’t really want to be doing that – plus I don’t want to be a single point of failure in a system. Everything else with regards to our sermons is automated – we upload it once to a custom post type that I’ve created in WordPress, then we use IFTTT to detect when there’s a new sermon and post a link to the sermon to our Facebook and Twitter accounts. Then separately I’ve created an itunes-formatted RSS feed, at which I’ve pointed Apple Podcasts, Stitcher, PlayerFM and Spotify so people can be served the sermons from their favourite podcast platform. So let’s see if we can automate this phone call stuff.

The first thing I do when creating a new thing is to find out whether it actually is a new thing, so I check whether something exists out there already. This was the 27 March… it didn’t, so I got started. Using the blog post as a starting point, I got stuck into familiarising myself with Javascript (the language that the functions needed to be written in), and wrestling with some libraries to help me out. Oh, and there was also the thing of entertaining young children, working from home etc that meant I couldn’t dedicate much time to it. I finally finished on 6 April and it was all working.

And then I found out that someone had already done it and blogged about it on 3 April, with what I think is a neater solution (using the rss-parser library). The Switched On Network method enables you to point to any standalone MP3 file. Nick Holcombe’s method consumes an RSS feed, and gives you a menu of sermons to select from. My method is somewhere in the middle.

So, here’s my code in case anyone wants to see my alternative way (follow the instructions in the other blog posts to get Twilio up and running… the only extra bit you’ll need for mine is to add an npm dependency on the node-fetch library – version 2.6.0).

url = "";

const fetch = require('node-fetch');
const DOMParser = require('xmldom').DOMParser;

exports.handler = function(context, event, callback) {
	// create the voice response object
	let twiml = new Twilio.twiml.VoiceResponse();
    // load the first item from the RSS feed (
    function(response) {
      if (response.status !== 200) {
        console.log('Looks like there was a problem. Status Code: ' +
        // end the call and hang up
	    callback(null, twiml);

      // Examine the text in the response
      response.text().then(function(data) {
        // create a parser, give it the RSS feed and tell it to parse as XML
        parser = new DOMParser();
        xmlfeed = parser.parseFromString(data,"text/xml");

        // extract the data from within the channel
        const channel = xmlfeed.getElementsByTagName("channel")[0];

        // get the title and description
        podcastTitle = channel.getElementsByTagName("title")[0].textContent;
        podcastDescription = channel.getElementsByTagName("description")[0].textContent;


        // Say the welcome text
        twiml.say('Welcome to ' + podcastTitle);

        // get the first item 
        const podcastItem1 = channel.getElementsByTagName("item")[0];

        itemTitle = podcastItem1.getElementsByTagName("title")[0].textContent;
        itemDescription = podcastItem1.getElementsByTagName("itunes:subtitle")[0].textContent;
        itemDurationTotal = podcastItem1.getElementsByTagName("itunes:duration")[0].textContent;

        // use the double not bitwise operator to round to the minutes
        itemDurationMinutes = ~~(itemDurationTotal / 60);
        // use the modulus to get the seconds 
        itemDurationSeconds = itemDurationTotal % 60;

        itemUrl = podcastItem1.getElementsByTagName("enclosure")[0].getAttribute("url");
        // Introduce the item
        twiml.say('You are about to hear ' +itemTitle);
        twiml.say('This is ' +itemDurationMinutes+ ' minutes and ' +itemDurationSeconds+ ' seconds');
        twiml.say('Please wait while we load the sound file');
        // Play the item;

        // end the call and hang up
	    callback(null, twiml);
  .catch(function(err) {
    console.log('Fetch Error', err);
    // end the call and hang up
	callback(null, twiml);

Before I close, it’s probably worth a brief note on SOP and CORS (no, not SOP and The Corrs… although check them out!). This is all about permissions for scripts to access resources that are stored on other sites. The best description of it that I could find when trying to work out why my code wasn’t working was at

In essence, I needed to make a minor addition to the .htaccess file on the church website; we’re happy to allow GET requests from anywhere, so this is the code I added:

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET"
Header set Access-Control-Allow-Headers "Content-Type"

But hang on, there are other services consuming the RSS feed (Apple Podcasts, Stitcher,, Spotify)… how come these permissions are not needed for the other feeds? My educated guess (although please do correct me) is because this code uses javascript (which is a client-server interaction) whereas the other podcast feed code will be server-server. SOP and CORS only apply for client-server conversations.

If you fancy using my code, it should work for you by just changing the URL to be the URL of your podcast RSS feed. If your podcast is available on ApplePodcasts or Soundcloud and you don’t know your RSS feed URL, then you can use the handy tool to find it.

Am I little irked that I could have saved myself some time an effort if I’d kept on searching to see if anyone had done this? Yes. Am I pleased that I managed to get something working on my own? Yes. Is the code meeting a need? Yes. And actually, that’s the main thing.

Stay safe.

3 Responses

Brilliant Steve. I don’t understand a word of it but will forward it to someone who might. We’re also trying to sort out how to get non- I.T. savvy church members more involved. So, thanks for going public with this.

Thanks – spread the word! I’m happy to help anyone set this up for their church and have separately dropped a note to Twilio to ask if they’d add something like this as a template so it’s even easier for people to set up.

Wow Steve. Impressed. A little on the geeky side for me, though. But the main point I sense is the satisfaction that you had in completing the project. It’s good to have that determination, getting one’s teeth stuck into something and not letting go until it is completed. It’s very rewarding.

Leave a Reply

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.