Kodi / XBMC / uTorrent / EventGhost / TheRenamer: Automatically renaming downloads for Kodi consumption

0 Comments

Kodi expects your files to be organised in a certain way if you want it to be displayed correctly. This isn't a big ask, but most people are incapable or lazy, so it'd be nice if it could be done automatically.

At the moment this handles movies and TV shows just fine, but anime renaming is a whole different can of worms needs a little more work.

This method relies on a particular setup, but your setup is similar then it'll work for you. If your setup is similar, then you can easily adapt it.

update 10/01/2016: Made the process work better with anime.

Basic process

  • When files are added to uTorrent, categorise them with a label (movie, TV show, anime, etc)
  • uTorrent completes a download and moves it your "completed" folder but also appends the label. (eg. C:\Downloads\Movies\)
  • EventGhost monitors the labelled folders for media files and copies them off to a temporary folder (so you can continue seeding)
  • When the file has finished copying to the temporary folder, EventGhost will start TheRenamer to rename and move the files to it's final resting place
  • Next time Kodi starts, it'll scan and detect the new files

For the time being, anime is copied to a temporary folder but no renaming is done.

Downloads

Setting up your computer

You'll need 3 sets of folders, one for completed downloads and one for temporary downloads.

For example:

  • C:\Downloads\Movies
  • C:\Downloads\TV Shows
  • C:\Downloads\Anime
  • C:\XBMC-prepare\Movies
  • C:\XBMC-prepare\TV Shows
  • C:\XBMC-prepare\Anime
  • C:\XBMC\Movies
  • C:\XBMC\TV Shows
  • C:\XBMC\Anime

Ensure these are ready before continuing.

Setting up uTorrent

  • Options > Preferences
  • Under "Directories", ensure that you set the "Move completed downloads to:" to a specific folder
image4
  • On older uTorrent clients, you'll have to check "Append the torrent's label to the directory name" as well
  • (optional) Under Advanced > UI Extras, fill in the persistent labels "Anime|Movies|TV Shows" so you don't run into inconsistent label names

uTorrent and Anime

The difference with anime is that it's a pain in the butt to get working because of the naming convention compared to TV Shows.

  • Set up the filename scanner as shown http://kodi.wiki/view/Anime#Scanning_files_without_renaming_them here by pasting the snippet into advancedsettings.xml.
  • In uTorrent, name your labels as "Anime\One-Punch Man" and such so that the name matches the name you want to match in the scraper (anidb or thetvdb)
  • That should be enough to get you by. Specials and movies will probably require a change of scraper or involve manual renaming.

If your anime (one off movie) doesn't belong in a folder, then you can simply label it as "Anime" and the script will still work.

Setting up EventGhost

image14

To the right is an image of the setup you should replicate in EventGhost.

Preparation

  • Click "Add plugin" in the toolbar
  • Select Other > Directory Watcher
  • Select the folder "C:\Downloads\TV Shows" and tick "Watch subdirectories too"
  • Do this again for Movies and Anime
  • Now under Autostart, you should have "Plugin: Directory Watcher" "Autostart" #2 and #3 (note this for naming for events)
  • Select "Configuration Tree" at the top
  • Click the "Add macro..." button in the toolbar
  • Select "Event Ghost > Python Script"
  • Paste in the following content:
