I’m not a fan of linear TV watching. Therefore, I try to automatically download TV content that I want to watch either as Podcasts to my smartphone or as video files to my computer. The famous German TV show ‘Tatort’ is an example of the later category. How to automatically download ‘Tatort’ media files to your computer will be a topic for a separate post. This blog post however is about automatically renaming ‘Tatort’ media files with the help of ‘Hazel‘ and ‘AppleScript’.
The challenge
When downloading the latest ‘Tatort’ episode they normally only have the episode title in the file name, such as ‘Tatort-Taxi nach Leipzig.mp4. Other ‘Tatort’ files that I came across either had the episode ID such as ‘1000.mp4’ or the the season/episode number such as ‘S2016E32.mp4’ in the file name.
However, as a ‘KODI‘ and ‘Plex‘ user I would need structured file names that contain the relevant episode information in order that the two media systems are able to identify the correct ‘Tatort’ episodes. Furthermore, I personally want to have the investigator name in the file name as well. Therefore, my preferred naming scheme would be:
- Scheme: Tatort – S<season:yyyy>E<episode:[e]e> – <id:iiii> – <title:text> – <investigator:text>.mp4
- Example: Tatort – S2016E32 – 1000 – Taxi nach Leipzig – Lindholm.mp4
So far, I had to open a website, looking up the missing data and manually update the file name of the downloaded MP4 file. As this was too much (manual) work every week I decided to write an AppleScript for ‘Hazel‘ that would rename the MP4 files for me.
The solution
My new workflow now is:
- I check if the file name of my ‘Tatort’ media file is formatted according to one of the following three options:
1) episode title, e.g. ‘Taxi nach Leipzip.mp4’
2) episode ID, e.g. ‘1000.mp4’
3) season/episode numbering, e.g. ‘S2016E32.mp4’
If the file name does not match any of the the above mentioned options I start watching/scrolling the beginning of the ‘Tatort’ episode. Luckily with macOS’ built-in ‘QuickView’ this can be done with little effort. I just have to hit the space bar when the media file is selected in ‘macOS Finder’. - At this point my ‘Hazel Tatort Workflow’ kicks in. The workflow reads the file name of the MP4 file and hands it over to the the AppleScript. The AppleScript downloads a XML file from the internet and looks up the relevant episode information. This information is then handed back to the ‘Hazel’ workflow which saves the final file name of the the MP4 file und uploads the file to the correct folder on my ‘NAS’.
The following image gallery shows how to to setup such a workflow in Hazel.
[masterslider id=”2″]
Additional comments for each individual step:
- Step 1: Create a new ‘Hazel’ workflow for the folder where your new ‘Tatort’ media files are coming in. The matching condition can be set to files of the kind ‘Movie’. Then add the first rule action of the type ‘Run AppleScript’ to the workflow. Copy & paste the whole code that is listed below to this rule action as embedded code.
- Step 2: Define the import and export values of the rule action ‘Run AppleScript’. The only import value required by the AppleScript is the file name. The export values can be defined by the user. In total there are nine export values to choose from. Please read the comments in the code for further details. It’s important that all export values with a ‘true’ value in the code show up in exactly the same sequence in Hazel’s ‘Script export’ box as in the code. If you have no idea what the instructions in this step mean, then just copy the same setup as shown in the image of ‘Step 2’.
- Step 3: Create your preferred naming scheme for your ‘Tatort’ media files. Note that the available elements may depend on your settings in ‘Step 2’.
- Step 4: Define the subfolder(s) where your ‘Tatort’ media files shall be copied. This step is optional.
- Step 5: Move your ‘Tatort’ media files to your preferred storage device (internal or external hard disk, NAS, etc.). This step is optional.
Note that there can be a significant lag between the moment you copy the ‘Tatort’ media file to the watched folder and the moment Hazel is actually renaming the file. On the one hand this is due to the fact that ‘Hazel’ itself has some built-in delays until a ‘Hazel’ rule is executed. On the other hand it is also because of the poor performance of ‘AppleScript’ execution on ‘macOS’.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
---- Script info ------------------------------------ -- - Version: 9.2 -- - Last updated: 06.08.2018 -- - Creator: Andreas Hess -- - URL: https://blogx.ch/blog/technology/renaming-tatort-files-with-hazel-1/ -- - Copyright: Andreas Hess, May 2018 -- - License: GNU GPLv3 ---- Description ----------------------------------- -- This script was developed as a 'Hazel Rule Action'. The script either accepts the episode title (e.g. "Taxi nach Leipzig"), the episode ID (e.g. "1000") or -- the season/episode number (e.g. "S2016E32") as input parameter from Hazel. It then downloads a XML file with all "Tatort" information, searches the -- input parameter in the XML file and returns the episode parameters the user has defined. -- Note 1: TV Stations have used some episode titles more than one time (e.g. "Taxi nach Leipzig"). As Hazel does not allow the AppleScript to interact with the -- user (e.g. with the help of a pop-up window), it is not possible for the script to know which of the several possible episodes has to be returned. Therefore -- the scripts stops after it found the first match. This problem arises only if you use title as search term, but not if you use episode ID or season/episode number. -- You can change the behavior from returning the 'first result found' to the 'last result found' by setting the parameter 'forceLastResult' to true. Also see below. -- Note 2: The XML file is hosted in my public folder of my Dropbox account. The file will regularly be updated with the latest episode information. The data within -- the XML file is sorted "newest to oldest". To find the information of an old episode it will take considerably longer processing time than for an episode that was -- recently aired. -- -- The following parameters can be defined as true/false values: -- - forceEnglishSeriesName: returns either "Tatort" or "Crime of the Scene" as series name -- - forceCreateReleaseDateObject: forces the code to create a AppleScript date object with the release date of the episode. Only needed if you have some special date calculation needs and you want to extend this script. -- - forceTwoDigitEpisodeNumber: forces the code to return a two-digit episode number (e.g. "02" instead of "2"). Only relevant for output, not for input/search. -- - forceFourDigitIDNumber: forces the code to return a four-digit episode ID (e.g. "0865" instead of "865"). Only relevant for output, not for input/search. -- - forceGermanTransliteratedUmlauts: forces the code to replace German umlauts (Ä,Ö,Ü,ä,ö,ü) to transliterated umlauts (Ae,Oe,Ue,ae,oe,ue). Only relevant for output, not for input/search. -- - forceReplaceGermanDoubleS: forces the code to replace German double S ('ß') with normal double S ('ss'). Only relevant for output, not for input/search. -- - forceLastResult: forces the code to continue the search for the last occurence of the episode title in the XML file. In general, requires longer processing time! -- -- The following true/false parameters indicate the return values of the script -- - returnSeriesNameValue: returns the series name, also see parameter 'forceEnglishSeriesName' -- - returnDateValue: returns the release date of the episode formatted as DD.MM.YYYY, also see parameter 'forceCreateReleaseDateObject' -- - returnSeasonValue: returns the season value of the episode (e.g. "2015") -- - returnEpisodeValue: returns the episdoe value, also see parameter 'forceTwoDigitEpisodeNumber' -- - returnIDValue: returns the consecutive episode ID (e.g. "865") from the beginning of 'Tatort' in 1970, also see parameter 'forceFourDigitIDNumber' -- - returnTitleValue: returns the episode title (e.g. "Taxi nach Leipzig") -- - returnInvestigatorValue: returns the name of the investigator (e.g. "Schimanski") -- - returnTvStationValue: returns the name of the releasing TV station (e.g. "NDR") -- - returnSeasonEpisodeValue: returns the season/episode number (e.g. "S2015E15"), also see parameter 'forceTwoDigitEpisodeNumber' -- -- Search parameter ----------------- -- The following three types of search terms can be used as input value: -- - Episode title: small/capital letters and special characters do not influence the search, e.g. the search term "kaelter ALS Der tod" or "Cote dAzur" will match the correct episodes "Kälter als der Tod" respectively "Côte d'Azur" -- - Episode ID: use integer numbers, e.g. "1", "65", "865", "1025" or special characters like "168a" as ID search terms. Do not add leading zeros, e.g. "0865" or "0168a" -- - Season/Episode: use syntax 'SyyyyE[x]x', e.g. "S2015E15". Do not add leading zeros for episode number, e.g. use "S2015E5" instead of "S2015E05" -- ---- Notes ---------------------- -- You can use this script either in Hazel or with Apple's Script Editor for testing purposes. The only change that has to be done is the setup of the input variable. -- - for Hazel: activate this line -> set theCurrentFileName to item 1 of inputAttributes -- - for Script Editor: activate this line -> set theCurrentFileName to "Taxi nach Leipzig" -- Activating means removing the two dashes "--" in front of the code. Note: only one of these code lines should be active, the other line should be commented out by two dashes "--" -- Parameters for processing ---------------------- set forceEnglishSeriesName to false as boolean set forceCreateReleaseDateObject to false as boolean set forceTwoDigitEpisodeNumber to true as boolean set forceFourDigitIDNumber to true as boolean set forceGermanTransliteratedUmlauts to false as boolean set forceReplaceGermanDoubleS to true as boolean set forceLastResult to false as boolean -- Parameters for return values ------------------ set returnSeriesNameValue to false as boolean set returnDateValue to false as boolean set returnSeasonValue to true as boolean set returnEpisodeValue to false as boolean set returnIDValue to true as boolean set returnTitleValue to true as boolean set returnInvestigatorValue to true as boolean set returnTvStationValue to false as boolean set returnSeasonEpisodeValue to true as boolean ---- Download XML file with Tatort information and store it on the harddisk. Helpful resource were: -- - https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/WorkwithXML.html -- - https://discussions.apple.com/thread/3386494?start=15&tstart=0 set myXMLCmd to " /usr/bin/curl -O -J -L 'Cache-Control: no-cache' 'https://www.dropbox.com/s/16zfe4sf5i6xpxc/tatort.xml?dl=0' > /tmp/tatort.xml" do shell script myXMLCmd -- receive the filename from Hazel or set the file name manually for testing purposes (one of the following two code lines must be deactivated) set theCurrentFileName to item 1 of inputAttributes -- code line required for execution within Hazel -- set theCurrentFileName to "Tatort - Taxi nach Leipzig" as text -- code line required for exectuion within Apple Script Editor for testing purposes --> either enter ID (e.g. "1000"), title (e.g. "Taxi nach Leipzig") or series/episode identifcation (such as SyyyEx, e.g. "S2017E5") -- the file names of Tatort media files automatically downloaded by Synology Download Manager can contain the text prefix "Tatort" with a random string such as "-", " -", "- " or " - ". This text needs to be removed. if theCurrentFileName starts with "Tatort - " then set theCurrentFileName to characters 10 thru (length of theCurrentFileName) of theCurrentFileName as text else if theCurrentFileName starts with "Tatort- " then set theCurrentFileName to characters 9 thru (length of theCurrentFileName) of theCurrentFileName as text else if theCurrentFileName starts with "Tatort -" then set theCurrentFileName to characters 9 thru (length of theCurrentFileName) of theCurrentFileName as text else if theCurrentFileName starts with "Tatort-" then set theCurrentFileName to characters 8 thru (length of theCurrentFileName) of theCurrentFileName as text end if -- AppleScript can ignore the difference e.g. between "a" and "ä", but not between "ä" and "ae". File names containing e.g. "ae" instead of "ä" need to be changed in order to find the correct title in the XML file set theCurrentFileNameUmlauts to theCurrentFileName as text if theCurrentFileName contains "ae" or theCurrentFileName contains "oe" or theCurrentFileName contains "ue" then considering case set myItemsToBeReplaced to {"ae", "oe", "ue", "Ae", "Oe", "Ue"} set myItemsToReplace to {"ä", "ö", "ü", "Ä", "Ö", "Ü"} set prevTxtItemDelimiters to AppleScript's text item delimiters repeat with i from 1 to length of myItemsToBeReplaced set AppleScript's text item delimiters to item i of myItemsToBeReplaced set the item_list to every text item of theCurrentFileNameUmlauts set AppleScript's text item delimiters to item i of myItemsToReplace set theCurrentFileNameUmlauts to the item_list as text end repeat set AppleScript's text item delimiters to prevTxtItemDelimiters end considering end if -- set the result variables set myValueList to {} set myResultArray to {} -- XML processing routine tell application "System Events" tell XML file "/tmp/tatort.xml" tell XML element "tatort" tell XML element "episodes" set myEpisodes to every XML element whose name = "episode" repeat with i from 1 to length of myEpisodes set myEpisode to item i of myEpisodes tell myEpisode -- start retrieving and formating the 3 search terms set myID to value of XML attribute "id" as text -- search term 1 -- display dialog myID set myDateTxt to value of XML attribute "date" set mySeasonInt to (text 7 thru 10 of myDateTxt) as integer set myEpisodeInt to value of XML attribute "no" as integer set mySeasonEpisodeTxt to "S" & mySeasonInt & "E" & myEpisodeInt as text -- search term 3 set myTitleTxt to value of XML attribute "title" as text -- search term 2 -- check if the current XML item matches with the file name provided by Hazel. If yes, put together the return values as list object. ignoring case, diacriticals, hyphens and punctuation if (myID = theCurrentFileName or myTitleTxt = theCurrentFileName or myTitleTxt = theCurrentFileNameUmlauts or mySeasonEpisodeTxt = theCurrentFileName) then -- start formating the series name (DE or EN) if (forceEnglishSeriesName) then set mySeriesNameTxt to "Scene of the Crime" as text -- translated series name according to TheTVDB.com else set mySeriesNameTxt to "Tatort" as text end if -- start formating an AppleScript date object for the release date of the episode if (forceCreateReleaseDateObject) then set myDateObj to the current date set the day of myDateObj to (text 1 thru 2 of myDateTxt) set the month of myDateObj to (text 4 thru 5 of myDateTxt) set the year of myDateObj to mySeasonInt set the hours of myDateObj to "20" set the minutes of myDateObj to "15" set the seconds of myDateObj to "0" -- add code here for formating/calculating the date/time according to your needs and assign the formated/calculated date/time to the variable 'myDateTxt' as text end if -- start of formating the episode number if (forceTwoDigitEpisodeNumber) then set myEpisodeTxt to text -2 thru -1 of ("00" & myEpisodeInt) as text else set myEpisodeTxt to myEpisodeInt as text end if -- put the season/episode string togehter set mySeasonEpisodeTxt to "S" & mySeasonInt & "E" & myEpisodeTxt as text -- start of replacing German umlauts with transliterated umlauts if (forceGermanTransliteratedUmlauts) then considering case and diacriticals set myItemsToBeReplaced to {"ä", "ö", "ü", "Ä", "Ö", "Ü"} set myItemsToReplace to {"ae", "oe", "ue", "Ae", "Oe", "Ue"} set prevTxtItemDelimiters to text item delimiters of AppleScript repeat with i from 1 to length of myItemsToBeReplaced set AppleScript's text item delimiters to item i of myItemsToBeReplaced set the item_list to every text item of myTitleTxt set AppleScript's text item delimiters to item i of myItemsToReplace set myTitleTxt to the item_list as string end repeat set text item delimiters of AppleScript to prevTxtItemDelimiters end considering end if -- start of replacing German double S ('ß') with normal double S ('ss'). if (forceReplaceGermanDoubleS) then set myItemsToBeReplaced to {"ß"} set myItemsToReplace to {"ss"} repeat with i from 1 to length of myItemsToBeReplaced set prevTxtItemDelimiters to text item delimiters of AppleScript set AppleScript's text item delimiters to item i of myItemsToBeReplaced set the item_list to every text item of myTitleTxt set AppleScript's text item delimiters to item i of myItemsToReplace set myTitleTxt to the item_list as string set text item delimiters of AppleScript to prevTxtItemDelimiters end repeat end if -- start of formating the ID number. Some episodes have a character in the ID, e.g. '168a'. these need to handled separately. set myLastChar to (get last character of myID) if "1234567890" does not contain myLastChar then set myIDTemp to characters 1 thru ((length of myID) - 1) of myID as text set myIDInt to myIDTemp as integer else set myIDInt to myID as integer set myLastChar to "" end if -- add leading zero for ID numbers below 1000. Note that the ID number will become 5 digit if the ID contains a character, eg. '168a' becomes '0168a'. if (forceFourDigitIDNumber) then set myIDTxt to text -4 thru -1 of ("0000" & myIDInt) & myLastChar as text else set myIDTxt to myIDInt & myLastChar as text end if -- start of assigning Investigator and TV Station set myInvestigatorTxt to value of XML attribute "inv" as text set myTvStationTxt to value of XML attribute "tvs" as text -- start putting the values of the episode into an AppleScript list object if (returnSeriesNameValue) then set myValueList to {mySeriesNameTxt} if (returnDateValue) then set myValueList to myValueList & {myDateTxt} if (returnSeasonValue) then set myValueList to myValueList & {mySeasonInt} if (returnEpisodeValue) then set myValueList to myValueList & {myEpisodeTxt} if (returnIDValue) then set myValueList to myValueList & {myIDTxt} if (returnTitleValue) then set myValueList to myValueList & {myTitleTxt} if (returnInvestigatorValue) then set myValueList to myValueList & {myInvestigatorTxt} if (returnTvStationValue) then set myValueList to myValueList & {myTvStationTxt} if (returnSeasonEpisodeValue) then set myValueList to myValueList & {mySeasonEpisodeTxt} set myResultArray's end to myValueList set myValueList to {} if (forceLastResult is false) then exit repeat end if end if end ignoring end tell end repeat end tell end tell end tell end tell -- clean up --> delete XML file do shell script "rm /tmp/tatort.xml" -- throw an error if nothing has been found or return the calculated values back to Hazel if (length of myResultArray is 0) then error "No match found!" else return {hazelOutputAttributes:last item of myResultArray} end if |
If you want you can also download a standalone script file that can be executed within ‘Apple Script Editor’. Read the comments within the script (especially the ‘Note’ section) to learn about the differences of the ‘Hazel script’ and the ‘Standalone script’.
Tatort AppleScript v9.2 (26.3 KB)