{"id":13448230,"url":"https://github.com/caronc/nzb-subliminal","last_synced_at":"2025-11-06T10:03:51.147Z","repository":{"id":19548638,"uuid":"22797130","full_name":"caronc/nzb-subliminal","owner":"caronc","description":"Fetches subtitles for the videos it's provided. It can be easily integrated into NZBGet and SABnzbd too.","archived":false,"fork":false,"pushed_at":"2020-08-26T21:45:42.000Z","size":26955,"stargazers_count":106,"open_issues_count":6,"forks_count":14,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-02-27T17:36:26.454Z","etag":null,"topics":["automation","cli","nzbget","nzbget-script","sabnzbd","scheduling-script","subtitle"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/caronc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"caronc","custom":["https://www.paypal.me/lead2gold"]}},"created_at":"2014-08-09T23:10:23.000Z","updated_at":"2025-02-23T14:03:50.000Z","dependencies_parsed_at":"2022-08-31T08:12:02.135Z","dependency_job_id":null,"html_url":"https://github.com/caronc/nzb-subliminal","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caronc%2Fnzb-subliminal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caronc%2Fnzb-subliminal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caronc%2Fnzb-subliminal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caronc%2Fnzb-subliminal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/caronc","download_url":"https://codeload.github.com/caronc/nzb-subliminal/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243841211,"owners_count":20356443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","cli","nzbget","nzbget-script","sabnzbd","scheduling-script","subtitle"],"created_at":"2024-07-31T05:01:39.455Z","updated_at":"2025-10-06T18:11:50.138Z","avatar_url":"https://github.com/caronc.png","language":"Python","funding_links":["https://github.com/sponsors/caronc","https://www.paypal.me/lead2gold","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=MHANV39UZNQ5E"],"categories":["Python","Automation"],"sub_categories":["Subtitles Automation"],"readme":"__Note:__ This script was intended to be an [NZBGet](http://nzbget.net) _post-processing_\nand _scheduling_ script wrapper for _Subliminal_. The script will work with [SABnzbd](http://sabnzbd.org) (starting at v2.0.0+) and can\nalso work fine as a standalone script for others too.\nSee the _Command Line_ section below for details how you can easily use this on it's own (without NZBGet or SABnzbd).\n\n[![Paypal](http://repo.nuxref.com/pub/img/paypaldonate.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=MHANV39UZNQ5E)\n\nSubliminal Processing Script\n============================\n[Subliminal](https://github.com/Diaoul/subliminal) was originally written by Antoine\nBertin (Diaoul Ael). This tool I'm hosting here merely acts as a wrapper to it\nby enhancing the great functionality it already provides. Subliminal\nallows us to take a video file (and/or a directory containing videos) you\nprovide it. From there it makes use of a series of websites in efforts to\nobtain the subtitles associated with the videos it scanned. This wrapper\nextends this functionallity by controlling how many interenet requests are made\nfor videos without subtitles. This script will prevents querying videos over\nand over again that simply don't have subtitles at all.\n\nI do however maintain a [fork](https://github.com/caronc/subliminal/tree/0.7.x) of the\nSubliminal 0.7.x branch here where I've added my own enhancements to help make\nthis tool do what I want to. Enhancments such as:\n* The script pays attention to the date of the files and only acts on those that are within a certain (configurable) timeframe; _the default age is 24 hours_. This works really amazing for NZBGet users, but for those using this tool in it's standalone version may find it works for them too. This feature allows you to control how many times the internet is polled against a video that has never had subtitles posted for it.  There is more detail on this below in the __Command Line__ section on how to use _(or disable)_ this feature.\n* The script can operate in one of 5 modes:\n   * __ImpairedOnly__: Only attempt to fetch subtitles that are identified as supporting the hearing impaired. _Note: This is not an enhancment and exists in the current version of subliminal._\n   * __StandardOnly__: Only attempt to fetch subtitles that are _NOT_ identified as supporting the hearing impaired. _Note: This is not an enhancment and exists in the current version of subliminal._\n   * __BestScore__: Just download the best matched subtitles reguardless of whether they are for the hearing impaired or not. _Note: This is the default option._\n   * __ImpairedFirst__: This is similar to the __BestScore__ mode above; except the script scores (weighs) the hearing impaired matches a bit higher in efforts to make them be priority over any other subtitles matched.\n   * __StandardFirst__: This is similar to the __BestScore__ mode above; except the script scores (weighs) the hearing impaired matches a bit lower in efforts to make them be the last to be considered as a match.\n* Python v2.6 Support in efforts to target a broader audience.\n\nMost of my changes actually made it back into the original source code ([pull request #404](https://github.com/Diaoul/subliminal/pull/404)). However I still like to maintain my own fork in case of an unforseen enhancment gets pushed upstream that breaks this wrapper.\n\nThis tool can also notify you using [Apprise](https://github.com/caronc/apprise) when a subtitle has\nbeen retrieved too!\n\nInstallation Instructions\n=========================\n1. Ensure you have Python v2.7 installed onto your system.\n```bash\n# Pull in dependencies:\npip install -r requirements.txt\n```\n2. Simply place the __Subliminal.py__ and __Subliminal__ directory together.\n   * __NZBGet users__: you'll want to place these inside of your _nzbget/scripts_ directory. Please ensure you are running _(at least)_ NZBGet v11.0 or higher. You can acquire the latest version of of it from [here](http://nzbget.net/download).\n   * __SABnzbd users__: you'll want to place these inside of your _sabnzbd/scripts_ directory. You may also want to [read this wiki link on maintaining your own Subliminal's Configuration file](https://github.com/caronc/nzb-subliminal/wiki/Subliminal-Configuration-File).\n   * The __Non-NZBGet and SABnzbd users__ can also use this script via a cron (or simply call it\nfrom the command line) to automatically poll directories for the latest\nsubtitles for the video content within it. See the __Command Line__ section\nbelow for more instructions on how to do this.\n\n**Note:** The _Subliminal_ directory provides all of the nessisary dependencies\nin order for this script to work correctly. The directory is only required\nif you do not have the packages already available to your global\nenvironment. These dependant packages are all identified under the\n_Dependencies_ section below.\n\nSupported Subtitle Sites\n========================\nThe table below identifies the provider _Subliminal.py_ supports and the\nlocation that content is retrieved from.\n\n| Provider | Source |\n| -------- | ------ |\n| addic7ed | http://www.addic7ed.com/\n| opensubtitles | http://www.opensubtitles.org/\n| tvsubtitles | http://www.tvsubtitles.net/\n| podnapisi | http://www.podnapisi.net/\n| thesubdb | http://thesubdb.com/\n\nDependencies\n============\nThe following dependencies are already provided for you within the\n_Subliminal_ directory and no further effort is required by you. However, it\nshould be known that Subliminal.py depends on the following packages:\n\n| Name                         | Version | Source                                                                               |\n| ---------------------------- |:------- |:------------------------------------------------------------------------------------ |\n| pysrt                        | 1.0.1   | https://pypi.python.org/pypi/pysrt/1.0.1                                             |\n| babelfish                    | 0.5.4   | https://pypi.python.org/pypi/babelfish/0.5.4                                         |\n| beautifulsoup4               | 4.3.2   | https://pypi.python.org/pypi/beautifulsoup4/4.3.2                                    |\n| python-dateutil              | 2.2     | https://pypi.python.org/packages/source/p/python-dateutil/python-dateutil-2.2.tar.gz |\n| dogpile-cache                | 0.5.4   | https://pypi.python.org/pypi/dogpile.cache/0.5.4                                     |\n| dogpile-core                 | 0.4.1   | https://pypi.python.org/pypi/dogpile.core/0.4.1                                      |\n| enzyme                       | 0.4.1   | https://pypi.python.org/pypi/enzyme/0.4.1                                            |\n| guesslanguage                | 0.2.1   | https://pypi.python.org/pypi/guesslanguage/0.2.1                                     |\n| guessit                      | 0.10.3  | https://pypi.python.org/pypi/guessit/0.10.3                                          |\n| html5lib                     | 0.999   | https://pypi.python.org/pypi/html5lib/0.999                                          |\n| ordereddict                  | 1.1     | https://pypi.python.org/pypi/ordereddict/1.1                                         |\n| repoze.lru                   | 0.6     | https://pypi.python.org/pypi/repoze.lru/0.6                                          |\n| setuptools                   | 0.6.10  | http://svn.python.org/projects/sandbox/branches/setuptools-0.6/pkg_resources.py      |\n| silpa_common                 | 0.3     | https://pypi.python.org/pypi/silpa_common/0.3                                        |\n| six                          | 1.6.1   | https://pypi.python.org/pypi/six/1.6.1                                               |\n| stevedore                    | 0.14    | https://pypi.python.org/pypi/stevedore/0.14                                          |\n| subliminal **[P]**           | 0.7.5   | https://pypi.python.org/pypi/subliminal/0.7.5                                        |\n| pyasn1                       | 0.1.7   | https://pypi.python.org/pypi/pyasn1/0.1.7                                            |\n| pyxdg                        | 0.25    | https://pypi.python.org/pypi/pyxdg/0.25                                              |\n| chared                       | 1.2.1   | https://code.google.com/archive/p/chared/                                            |\n| decorator                    | 4.3.0   | https://pypi.org/project/decorator/4.3.0                                             |\n\n**Note:** The items above denoted with a **[P]** were patched in efforts to:\n- Make their libaries compatible with Python v2.6.\n- Fix bugs to add stability to the overall functionality.\n- Add the nessesary enhancments that benifit this wrapper tool.\n\nTo be as transparent as possible, all patches have been provided in the\n[_/patches_](https://github.com/caronc/nzbget-subliminal/tree/master/patches) directory.\n\nCommand Line\n============\nSubliminal.py has a built in command line interface that can be easily tied\nto a cron entry or can be easilly called from the command line to automate\nthe fetching of subtitles.\n\nHere are the switches available to you:\n```\nUsage: Subliminal.py [options]\n\nOptions:\n  -h, --help            show this help message and exit\n  -S DIR, --scandir=DIR\n                        The directory to scan against. Note: that by setting\n                        this variable, it is implied that you are running this\n                        from the command line.\n  -a AGE, --maxage=AGE  The maximum age a file can be to be considered\n                        searchable. This value is represented in hours. The\n                        default value is 24 hours.\n  -n ENCODING, --encoding=ENCODING\n                        The system encoding to use (utf-8, ISO-8859-1, etc).\n                        The default value is 'UTF-8'.\n  -l LANG, --language=LANG\n                        The language the fetch the subtitles in (en, fr, etc).\n                        The default value is 'en'.\n  -p PROVIDER1,PROVIDER2,etc, --providers=PROVIDER1,PROVIDER2,etc\n                        Specify a list of providers (use commas as delimiters)\n                        to identify the providers you wish to use. The\n                        following will be used by default: 'opensubtitles,tvsu\n                        btitles,podnapisi,addic7ed,thesubdb'\n  -s, --single          Download content without the language code in the\n                        subtitle filename.\n  -b, --basic           Do not attempt to parse additional information from\n                        the video file. Running in a basic mode is much faster\n                        but can make it more difficult to determine the\n                        correct subtitle if more then one is matched.\n  -x PATH1,PATH2,etc, --cross-reference=PATH1,PATH2,etc\n                        Specify an optional list of directories to scan for\n                        subs first before checking on the internet. This is\n                        for directories containing subs (.srt files) that you\n                        have already downloaded ahead of time.\n  -z SIZE_IN_MB, --minsize=SIZE_IN_MB\n                        Specify the minimum size a video must be to be worthy\n                        of of checking for subtiles. This value is interpreted\n                        in MB (Megabytes) and defaults to 150 MB.\n  -c MINSCORE, --minscore=MINSCORE\n                        When scoring multiple matched subtitles for a video,\n                        this value identifies the threshold to assume the\n                        subtitle is no good and should be thrown away when\n                        being compared against others. It currently defaults\n                        to 20.\n  -k, --ignore-embedded\n                        If embedded subtitles were detected, choose not to use\n                        them and continue to search for the subtitles hosted\n                        by the identified provider(s).\n  -e ENCODING, --force-encoding=ENCODING\n                        Optionally specify the subtitle's file encoding toa\n                        specific type (utf-8, ISO-8859-1, etc). If none is\n                        specified then the file is left as is.\n  -f, --force           Force a download reguardless of the file age. This\n                        switch negates any value specified by the --age (-a)\n                        switch.\n  -o, --overwrite       Overwrite a subtitle in the event one is already\n                        present.\n  -m MODE, --fetch-mode=MODE\n                        Identify the fetch mode you wish to invoke, the\n                        options are: 'ImpairedOnly', 'StandardOnly',\n                        'BestScore', 'StandardFirst', 'ImpairedFirst'.  The\n                        default value is: BestScore\n  --addic7ed-user=USER  Optionally use login credentials when accessing\n                        Addic7ed's server. This option is ignored if the\n                        --addic7ed-pass switch is not specified.\n  --addic7ed-pass=PASS  Optionally use login credentials when accessing\n                        Addic7ed's server. This option is ignored if the\n                        --addic7ed-user switch is not specified.\n  --opensubs-user=USER  Optionally use login credentials when accessing Open\n                        Subtitles's server. This option is ignored if the\n                        --opensubs-pass switch is not specified.\n  --opensubs-pass=PASS  Optionally use login credentials when accessing Open\n                        Subtitles's server. This option is ignored if the\n                        --opensubs-user switch is not specified.\n  -t, --tidy-subs       Post process tidying of subtitle.\n  -u URL(s), --notify-urls=URL(s)\n                        Specify 1 or more notification URLs in their URL\n                        format ie: growl://mypass@localhost. See\n                        https://github.com/caronc/apprise for more information\n                        on the different kinds of supported Notification URLs.\n  -T COUNT, --throttle-threshold=COUNT\n                        The threshold defines the number of concurrent\n                        requests made to the remote subtitle websites before a\n                        temporary wait/pause occurs (defined by --throttle).\n                        The goal of the threshold is to prevent one from being\n                        banned for abusing the server (which can happen if you\n                        make to many requests).  This setting is ideal for\n                        those users who are scanning and getting subtitles for\n                        a very large media library. Set this value to 0\n                        (zero) if you want to disable this feature. It\n                        currently defaults to 5.\n  -W SEC, --throttle=SEC\n                        Defines the number of seconds a throttle/block will\n                        occur for when/if a throttle threshold is reached. It\n                        currently defaults to 3.\n  -L FILE, --logfile=FILE\n                        Send output to the specified logfile instead of\n                        stdout.\n  -D, --debug           Debug Mode\n```\n\nHere is simple example:\n```bash\n# Scan a single directory (recursively) for english subtitles\npython Subliminal.py -s -f -S /usr/share/TVShows\n\n# Or just omit the (recently) depricated -S switch to achive the same\n# results:\npython Subliminal.py -s -f /usr/share/TVShows\n\n```\n\n\nYou can scan multiple directories with the following command:\n```bash\n# Scan a single directory (recursively) for english subtitles\npython Subliminal.py -s -f -S \"/usr/share/TVShows, /usr/share/Movies\"\n\n# Or just omit the (recently) depricated -S switch to achive the same\n# results:\npython Subliminal.py -s -f /usr/share/TVShows /usr/share/Movies\n```\n\nAnother nice feature this tool offers is the ability to _expire_ the\nneed to check certain content over and over again.  Considering that most of\nus keep all our videos in one common location.  It would be excessive overkill\nto poll the internet each and every time for each and every file we have (for\nsubtitles) over and over again.  We can assume, that if there are no subtitles for\na given video within the _last 24 hours_ of it's existance on our system, then there\nsimply aren't going to be any later. _I realize this isn't always the case; but\nfor most situations it will be._\n\nIn the above examples, I provided a __--force__ (__-f__) switch which bypasses\nthis feature. But if you want to set up a cron entry to scan your library on\na regular basis, this feature can save you time and effort. A cron could be\neasily configured to scan your library every hour as so:\n```bash\n# $\u003e crontab -e\n0 * * * * /path/to/Subliminal.py -s /usr/share/TVShows /usr/share/Movies\n```\nIf 24 hours seems to short of a window for you, then just specify the\n__--age__ (__-a__) switch and adjust the time to your needs. Remember: it's\nvalue is represented in hours.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaronc%2Fnzb-subliminal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcaronc%2Fnzb-subliminal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaronc%2Fnzb-subliminal/lists"}