import shutil
import os
import subprocess
import re
ALLOWED_TYPES = ['avi', 'mkv', 'mov', 'mp4']
PREPARE_FOLDER = r"D:\XBMC-prepare\%s" % eg.globals.mediaType
CLEANSED_FOLDER = r"D:\XBMC\%s" % eg.globals.mediaType
THE_RENAMER = r"C:\\Program Files (x86)\\theRenamer\\theRenamer.exe"
MOVIE_MINIMUM_FILESIZE = 25 * 1024 * 1024 # 25mb
"""
No editing below this line unless you know what you're doing.
v1.4 15/11/2016
- Added MOVIE_MINIMUM_FILESIZE to prevent samples from being copied
- Update anime so it adds CRC32 checksum if missing to improve Kodi scans
- Recursively create target_folder structure
- Added target_filename which allows for customised renaming
- ignore files with 'rarbg.com' and 'sample' in the filename
- rename "Greys Anatomy to "Grey's Anatomy"
v1.3 10/01/2016
- Anime now copies directly to CLEANSED_FOLDER rather than interim prepare folder
- Renamed DESTINATION_FOLDER to PREPARE_FOLDER
v1.2 18/11/2015
- Now supports anime to destination folder
(requires source to be in the form of SOURCE_FOLDER\Anime\Show Name\Episode.ext)
"""
#print "PREPARE_FOLDER", PREPARE_FOLDER
def should_copy_file(filename):
isFolder = os.path.isdir(filename)
if isFolder:
return False
#print "not folder"
bits, fileExtension = os.path.splitext(filename.lower())
fileExtension = fileExtension.split(os.path.extsep)[1]
#print "bits", bits
#print "ext", fileExtension
if fileExtension not in ALLOWED_TYPES:
return False
if 'sample' in filename.lower() or 'rarbg.com' in filename.lower():
return False
if eg.globals.mediaType == "Movies":
if os.path.getsize(filename) <= MOVIE_MINIMUM_FILESIZE:
print "file too small"
return False
#print "allowed"
return True
def copy_file(filename):
f = None
print "copy_file", filename
if not os.path.exists(filename):
print "File doesn't exist", filename
return
target_folder = PREPARE_FOLDER
target_filename = None
mediaType = eg.globals.mediaType
if mediaType == "Movies":
# Create a fake folder
real_filename = filename.split(os.path.sep)[-1]
target_folder = os.path.join(target_folder, real_filename)
elif mediaType == "TV Shows":
if 'greys.anatomy' in filename.lower():
file_parts = filename.split(os.path.sep)
# The folder is correctly labelled + file extension
target_filename = file_parts[-2].lower().replace('greys.anatomy', "grey's.anatomy") + '.' + filename.split('.')[-1]
#print "target_filename", target_filename
elif mediaType == "Anime":
# No auto-renaming scripts/utilities
target_folder = CLEANSED_FOLDER
# C:\Downloads\Anime\Show Name\episode.ext
# C:\Downloads\Anime\whatever_ova.ext
file_parts = filename.split(os.path.sep)
real_filename = file_parts.pop()
show_name = file_parts.pop()
# Append show name if it's available
# (Assuming source folder structure is like the mediaType structure)
if show_name.lower() != mediaType.lower():
# READY\Anime\<show_name>\
target_folder = os.path.join(target_folder, show_name)
# Adding [CRC32SUM] ensures it's scannable by XBMC/Kodi
if not re.search(r"\[[a-fA-F0-9]{8}\]", real_filename):
filename_bits = real_filename.split(os.path.extsep)
filename_bits[0] += " [abcd1234]"
target_filename = os.path.extsep.join(filename_bits)
print "target_filename", target_filename
# Destination file already exists
if os.path.exists(os.path.join(target_folder, os.path.basename(filename))):
print "Destination file already exists", os.path.basename(filename)
return
try:
# Attempt to open the file for writing.
# If it's still copying, then this will fail
f = open(filename, 'rb')
f.close()
f = None
if not os.path.exists(target_folder):
print "Creating missing target folder:", target_folder
os.makedirs(target_folder)
if target_filename is not None:
target_folder = os.path.join(target_folder, target_filename)
shutil.copy(filename, target_folder)
print "*** Copied", os.path.basename(filename)
# Rename files
args = [ THE_RENAMER ]
if mediaType == "TV Shows":
args.append("-fetch")
elif mediaType == "Movies":
args.append("-fetchmovie")
# Use the target folder, because it'll be removed when it finishes (theRenamer -fetchmovie bug)
args.append(r'-ff="%s"' % target_folder)
elif mediaType == "Anime":
# No need for anime autorename
return
else:
raise Exception("Unsupported media type %s" % mediaType)
# print "subprocess call", args
subprocess.call(args)
# print "DONE!"
except IOError, e:
if f:
f.close()
f = None
# Error opening file, wait and try again; 30s
print "file open failed", str(e)
eg.scheduler.AddTask(10.0, copy_file, filename)
def is_file_in_schedule(filename):
# Files that are currently being checked
current_files = [item[2][0] for item in eg.scheduler.__dict__['heap'] if item[1] and item[1].__name__ == 'copy_file']
return (filename in current_files)
def prepare_file(item):
if is_file_in_schedule(item):
return
elif not should_copy_file(item):
return
else:
# Don't start immediately; 60s
eg.scheduler.AddTask(10.0, copy_file, item)
# Could be more than one file in this event
for item in eg.event.payload:
#print dir(eg)
isFolder = os.path.isdir(item)
# Check every file in folder
if isFolder:
for dir, subdirs, files in os.walk(item):
if len(files) == 0:
continue
for file in files:
prepare_file(os.path.join(dir, file))
# Prepare it for copying
else:
prepare_file(item)
view raw gistfile1.py hosted with ❤ by GitHub

