159 lines
5.2 KiB
Markdown
159 lines
5.2 KiB
Markdown
# 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:
|
|
|
|
```json
|
|
{
|
|
"dependencies": {
|
|
"@metazla/filename-tools": "workspace:*"
|
|
}
|
|
}
|
|
```
|
|
|
|
Build from `packages/filename-tool/`:
|
|
|
|
```bash
|
|
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`):
|
|
|
|
```typescript
|
|
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):
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
import { getSiblingFiles } from '@metazla/filename-tools';
|
|
|
|
// Returns siblings sharing the same basename (any extension).
|
|
const siblings = await getSiblingFiles('/media/show/episode.nfo');
|
|
```
|
|
|
|
### Language helper
|
|
|
|
```typescript
|
|
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)
|
|
|
|
```bash
|
|
pnpm build # tsc + tsup
|
|
pnpm test # vitest
|
|
```
|
|
|
|
## License
|
|
|
|
MIT — same as the MetaMesh monorepo.
|