Skip to content

Repository files navigation

Parsium

A highly accurate torrent and video filename parser.

Built from a very large collection of real-world torrents. Handles movies, TV series, anime, multi-language releases, and messy international filenames with a very high title accuracy.

Zero dependencies. <2ms per parse. Works everywhere JavaScript runs.

Try it live in your browser with our interactive demo and playground.


Highlights

  • Very high title accuracy: validated against 10K real production filenames
  • Auto-detects content type: movies, series, anime, no hints needed
  • 80+ languages: VFF, VOSTFR, MULTi, Latino, DL, DualAudio, and more
  • Anime-first-class: fansub conventions, absolute episodes, batch ranges
  • Position-independent: handles tracker prefixes, noise, mixed separators
  • Per-field confidence: know how certain the parser is about each value
  • Plugin system: extend with custom extractors without modifying core
  • Zero dependencies: pure TypeScript, ESM + CJS, <55KB bundled

Install

npm install parsium-media
# or
pnpm add parsium-media
# or
yarn add parsium-media

The package is published as parsium-media. A scoped alias @nepiraw/parsium points at the identical build if you prefer it: npm install @nepiraw/parsium.


Quick Start

import { parse } from 'parsium-media';

const result = parse("The.Boys.S05E02.REPACK.1080p.WEB.H264-TyHD.mkv");
// {
//   title: "The Boys",
//   contentType: "series",
//   seasons: [5],
//   episodes: [2],
//   resolution: "1080p",
//   source: "WEB-DL",
//   codec: "H.264",
//   releaseGroup: "TyHD",
//   isRepack: true,
//   ...
// }

CLI

# Parse a single filename
npx parsium-media "Movie.2024.2160p.UHD.BluRay.x265-GROUP"

# JSON output (only present fields)
npx parsium-media "filename.mkv" --json

# Full JSON (all fields including false/empty)
npx parsium-media "filename.mkv" --json-full

# Show per-field confidence scores
npx parsium-media "filename.mkv" --confidence

# Show debug explanation (extractor trace)
npx parsium-media "filename.mkv" --explain

# Batch mode from file (one filename per line)
npx parsium-media --file torrents.txt --json --progress

API

parse(filename, options?)

Parse a single filename into structured metadata.

import { parse } from 'parsium-media';

const result = parse(
  "Superman.2025.MULTi.2160p.UHD.BluRay.REMUX.DV.HDR10.HEVC.TrueHD.Atmos.7.1-FRATERNiTY.mkv"
);

result.title           // "Superman"
result.year            // 2025
result.contentType     // "movie"
result.resolution      // "2160p"
result.source          // "UHD BluRay"
result.codec           // "HEVC"
result.hdr             // ["DV", "HDR10"]
result.audio           // ["TrueHD", "Atmos"]
result.channels        // ["7.1"]
result.isMultiLanguage // true
result.isRemux         // true
result.releaseGroup    // "FRATERNiTY"

Options:

Option Type Default Description
explain boolean false Include extractor debug trace in result
fieldConfidence boolean false Include per-field confidence scores (0-1)
// With confidence scores
const result = parse("Movie.2024.1080p.BluRay.x264-GROUP", { fieldConfidence: true });
result.fieldConfidence.title      // 0.95
result.fieldConfidence.resolution // 1.0
result.fieldConfidence.source     // 1.0

// With explain trace
const result = parse("Movie.2024.1080p.BluRay.x264-GROUP", { explain: true });
result.explanation // [{ extractor: "resolution", value: "1080p", range: [10, 15], confidence: 1.0, reason: "..." }, ...]

parseBatch(filenames, options?)

Parse multiple filenames with optional progress reporting.

import { parseBatch } from 'parsium-media';

const results = parseBatch(filenames, {
  onProgress: (done, total) => console.log(`${done}/${total}`),
  explain: true,
  fieldConfidence: true,
});

createCachedParser(maxSize?)

Create a parser with LRU cache for repeated parsing of the same filenames.