This part took the longest because of the finicky nature of events and the EventGhost UI. A few people have contributed to the original script by Pako, but many of the solutions had flaws which made it unworkable for larger files (longer copy times). After months of trial, I've figured out the ideal script to handle most use cases without problems.

Note: Make sure the variables at the top of the script are correct for YOUR setup

    • ALLOWED_TYPES
    • DESTINATION_FOLDER
    • THE_RENAMER
  • When done, rename the new macro to "Copy Video Files"

For each media type (Movies, TV Shows, Anime)

  • Select "Configuration Tree" at the top
  • Click the "Add macro..." button in the toolbar
  • When asked to choose an event to add, select "EventGhost > Python Command" (not Python Script!)
  • For the statement, enter in: mediaType = "Movies" (or "TV Shows", "Anime" etc)
  • Select the macro and rename it to "Copy Movies" (because the default is just silly)
  • Now right click your macro and select "Add event"
  • Type in "DirectoryWatcher.Created" and click ok (Note: For Movies or Anime, use DirectoryWatcher2 or DirectoryWatcher3 accordingly depending on the order you created the plugins)
  • Now right click your macro and select "Add action"
  • Change "If" to "Always"
  • Select "EventGhost > Jump" and select "Copy Video Files"
  • Repeat these steps for TV Shows and Anime if needed

Phew, that's it for EventGhost!

Setting up TheRenamer

Last piece of the puzzle is quite a useful tool. However, the UI isn't the most intuitive so I'll have to guide you through that part. I forgot which mode TheRenamer starts in, but you can switch between "TV Shows" and "Movies" modes by clicking on the middle of the screen as highlighted.

Settings for the current mode is always in the top-right corner.

image37

TV Shows

For TV shows, set it up as shown. This configuration makes it very easy for XBMC to parse your content when organised as "C:\XBMC\TV Shows\Show Name\Season 01\Show Name S01E02.avi".

image31

The important parts are:

  • Renamed format: s1e01 ticked
  • Fetch folder
  • TV shows archive (destination folder)
  • Moving File Structure: TV Show Folder ticked

Movies

For movies, it's much simpler. All you really need is "Movie Name (Year)" and it'd be enough to scrape correctly.

image36

The important parts are:

  • Fetch folder
  • Movies archive (destination folder)
  • Auto move
  • The brackets around the year format

Kodi / XBMC scanning

Whenever Kodi starts up it should scan for new media files. I forgot if this was enabled by default or not, but it's definitely something I would consider setting up after all this.

TV shows and movies will work out of box with The Renamer doing its job correctly.

However, anime will need a little tweaking to read the format correctly.

  • Open up "%APPDATA%\Kodi\userdata\" in Windows Explorer and find advancedsettings.xml
  • If it doesn't exist, download this file and save it there. Then you're done.
  • If it DOES exist, copy in the contents from http://kodi.wiki/view/Anime#Scanning_files_without_renaming_them into it into the right location under the <advancedsettings> tag
  • Save and restart Kodi
  • Anime files should now detect without need for renaming

20DQV7U4
Automation, it's a beautiful thing... when it works.

Sources

 
Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog