martastain

nxtools based podcast downloader

Feb 15th, 2019 (edited)
623
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.77 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. """
  4.  
  5. podcast.py is a very simple podcast downloader which can used with cron.
  6. It takes only one positional argument (path to a json configuration file)
  7.  
  8. Structure of this file follows:
  9.  
  10. {
  11.    "save_dir" : "~/Music/Podcasts",
  12.    "feeds" : [
  13.        {
  14.        "title" : "Demuxed",
  15.        "url" : "https://www.heavybit.com/category/library/podcasts/demuxed/feed/"
  16.        },
  17.        {
  18.        "title" : "Marvin suicide",
  19.        "url" : "http://feeds.feedburner.com/marvinsuicidefeedburner?format=xml"
  20.        }
  21.    ]
  22. }
  23.  
  24. Podcasts are downloaded and converted using ffmpeg to specified "save_dir" as
  25.  
  26. {podcast_name}/{episode name}.mp3
  27.  
  28. all names are slugified. eg. specials characters are stripped,
  29. spaces replaced with dashes etc...
  30.  
  31. Script also sets MP3 metadata (see the code)
  32.  
  33. """
  34.  
  35. import os
  36. import sys
  37. import json
  38. import requests
  39.  
  40. from nxtools import *
  41. from nxtools.media import *
  42.  
  43. config = {}
  44.  
  45.  
  46. if len(sys.argv) == 2:
  47.     config_path = sys.argv[-1]
  48. else:
  49.     config_path = os.path.abspath(os.path.expanduser("~/.private/special/podcasts.json"))
  50.  
  51. if not os.path.exists(config_path):
  52.     critical_error("Config path does not exist")
  53.  
  54. try:
  55.     config = json.load(open(config_path))
  56. except Exception:
  57.     log_traceback()
  58.     critical_error("Unable to open config file")
  59.  
  60.  
  61. def get_feed(**kwargs):
  62.     title = kwargs.get("title")
  63.     url = kwargs.get("url")
  64.     if not (url and title):
  65.         logging.error("Title and url must be specified in feed config")
  66.         return False
  67.  
  68.     try:
  69.         feed_data = requests.get(url)
  70.         feed = xml(feed_data.text)
  71.         channel = feed.find("channel")
  72.     except Exception:
  73.         return
  74.  
  75.     for item in channel.findall("item"):
  76.         try:
  77.             ititle = item.find("title").text
  78.             iurl = item.find("enclosure").attrib["url"]
  79.         except Exception:
  80.             return
  81.  
  82.         tpath = FileObject(
  83.                     os.path.expanduser(config["save_dir"]),
  84.                     slugify(title),
  85.                     slugify(ititle) + ".mp3"
  86.                 )
  87.         if tpath.exists:
  88.             return
  89.  
  90.         if not os.path.isdir(tpath.dir_name):
  91.             os.makedirs(tpath.dir_name)
  92.  
  93.         res = ffmpeg( "-y",
  94.                 "-i", iurl,
  95.                 "-vn", "-c:a", "libmp3lame", "-b:a", "128k",
  96.                 "-map_metadata", "-1",
  97.                 "-metadata", "title={}".format(ititle),
  98.                 "-metadata", "album={}".format(title),
  99.                 "-metadata", "artist=_Podcasts_",
  100.                 tpath
  101.             )
  102.  
  103.         if not res:
  104.             if tpath.exists:
  105.                 os.remove(tpath.path)
  106.  
  107.  
  108. if __name__ == "__main__":
  109.     for feedconfig in config.get("feeds", []):
  110.         get_feed(**feedconfig)
Advertisement
Add Comment
Please, Sign In to add comment