import { createCachedParser } from 'parsium-media';

const parser = createCachedParser(10000); // max 10K entries
parser.parse("filename.mkv"); // parsed
parser.parse("filename.mkv"); // instant cache hit
parser.size;   // current cache size
parser.clear(); // clear cache

createParser({ plugins })

Create a custom parser with plugins for extending extraction capabilities.

import { createParser } from 'parsium-media';
import type { ParsiumPlugin } from 'parsium-media';

const myPlugin: ParsiumPlugin = {
  name: 'my-plugin',
  extractors: [myCustomExtractor],
};

const parser = createParser({ plugins: [myPlugin] });
const result = parser.parse("filename.mkv");

See PLUGINS.md for the full plugin API.


Extracted Fields

Identity

Field Type Description
title string Extracted title (always present)
altTitle string Alternative title (e.g., original language title)
year number Release year
contentType 'movie' | 'series' | 'unknown' Auto-detected content type
contentSubtype 'anime' Subtype when anime signals are detected

Episodes

Field Type Description
seasons number[] Season numbers (e.g., [5] or [1,2,3] for packs)
episodes number[] Episode numbers (e.g., [2] or [1,2] for multi-ep)
episodeRange { from, to } Episode range (e.g., E01-E12)
absoluteEpisode number Anime absolute episode number
absoluteEpisodeRange { from, to } Anime batch range (e.g., 01~25)
episodeTitle string Episode title if present
date string Date-based episode (YYYY-MM-DD format)
isSeasonPack boolean Full season pack
isCompleteSeries boolean Complete series release
isBatchRelease boolean Batch release (anime)

Video Quality

Field Type Description
resolution string 2160p, 1080p, 720p, 480p, etc.
source string BluRay, UHD BluRay, WEB-DL, WEBRip, HDTV, etc.
codec string x264, x265, H.264, H.265, HEVC, AV1, etc.
bitDepth string 10-bit, 8-bit, 12-bit
frameRate string 24fps, 60fps, etc.
hdr string[] Atomic, ordered: HDR10, DV, HDR10+, HLG, SDR (e.g. ["DV","HDR10"])

Audio

Field Type Description
audio string[] Atomic codecs/layers, e.g. ["DD+","Atmos"], ["TrueHD","Atmos"], ["DTS-HD MA"], ["AAC"]
channels string[] All channel layouts found, e.g. ["7.1"], ["7.1","5.1"], ["2.0"]

Language

Field Type Description
languages Language[] Detected languages with codes and labels
isMultiLanguage boolean MULTi / multi-language release
isDualAudio boolean Dual audio (DualAudio, DUAL, DL/ML markers)
subtitleLanguages Language[] Detected subtitle languages
isMultiSubtitle boolean Multiple subtitle tracks (Multi Subs, MSub, M-SUB)

Release Info

