2026-06-06 15:19:09 +02:00
2026-06-06 15:19:09 +02:00
2026-01-09 22:33:03 +01:00
2026-01-09 22:33:03 +01:00
2026-01-09 22:33:03 +01:00
2026-06-06 15:19:09 +02:00
2026-02-08 21:53:22 +01:00
2026-05-25 23:47:06 +02:00
2026-01-09 22:57:30 +01:00
2026-01-09 22:57:30 +01:00
2026-01-09 22:33:03 +01:00

Filename Tool

TypeScript library for extracting metadata from media filenames, designed for the MetaMesh ecosystem.

Package name: @metazla/filename-tools (plural — kept for backwards compatibility).

Overview

@metazla/filename-tools parses media file paths to extract structured metadata: titles, seasons, episodes, movie years, plus file-type classification driven by extension and MIME-type mappings. It is a pure-TS library — no Docker, no service. Used inside meta-sort (WatchedFileProcessor) and inside the metamesh-plugin-filename-parser container plugin.

Features

  • Video metadata extraction — title, season, episode, increment, movie year, videoType: "movie" | "tvshow"
  • File-type classification — by extension and MIME type, into a small set (video, audio, subtitle, document, archive, torrent, other, undefined)
  • Title heuristics — combines filename, parent folder, grandparent folder; TV-show pattern detection picks the series name over the episode name
  • Folder helpers — sibling-file lookup
  • Language helpers — convert anything (ISO 639-1 / 2 / 3 / full name) to ISO 639-3
  • Configurable — every pattern set (episodePatterns, seasonAndEpisodePatterns, keywordsArray, …) is exported and overridable

Installation

In the monorepo:

{
  "dependencies": {
    "@metazla/filename-tools": "workspace:*"
  }
}

Build from packages/filename-tool/:

pnpm build
pnpm test    # vitest

Public API

The full export list is in src/lib/index.ts. The two extractor classes are the main entry points; the rest are tools/configs that the extractors consume but you can use directly.

FileNameMetaExtractor

extractMetadata(filePath) is the high-level entry point. It returns a FileMetadata (extends VideoFileMetadata):

import { FileNameMetaExtractor, FileMetadata } from '@metazla/filename-tools';

const watchFolders = ['/files/watch'];
const extractor = new FileNameMetaExtractor(watchFolders);

const metadata: FileMetadata = await extractor.extractMetadata(
  '/files/watch/Naruto/Season 01/Naruto.S01E01.1080p.mkv',
);

// metadata fields that may be populated:
//   fileName     : "Naruto.S01E01.1080p.mkv"
//   extension    : "mkv"
//   fileType     : "video"
//   tags         : string[]                  (extracted from brackets)
//   originalTitle: "Naruto"
//   season       : "1"
//   episode      : "1"
//   increment    : "10001"                   (season * 10000 + episode)
//   movieYear?   : string
//   videoType    : "tvshow"                  (or "movie")
//   extra?       : "true"                    (specials/extras)

The optional second constructor arg is a path to a JSON file that overrides any of the default pattern sets (extensionMappings, mimeTypeMappings, episodePatterns, seasonAndEpisodePatterns, seasonPatterns, extraEpKeyWords, keywordsArray, substringArray, soloEp).

FileNameVideoMetaExtractor

Lower-level — only does the video bits (title, season/episode, year, videoType). Requires all pattern arrays as constructor args (see how metamesh-plugin-filename-parser constructs it):

import {
  FileNameVideoMetaExtractor,
  episodePatterns,
  seasonAndEpisodePatterns,
  seasonPatterns,
  extraEpKeyWords,
  keywordsArray,
  substringArray,
  soloEp,
  VideoFileMetadata,
} from '@metazla/filename-tools';

const extractor = new FileNameVideoMetaExtractor(
  [],
  episodePatterns,
  seasonAndEpisodePatterns,
  seasonPatterns,
  extraEpKeyWords,
  keywordsArray,
  substringArray,
  soloEp,
);

const meta: VideoFileMetadata = extractor.extractVideoFileMetadata(
  'The.Matrix.1999.1080p.BluRay.x264-GROUP.mkv',
);
// { originalTitle: "The Matrix", movieYear: "1999", videoType: "movie" }

FileType

Synchronous classifier wrapping FileTypeConfigurable with the default mappings:

import { FileType, SimpleFileType } from '@metazla/filename-tools';

const ft = new FileType();
const t: SimpleFileType = await ft.getFileType('episode.mkv');  // "video"

SimpleFileType is the union of all classifications: 'audio' | 'video' | 'document' | 'archive' | 'subtitle' | 'torrent' | 'other' | 'undefined'.

Folder helper

import { getSiblingFiles } from '@metazla/filename-tools';

// Returns siblings sharing the same basename (any extension).
const siblings = await getSiblingFiles('/media/show/episode.nfo');

Language helper

import { anyTo_iso_639_3 } from '@metazla/filename-tools';

anyTo_iso_639_3('en');         // "eng" (ISO 639-1 → 639-3)
anyTo_iso_639_3('english');    // "eng" (name → 639-3)
anyTo_iso_639_3('jpn');        // "jpn" (already 639-3; pass-through)

What videoType actually contains

Note this differs from what some older docs claim — the library only emits "tvshow" or "movie". There is no "anime"/"documentary"/"unknown" value. Anime-detection happens elsewhere (the metamesh-plugin-anime-detector plugin and AnimeMeta in @metazla/meta-interface).

Build

Dual-format build via tsup:

  • dist/index.js (ESM)
  • dist/index.cjs (CommonJS)
  • dist/index.d.ts (types)
pnpm build      # tsc + tsup
pnpm test       # vitest

License

MIT — same as the MetaMesh monorepo.

S
Description
No description provided
Readme MIT
91 KiB
Languages
TypeScript 99.6%
JavaScript 0.4%