Podcast generator

This projects allows you to turn a bunch of mp3s into an RSS feed formatted for the iPhone podcast app (it should work with any podcast app).

The steps are:

  1. Create a directory on your webserver for example (/var/www/html/mypodcasts/)
  2. Create the PHP file below in your mypodcasts directory
  3. Create an .htaccess file with the following contents:
RewriteEngine On
RewriteRule (.*)\.rss mp3-to-rss.php?dirname=$1 [L]

Now, for each album/collection you want to access:

  1. Create a directory of mp3s there (ie. /var/www/html/mypodcasts/themartian/)
  2. Create a metadata JSON file called info.json in the mp3 directory (/var/www/html/mypodcasts/themartian/info.json), here is an example:
{"author":"Andy Weir", "title":"The Martian"}

You can now view the generated RSS feed by visiting:

http://your_domain_name/mypodcasts/themartian.rss

mp3-to-rss.php

<?php
// url that the mp3s will be accessed at (by the podcast client)
$url = "http://yourdomain.com/mypodcasts/";
// path the mp3 directories are stored under
$mp3_dir = "/var/www/html/mypodcasts/";
 
/* Each mp3 directory must have an 'info.json' file in the format:
 
   {"author":"Peter F Hamilton","title":"The Great North Road"}
 
   You can add the following optional fields:
   summary, owner, owneremail, subtitle, description, image_file
 
   If image.jpg exists in the directory, that will be used
   as the podcast thumbnail (it can be overriden with
   image_file above)
 
 
*/
if(empty($_REQUEST['dirname']))
   die("Missing mp3 directory");
 
$dir_name = basename($_REQUEST['dirname']);
 
if(preg_match('/[^a-z_\-0-9]/i', $dir_name))
   die("Invalid directory");
 
if(!empty($dir_name) and is_dir($mp3_dir.$dir_name)) {
 
   $path = $mp3_dir.$dir_name."/";
   $meta_file = $path."info.json";
   $files = glob($path."*.mp3");
 
   if(!file_exists($meta_file))
   die("Missing info.json");
 
   header("Content-Type: application/rss+xml; charset=utf-8");
 
   $json = json_decode(file_get_contents($meta_file), true);
   $author = $json['author'];
   $replace_array['#AUTHOR#'] = $replace_array['#OWNER#'] = $replace_array['#OWNEREMAIL#'] = $json['author'];
   $replace_array['#TITLE#'] = $json['title'];
   $replace_array['#SUMMARY#'] = $replace_array['#DESCRIPTION#'] = $json['title']." by ".$json['author'];
   if(isset($json['summary']))
      $replace_array['#SUMMARY#'] = $json['summary'];
   $replace_array['#LINK#'] = $url.$dir_name;
   $replace_array['#IMAGE_URL#'] = $url.$dir_name."/image.jpg";
   if(isset($json['image_file']))
      $replace_array['#IMAGE_URL#'] = $url.$dir_name."/".$json['image_file'];
   $replace_array['#SUBTITLE#'] = "";
   if(isset($json['subtitle']))
      $replace_array['#SUBTITLE#'] = $json['subtitle'];
   if(isset($json['description']))
      $replace_array['#DESCRIPTION#'] = $json['description'];
   if(isset($json['owner']))
      $replace_array['#OWNER#'] = $json['owner'];
   if(isset($json['owneremail']))
      $replace_array['#OWNEREMAIL#'] = $json['owneremail'];
 
   $number = 1;
   $all_items = "";
   foreach($files as $file) {
      $size = filesize($file);
      $filename = basename($file);
   $all_items .= "
<item>
    <title>$filename</title>
    <itunes:summary>$filename</itunes:summary>
    <description>$filename</description>
    <link>$url/$dir_name/$filename</link>
    <enclosure url=\"$url/$dir_name/$filename\" type=\"audio/mpeg\" length=\"$size\"></enclosure>";
$all_items .= "<pubDate>".date("r", strtotime("1 June 2018 21:00 +$number days"))."</pubDate>";
$all_items .= "
    <itunes:author>$author</itunes:author>
    <itunes:duration>00:32:16</itunes:duration>
    <itunes:explicit>no</itunes:explicit>
    <guid>$url$dir_name/$filename</guid>
</item>";
 
      $number++;
   }
 
 
} else {
   http_response_code(404);
   die("File not found");
}
 
 
function header_update($buffer) {
   global $replace_array;
   return(str_replace(array_keys($replace_array), $replace_array, $buffer));
}
 
ob_start("header_update");
?>
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
<channel>
<title>#TITLE#</title>
<link>#LINK#</link>
<language>en-us</language>
<itunes:subtitle>#SUBTITLE#</itunes:subtitle>
<itunes:author>#AUTHOR#</itunes:author>
<itunes:summary>#SUMMARY#</itunes:summary>
<description>#DESCRIPTION#</description>
<itunes:owner>
    <itunes:name>#OWNER#</itunes:name>
    <itunes:email>#OWNEREMAIL#</itunes:email>
</itunes:owner>
<itunes:explicit>no</itunes:explicit>
<itunes:image href="#IMAGE_URL#" />
<itunes:category text="Arts">
     <itunes:category text="Literature"/>
</itunes:category>
<?php
 
ob_end_flush();
 
echo $all_items;
?>
 
</channel>
</rss>

The lengths/duration above are just set to 32 minutes (this will be auto-updated by your client when you start to play the file). You can set these automatically if you have access to the mp3info program (apt install mp3info) then replace the duration (00:32:16 with $duration) and add this code around line 61, just after the $size variable is set:

$duration = gmdate("H:i:s", `mp3info -p "%S" "$file"`);