# Subliminal's badges still point at master while the branch is main

> Diaoul/subliminal fetches subtitles for video files and ships a CLI, a Python library and a container image. The three install routes differ in ways the README does not spell out: the image compiles unrar only when a build argument says so, ships a libmediainfo provider that a pipx install does not, and keeps its cache in a directory the docs never explain, while several links still point at master over plain http.

**Diaoul/subliminal** — Subtitles, faster than your thoughts

- Repository: https://github.com/Diaoul/subliminal
- Website: http://subliminal.readthedocs.org
- Stars: 2,671 · Forks: 317
- Language: Python
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/diaoul-subliminal

## Badges and links that still read master over plain http

The documentation URL in the package metadata is `http://subliminal.readthedocs.org`, without a scheme upgrade, while the Documentation line in the README uses https and the Discord badge points at a discord.gg invite. Two of those links also disagree with each other about which branch they read. The license badge targets `https://github.com/Diaoul/subliminal/blob/master/LICENSE`, the coverage badge points at a raw file on a branch named `python-coverage-comment-action-data`, and every other path in the file uses `main`, which is the default branch.

Two more are dated in the same quiet way. The pypi badge still targets `pypi.python.org/pypi/subliminal`, and the documentation badge still uses the old `readthedocs.org/projects/subliminal/badge/?version=latest` shape. The Discord badge URL is malformed in a smaller way: it reads `https://img.shields.io/badge/discord-7289da.svg?style=flat-square&logo=discord`, so the query string starts with a semicolon instead of a question mark and the styling parameters are not passed to the badge service at all.

## The default config command prints, it does not write

The configuration story has two halves and neither one closes. Arguments can be passed to the CLI through a `subliminal.toml` file in the default configuration folder, and the README says the exact platform-specific path is in the CLI help rather than here. The other half is a one-liner presented as a way to generate a configuration file with all the options and their default values:

```bash
$ python -c "from subliminal.cli import generate_default_config; print(generate_default_config())"
```

It prints to standard output. Nothing in the file redirects that into `subliminal.toml` and nothing names the folder to write into, so the reader still has to know the platform path that the same README declined to print. The `-c` option for pointing at a configuration file elsewhere is stated in one sentence with no example, and the sample configuration is a separate file under docs/assets rather than anything shown inline.

## Three cache mechanisms, one of them documented only in the Dockerfile

Cache handling looks like an afterthought in the prose and a settled decision in the code. The library example configures a DBM backend in Python:

```python
region.configure('dogpile.cache.dbm', arguments={'filename': 'cachefile.dbm'})
```

The container takes a different route. The Dockerfile declares `VOLUME /usr/src/cache` and sets its entrypoint to `["subliminal", "--cache-dir", "/usr/src/cache"]`, and the documented run command mounts a named volume, `subliminal_cache`, at that same path. So three mechanisms sit side by side: a dogpile backend configured in Python, a command line flag, and a container volume. The flag that connects the last two is documented only inside the Dockerfile. A library user copying the example gets a `cachefile.dbm` in the working directory; a container user gets a volume that outlives the container, and neither file explains that choice.

## unrar is only compiled when a build argument asks for it

The image does not fail when it omits something, it just ships without it. `ARG BUILD_WITH_UNRAR=false` defaults to false, and the whole block that fetches the unrar source from rarlab, unpacks it, runs make and installs the result into /usr/local/bin sits behind `if [ "$BUILD_WITH_UNRAR" = true ]`. The version is pinned separately as `ARG UNRAR_VERSION=6.2.6`, and the block installs curl and a virtual apk group only to delete both afterwards with `apk del build-dependencies curl`, so no compiler is left in the final layer.

With the default value, that block is a shell test that does nothing, and the resulting image has no unrar on it. The README never mentions unrar, RAR archives or the build argument anywhere, so the one person who needs it discovers the flag by reading the Dockerfile, and enabling it means fetching a source tarball from rarlab during every image build rather than installing a package.

## The image ships libmediainfo and a pipx install does not

Video details come from knowit, and the README says one of its providers should be installed for better results, naming MediaInfo as the example. One install route meets that and the other does not. The image installs the Alpine package with `apk add --no-cache libmediainfo`, under a comment calling it libmediainfo for metadata refiner, so a container user gets a provider without asking for one. `pipx install subliminal` and `pip install --user subliminal` deliver the Python side only, and the provider stays a separate manual step on a host the README does not describe.

The integrations section has the same shape. Nautilus and Nemo support is delegated to a project page in a different repository, Dolphin support to a Gist, and the tree at the top of this one carries no file manager extension code, so a reader looking for the hook has to leave this repository to find it. The file manager story is a list of addresses, not a description of what each one does.

