NeuRelease
A fast neural parser for torrent and release names.
NeuRelease is a fast, high-performance, multilingual neural parser for torrent and release names. It reads a name, extracts its fields - title, season and episode, year, quality, codecs, languages, release group and more - and classifies what the name is: a film, a series, music, a game, software, a book, and whether it is anime. Every value comes with a confidence score and the span it was read from.
It combines a character-level CNN with a Transformer encoder, running as int8 inference with
runtime-dispatched SIMD kernels. No ML runtime, no model download: the wheel carries the compiled
library and the weights, about 5 MB, and Parser() needs no paths.
Pattern-based parsers recognise known markers and guess the rest by position, so anything ambiguous - a number that may be a year or an episode, a word that may be a language or part of the title - is settled the same way every time, right or wrong. NeuRelease decides from context. It is trained on hundreds of thousands of real, labelled release names from a large torrent index - mostly English, with German, Spanish, French, Italian, Russian, Chinese and Japanese names as well.
pip install neurelease
Use
from neurelease import Parser
parser = Parser()
r = parser.parse("Ted.Lasso.S03E03.4-5-1.1080p.ATVP.WEB-DL.DDP5.1.H.264-NTb")
r.title # 'Ted Lasso'
r.season, r.episode, r.episode_title # 3, 3, '4-5-1'
r.streaming_service, r.release_group # 'ATVP', ('NTb',)
r.source == "WEB-DL" # True: enums equal their labels
r.year # None: the name does not say
r.title.confidence, r.episode_title.confidence # 1.00, 0.80: every value knows how sure the model was
r.to_dict() # {'title': 'Ted Lasso', 'season': 3, 'episode': 3, ...}
names = ["Blade.Runner.2049.2017.2160p.UHD.BluRay.x265-TERMiNAL.mkv",
"Stray_v1.5-Razor1911",
"La Casa de Papel - Temporada 3 [HDTV 720p][Cap.305][AC3 5.1 Castellano]",
"【高清剧集网 www.BTHDTV.com】邻家哥哥给我爱[第05-06集][简繁英字幕].Brother.Next.Door.2024.S01E05-06.1080p.WEB-DL.H264.AAC-BTHDTV",
"葬送のフリーレン 第28話 「また会ったときに恥ずかしいからね」 (1080p).mkv",
"Blade.Runner.1982.Final.Cut.REPACK.2160p.UHD.BluRay.DV.HDR.TrueHD.7.1-FraMeSToR"]
releases = parser.parse_batch(names) # one result per name, in order
SHOW = ("title", "alternative_title", "season", "episode", "absolute_episode",
"episode_title", "year", "content", "edition", "version")
for r in releases:
d = r.to_dict()
print({k: d[k] for k in SHOW if d.get(k) is not None})
# {'title': 'Blade Runner 2049', 'year': 2017, 'content': 'movie'}
# {'title': 'Stray', 'content': 'game'}
# {'title': 'La Casa de Papel', 'season': 3, 'episode': 5, 'content': 'series'}
# {'title': 'Brother Next Door', 'alternative_title': '邻家哥哥给我爱', 'season': 1, 'episode': [5, 6], 'year': 2024, 'content': 'series'}
# {'title': '葬送のフリーレン', 'absolute_episode': 28, 'episode_title': 'また会ったときに恥ずかしいからね', 'content': 'series'}
# {'title': 'Blade Runner', 'year': 1982, 'content': 'movie', 'edition': 'Final Cut', 'version': 2}
parse_batch runs many names at once on several threads and returns them in input order. Titles
and evidence keep the original script - Latin, Han, Kana, Cyrillic.
A name also states things about ITSELF rather than its content, and those are fields too:
r = parser.parse("The.Expanse.S05E06.REAL.PROPER.1080p.AMZN.WEB-DL.DDP5.1.H.264-NTb")
r.proper, r.release_real, r.release_version # True, 1, 2
release_version is the one number to sort on: a proper or a repack IS the second copy, v2 is
the anime spelling of the same thing, and release_real counts the times a botched proper had to
be redone - the scene writes REAL.REAL.PROPER, and a boolean would read that as the same release.
edition is a tuple because a release is routinely several at once. Every field a result can carry
is documented in
docs/RESULT.md.
Compared with GuessIt, Sonarr and Radarr
Measured on 2026-09-22 with the shipped model (version 5). Every figure is the share of names answered completely correctly - every field the name states read right, nothing invented. One wrong field fails the name.
Sonarr answers only series and Radarr only films, and they model 16 and 14 fields against 29 here, so the table is split by content kind and scored only on the nine fields all four answer: title, year, resolution, source, release group, edition, audio language, subtitle language, checksum. Our hard sets keep at most three names per franchise.
| cases | NeuRelease | GuessIt | Radarr | Sonarr | |
|---|---|---|---|---|---|
| our labelled names, films | 1,001 | 93.5% | 78.0% | 69.7% | 2.5% |
| our labelled names, series | 2,075 | 96.0% | 60.9% | 8.1% | 65.5% |
| our hard names, films | 1,037 | 54.1% | 30.1% | 36.1% | 1.4% |
| our hard names, series | 915 | 79.2% | 42.2% | 5.8% | 55.0% |
| GuessIt's own corpus, films | 194 | 88.7% | 95.4% | 49.5% | 2.1% |
| GuessIt's own corpus, series | 461 | 85.5% | 94.4% | 7.2% | 57.3% |
| Sonarr's own suite, series | 935 | 91.0% | 80.7% | 45.0% | 95.2% |
| Radarr's own suite, films | 535 | 88.0% | 76.8% | 98.5% | 68.8% |
The last four rows are each parser's own regression suite: strings written to pin its own regexes
down, which is why every parser wins its own and why those wins say little about real names.
NeuRelease is second on all three, having trained on none of them. GuessIt's suite is scored on 859
of its 1,048 entries - the rest are filesystem paths, type assertions inherited from file
defaults, or values our closed vocabulary cannot express. Sonarr's and Radarr's suites run almost
unfiltered.
On the full twenty-field contract, video names: 97.88% macro field F1 and 91.54% exact against GuessIt's 86.74% and 52.96%. About 3x faster on one thread (2,793 us/name against 8,275), 949 us/name in batch on four threads.
Method, exact model identity, scoring snapshot and reproduction: docs/GUESSIT_COMPARISON.md.
Wheels
Python 3.10 or newer. The wheels are tagged py3-none-<platform>, one per platform rather than one
per interpreter, because the library is loaded through ctypes and speaks the stable C ABI.
| Platform | Wheel |
|---|---|
| Linux x86-64 | manylinux_2_28 |
| macOS, Apple Silicon | macosx_11_0_arm64 |
| Windows x86-64 | win_amd64 |
Anywhere else, build from source: the C++ library, the C ABI and the build instructions are in the repository.
License
MIT. PCRE2 is statically linked into the
bundled library, and its notice travels in the wheel as THIRD_PARTY_NOTICES.md.
Release files for neurelease 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| neurelease-0.2.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| neurelease-0.2.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl | Python 3 | none | Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 | Details |
| neurelease-0.2.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
Total release size: 14.8 MB
Release files / neurelease-0.2.0-py3-none-win_amd64.whl
| Download URL | neurelease-0.2.0-py3-none-win_amd64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
edef0d0d4b19456b8d65eac8dc98297147774e1162c1a288b5706d58a08460ea
|
|
BLAKE2b-256 checksum How to use checksums |
f50eea372a185e79d41ccdf8fb21d753a31d4ccd50194b61465b17158fffc0ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.
Transparency logRelease files / neurelease-0.2.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | neurelease-0.2.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
f4392d6337845516a16f330bb4b4ac0ee534d519675ba83d2d004b052dfc569e
|
|
BLAKE2b-256 checksum How to use checksums |
426a10c98861e9ab783f73319e68dfe6964341b04f29e9cd692b62488b8d28aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.
Transparency logRelease files / neurelease-0.2.0-py3-none-macosx_11_0_arm64.whl
| Download URL | neurelease-0.2.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 4.6 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
01fc19c6c9bac8225fcf61f07e2b73de7c6fb307efb7bf2a478e94f74132565b
|
|
BLAKE2b-256 checksum How to use checksums |
7dde89ede8b8b7e3dced672203e0de0aebd0ee2e1f8b845eaafbd49a040f3c82
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.
Transparency log