dotfiles

My personal shell configs and stuff
git clone git://git.alex.balgavy.eu/dotfiles.git
Log | Files | Refs | Submodules | README | LICENSE

autosub.lua (9820B)


      1 --=============================================================================
      2 -->>    SUBLIMINAL PATH:
      3 --=============================================================================
      4 --          This script uses Subliminal to download subtitles,
      5 --          so make sure to specify your system's Subliminal location below:
      6 local subliminal = '/Users/alex/.local/bin/subliminal'
      7 --=============================================================================
      8 -->>    SUBTITLE LANGUAGE:
      9 --=============================================================================
     10 --          Specify languages in this order:
     11 --          { 'language name', 'ISO-639-1', 'ISO-639-2' } !
     12 --          (See: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
     13 local languages = {
     14 --          If subtitles are found for the first language,
     15 --          other languages will NOT be downloaded,
     16 --          so put your preferred language first:
     17             { 'English', 'en', 'eng' },
     18 --          { 'Dutch', 'nl', 'dut' },
     19 --          { 'Spanish', 'es', 'spa' },
     20 --          { 'French', 'fr', 'fre' },
     21 --          { 'German', 'de', 'ger' },
     22 --          { 'Italian', 'it', 'ita' },
     23 --          { 'Portuguese', 'pt', 'por' },
     24 --          { 'Polish', 'pl', 'pol' },
     25 --          { 'Russian', 'ru', 'rus' },
     26 --          { 'Chinese', 'zh', 'chi' },
     27 --          { 'Arabic', 'ar', 'ara' },
     28 }
     29 --=============================================================================
     30 -->>    PROVIDER LOGINS:
     31 --=============================================================================
     32 --          These are completely optional and not required
     33 --          for the functioning of the script!
     34 --          If you use any of these services, simply uncomment it
     35 --          and replace 'USERNAME' and 'PASSWORD' with your own:
     36 local logins = {
     37 --          { '--addic7ed', 'USERNAME', 'PASSWORD' },
     38 --          { '--legendastv', 'USERNAME', 'PASSWORD' },
     39 --          { '--opensubtitles', 'USERNAME', 'PASSWORD' },
     40 --          { '--subscenter', 'USERNAME', 'PASSWORD' },
     41 }
     42 --=============================================================================
     43 -->>    ADDITIONAL OPTIONS:
     44 --=============================================================================
     45 local bools = {
     46     auto = false,   -- Automatically download subtitles, no hotkeys required
     47     debug = true, -- Use `--debug` in subliminal command for debug output
     48     force = true,  -- Force download; will overwrite existing subtitle files
     49     utf8 = true,   -- Save all subtitle files as UTF-8
     50 }
     51 local excludes = {
     52     -- Movies with a path containing any of these strings/paths
     53     -- will be excluded from auto-downloading subtitles.
     54     -- Full paths are also allowed, e.g.:
     55     -- '/home/david/Videos',
     56     'no-subs-dl',
     57 }
     58 local includes = {
     59     -- If anything is defined here, only the movies with a path
     60     -- containing any of these strings/paths will auto-download subtitles.
     61     -- Full paths are also allowed, e.g.:
     62     -- '/home/david/Videos',
     63 }
     64 --=============================================================================
     65 local utils = require 'mp.utils'
     66 
     67 
     68 -- Download function: download the best subtitles in most preferred language
     69 function download_subs(language)
     70     language = language or languages[1]
     71     if #language == 0 then
     72         log('No Language found\n')
     73         return false
     74     end
     75 
     76     log('Searching ' .. language[1] .. ' subtitles ...', 30)
     77 
     78     -- Build the `subliminal` command, starting with the executable:
     79     local table = { args = { subliminal } }
     80     local a = table.args
     81 
     82     for _, login in ipairs(logins) do
     83         a[#a + 1] = login[1]
     84         a[#a + 1] = login[2]
     85         a[#a + 1] = login[3]
     86     end
     87     if bools.debug then
     88         -- To see `--debug` output start MPV from the terminal!
     89         a[#a + 1] = '--debug'
     90     end
     91 
     92     a[#a + 1] = 'download'
     93     if bools.force then
     94         a[#a + 1] = '-f'
     95     end
     96     if bools.utf8 then
     97         a[#a + 1] = '-e'
     98         a[#a + 1] = 'utf-8'
     99     end
    100 
    101     a[#a + 1] = '-l'
    102     a[#a + 1] = language[2]
    103     a[#a + 1] = '-d'
    104     a[#a + 1] = directory
    105     a[#a + 1] = filename --> Subliminal command ends with the movie filename.
    106 
    107     local result = utils.subprocess(table)
    108 
    109     if string.find(result.stdout, 'Downloaded 1 subtitle') then
    110         -- When multiple external files are present,
    111         -- always activate the most recently downloaded:
    112         mp.set_property('slang', language[2])
    113         -- Subtitles are downloaded successfully, so rescan to activate them:
    114         mp.commandv('rescan_external_files')
    115         log(language[1] .. ' subtitles ready!')
    116         return true
    117     else
    118         log('No ' .. language[1] .. ' subtitles found\n')
    119         return false
    120     end
    121 end
    122 
    123 -- Manually download second language subs by pressing 'n':
    124 function download_subs2()
    125     download_subs(languages[2])
    126 end
    127 
    128 -- Control function: only download if necessary
    129 function control_downloads()
    130     -- Make MPV accept external subtitle files with language specifier:
    131     mp.set_property('sub-auto', 'fuzzy')
    132     -- Set subtitle language preference:
    133     mp.set_property('slang', languages[1][2])
    134     mp.msg.warn('Reactivate external subtitle files:')
    135     mp.commandv('rescan_external_files')
    136     directory, filename = utils.split_path(mp.get_property('path'))
    137 
    138     if not autosub_allowed() then
    139         return
    140     end
    141 
    142     sub_tracks = {}
    143     for _, track in ipairs(mp.get_property_native('track-list')) do
    144         if track['type'] == 'sub' then
    145             sub_tracks[#sub_tracks + 1] = track
    146         end
    147     end
    148     if bools.debug then -- Log subtitle properties to terminal:
    149         for _, track in ipairs(sub_tracks) do
    150             mp.msg.warn('Subtitle track', track['id'], ':\n{')
    151             for k, v in pairs(track) do
    152                 if type(v) == 'string' then v = '"' .. v .. '"' end
    153                 mp.msg.warn('  "' .. k .. '":', v)
    154             end
    155             mp.msg.warn('}\n')
    156         end
    157     end
    158 
    159     for _, language in ipairs(languages) do
    160         if should_download_subs_in(language) then
    161             if download_subs(language) then return end -- Download successful!
    162         else return end -- No need to download!
    163     end
    164     log('No subtitles were found')
    165 end
    166 
    167 -- Check if subtitles should be auto-downloaded:
    168 function autosub_allowed()
    169     local duration = tonumber(mp.get_property('duration'))
    170     local active_format = mp.get_property('file-format')
    171 
    172     if not bools.auto then
    173         mp.msg.warn('Automatic downloading disabled!')
    174         return false
    175     elseif duration < 900 then
    176         mp.msg.warn('Video is less than 15 minutes\n' ..
    177                       '=> NOT auto-downloading subtitles')
    178         return false
    179     elseif directory:find('^http') then
    180         mp.msg.warn('Automatic subtitle downloading is disabled for web streaming')
    181         return false
    182     elseif active_format:find('^cue') then
    183         mp.msg.warn('Automatic subtitle downloading is disabled for cue files')
    184         return false
    185     else
    186         local not_allowed = {'aiff', 'ape', 'flac', 'mp3', 'ogg', 'wav', 'wv', 'tta'}
    187 
    188         for _, file_format in pairs(not_allowed) do
    189             if file_format == active_format then
    190                 mp.msg.warn('Automatic subtitle downloading is disabled for audio files')
    191                 return false
    192             end
    193         end
    194 
    195         for _, exclude in pairs(excludes) do
    196             local escaped_exclude = exclude:gsub('%W','%%%0')
    197             local excluded = directory:find(escaped_exclude)
    198 
    199             if excluded then
    200                 mp.msg.warn('This path is excluded from auto-downloading subs')
    201                 return false
    202             end
    203         end
    204 
    205         for i, include in ipairs(includes) do
    206             local escaped_include = include:gsub('%W','%%%0')
    207             local included = directory:find(escaped_include)
    208 
    209             if included then break
    210             elseif i == #includes then
    211                 mp.msg.warn('This path is not included for auto-downloading subs')
    212                 return false
    213             end
    214         end
    215     end
    216 
    217     return true
    218 end
    219 
    220 -- Check if subtitles should be downloaded in this language:
    221 function should_download_subs_in(language)
    222     for i, track in ipairs(sub_tracks) do
    223         local subtitles = track['external'] and
    224           'subtitle file' or 'embedded subtitles'
    225 
    226         if not track['lang'] and (track['external'] or not track['title'])
    227           and i == #sub_tracks then
    228             local status = track['selected'] and ' active' or ' present'
    229             log('Unknown ' .. subtitles .. status)
    230             mp.msg.warn('=> NOT downloading new subtitles')
    231             return false -- Don't download if 'lang' key is absent
    232         elseif track['lang'] == language[3] or track['lang'] == language[2] or
    233           (track['title'] and track['title']:lower():find(language[3])) then
    234             if not track['selected'] then
    235                 mp.set_property('sid', track['id'])
    236                 log('Enabled ' .. language[1] .. ' ' .. subtitles .. '!')
    237             else
    238                 log(language[1] .. ' ' .. subtitles .. ' active')
    239             end
    240             mp.msg.warn('=> NOT downloading new subtitles')
    241             return false -- The right subtitles are already present
    242         end
    243     end
    244     mp.msg.warn('No ' .. language[1] .. ' subtitles were detected\n' ..
    245                 '=> Proceeding to download:')
    246     return true
    247 end
    248 
    249 -- Log function: log to both terminal and MPV OSD (On-Screen Display)
    250 function log(string, secs)
    251     secs = secs or 2.5  -- secs defaults to 2.5 when secs parameter is absent
    252     mp.msg.warn(string)          -- This logs to the terminal
    253     mp.osd_message(string, secs) -- This logs to MPV screen
    254 end
    255 
    256 
    257 mp.add_key_binding('b', 'download_subs', download_subs)
    258 mp.add_key_binding('n', 'download_subs2', download_subs2)
    259 mp.register_event('file-loaded', control_downloads)