Field Type Description
releaseGroup string Release group name
editions string[] Edition labels (Director's Cut, Extended, Remastered...)
streamingService string Service (Netflix, Amazon, Disney+, etc.)
isRemux boolean REMUX release
isRepack boolean REPACK release
isProper boolean PROPER release
is3D boolean 3D release
isHybrid boolean Hybrid release
isUpscaled boolean AI upscale detected

File Info

Field Type Description
container string File container (mkv, mp4, avi)
raw string Original input string
warnings string[] Validation warnings (if any)

Examples

Movies

parse("Inception.2010.2160p.UHD.BluRay.REMUX.HDR.HEVC.Atmos-GRAIL.mkv");
// title: "Inception", year: 2010, resolution: "2160p", source: "UHD BluRay",
// isRemux: true, hdr: ["HDR"], codec: "HEVC", audio: ["Atmos"]

parse("Le.Comte.de.Monte-Cristo.2024.MULTi.1080p.BluRay.x264-FRATERNiTY");
// title: "Le Comte de Monte-Cristo", year: 2024, isMultiLanguage: true

TV Series

parse("The.Boys.S05E02.REPACK.1080p.WEB.H264-TyHD.mkv");
// title: "The Boys", seasons: [5], episodes: [2], isRepack: true

parse("Malcolm.In.The.Middle.S02E19.1080p.AMZN.WEB-DL.DD+5.1.H.264-ViSiON");
// title: "Malcolm In The Middle", streamingService: "Amazon Prime Video",
// audio: ["DD+"], channels: ["5.1"]

Anime

parse("[SubsPlease] Jujutsu Kaisen 2nd Season - 08 (1080p) [ABC12345].mkv");
// title: "Jujutsu Kaisen", contentType: "series", contentSubtype: "anime",
// seasons: [2], episodes: [8], releaseGroup: "SubsPlease"

parse("[Erai-raws] Oshi no Ko - 01~11 [1080p][Multiple Subtitle]");
// title: "Oshi no Ko", contentType: "series", contentSubtype: "anime",
// absoluteEpisodeRange: { from: 1, to: 11 }, isBatchRelease: true

Multi-Language

parse("Film.2024.MULTi.VFF.1080p.WEB-DL.H265-GroupName");
// title: "Film", isMultiLanguage: true, languages: [{ label: "French" }]

parse("Movie.2024.DUAL.1080p.BluRay.x264-GROUP");
// title: "Movie", isDualAudio: true

Date-Based Episodes

parse("Last.Week.Tonight.2025.01.15.1080p.WEB.H264-GROUPNAME");
// title: "Last Week Tonight", date: "2025-01-15", contentType: "series"

Architecture

Parsium uses a 5-stage pipeline:

Input → Normalizer → Structural Analyzer → Extractor → Classifier → Validator → Result
  1. Normalizer: Strips noise (tracker prefixes, URLs), normalizes separators, decodes entities
  2. Structural Analyzer: Identifies bracket groups and dash positions for context
  3. Extractor: Runs 15 priority-ordered extractors with consumed-range tracking
  4. Classifier: Weighted scoring determines content type (movie/series/anime)
  5. Validator: Cross-field validation and normalization

The title extractor runs last (priority 13) and claims whatever ranges weren't consumed by earlier extractors. This "by-elimination" approach gives Parsium its accuracy edge.

A central field registry (src/field-registry.ts) defines all output fields in one place: their types, categories, display behavior, JSON serialization mode, and default values. The CLI, pipeline assembly, and comparison tools are all driven from this registry, so adding a new field requires only a single entry.

Extractor Priority Order

Priority Extractor What it detects
1 Resolution 2160p, 1080p, 720p, 4K
2 Source BluRay, WEB-DL, HDTV
3 Codec / Date / FPS x265, H.264 / 2025.01.15 / 24fps
4 Audio TrueHD, DTS-HD MA, DD+
5 HDR DV, HDR10, HDR10+
6 Language 80+ langs, scene markers
7 Year Position-aware scoring
8 Edition Director's Cut, Extended
9 Misc REPACK, PROPER, streaming services
10 Season/Episode S01E02, packs, ranges
11 Anime Episode Absolute eps, batches
12 Release Group Trailing dash, fansub brackets
13 Title Claims unclaimed ranges

Requirements

  • Node.js 22+ (or Bun/Deno)
  • No native dependencies

HTTP API

Parsium also provides an HTTP API for remote parsing. See the API README for endpoints, deployment, and configuration.

Live API demo: https://api.parsium.nepiraw.com

cd api && pnpm install && pnpm dev
# → Parsium API listening on http://localhost:7002
curl -X POST http://localhost:7002/v1/parse \
  -H "Content-Type: application/json" \
  -d '{"filename": "Movie.2024.1080p.BluRay.x264-GROUP.mkv"}'

Endpoints: POST /v1/parse, POST /v1/parse/batch, GET /v1/health, GET /v1/version, GET /v1/openapi.json

Options: full, explain, fieldConfidence (passed via options object in request body)

Deployment: Docker, Vercel, or any Node.js host.