## The CLI example never says where the subtitle lands

The usage section shows one command and its output:

```bash
$ subliminal download -l en The.Big.Bang.Theory.S05E18.HDTV.x264-LOL.mp4
Collecting videos  [####################################]  100%
1 video collected / 0 video ignored / 0 error
Downloading subtitles  [####################################]  100%
Downloaded 1 subtitle
```

No path appears in that output, and the README does not follow it with a word about where the file is written, which is the first thing a new user wants to know. The library example answers the question sideways, scanning a folder and then calling `save_subtitles(v, subtitles[v])` for every video, described as saving them to disk next to the video. Language selection appears only as `-l en`. The one other flag with any explanation is `--debug`, and the README is explicit that it goes before the `download` subcommand, so argument order matters:

```bash
$ subliminal --debug download -l en The.Big.Bang.Theory.S05E18.HDTV.x264-LOL.mp4
```

Both routes share one silence. The dependency list includes stevedore and click-option-group, yet no provider is named anywhere in the file and no command for listing them is given.

## The version comes from git tags while the Dockerfile names another tool

The package metadata declares `dynamic = ["version"]` and builds with `hatchling` plus `hatch-vcs`, so the version number is derived from the repository's tags instead of being written down anywhere. The Dockerfile then adds a comment reading Add git for setuptools-scm, installs git, and bind mounts the build context before running `python -m pip install .` from that tree, so the image is built out of a local checkout rather than a published wheel. The comment and the declared build backend name two different version control plugins for one job.

The Python range is wider than the container. `requires-python` is `>=3.10`, the classifiers name 3.10 through 3.14, and the image is built `FROM python:3.12-alpine`, one of those five. The tree also carries `.python-version-default`, `changelog.d/`, `HISTORY.rst` and `RELEASING.md`, none of which the README mentions. On timing, releases 2.7.0 and 2.7.1 landed two days apart in July 2026, 2.6.0 is back in February 2026, and the last push to main is dated 2026-09-22.

## Conclusion

Subliminal is a sound choice when you want one tool to fetch subtitles across a folder, and the library example is the most useful thing here because it fixes the cache backend, the age limit and the save step in Python instead of leaving you to guess at flags. Two things are worth checking before you rely on it. If you install the container, decide whether you need unrar, because the default build leaves it out and the flag that adds it is invisible outside the Dockerfile. If you install with pipx or pip, install a knowit provider yourself, because libmediainfo arrives only with the image. For anything scripted, do not expect the CLI section to tell you where files land: the README does not say, so the library route is the one to read.

## FAQ

### What does subliminal do with the video files it scans?

It extracts information about them with knowit, scans a folder for videos newer than a given age, downloads the best subtitles for the languages you name, and in the library route saves each one to disk next to its video through save_subtitles. The example passes age=timedelta(weeks=2) and asks for eng and fra.

### How do I configure subliminal from a file?

Put a subliminal.toml in the default configuration folder, whose platform-specific path the README leaves to the CLI help, or point at one with the `-c` option. The function generate_default_config in the subliminal.cli module returns every option with its default value, and the one-liner in the README prints that result to standard output.

### Does the subliminal container include an archive extractor?

Only when you ask for it at build time. The Dockerfile sets ARG BUILD_WITH_UNRAR=false, and the block that downloads unrar source from rarlab, pins ARG UNRAR_VERSION=6.2.6, compiles it and installs it to /usr/local/bin runs only when that argument is true.

### Where does the subliminal Docker image keep its cache?

At /usr/src/cache, declared as a VOLUME in the Dockerfile and passed by the entrypoint as `--cache-dir /usr/src/cache`; the documented run command mounts a named volume called subliminal_cache there. The library example takes a different path and configures dogpile.cache.dbm with the filename cachefile.dbm.

### Which Python versions does subliminal support?

The package metadata sets requires-python to >=3.10 and its classifiers name 3.10, 3.11, 3.12, 3.13 and 3.14, while the container image is built FROM python:3.12-alpine. The install instructions themselves do not name a version; the tree also carries a .python-version-default file.

## Sources

- [Diaoul/subliminal on GitHub](https://github.com/Diaoul/subliminal)
- [License: MIT](https://github.com/Diaoul/subliminal/blob/main/LICENSE)
- [Project website](http://subliminal.readthedocs.org)
- [README](https://github.com/Diaoul/subliminal/blob/main/README.md)
- [Releases](https://github.com/Diaoul/subliminal/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/diaoul-subliminal
