11 KiB
Tdarr Local Flow Plugin Suite
A collection of Tdarr Flow plugins for automated media transcoding with x265 2-pass encoding, audio track selection, subtitle extraction and OCR fallback.
Server: Docker (Linux) Workers: Windows (mapped drives)
⚡ Quick Install / Update via curl
Recommended — install.sh (no ZIP, no clone)
The repo includes an install.sh script that downloads only the index.js
files you need directly from Gitea raw URLs.
Update all plugins at once:
curl -fsSL https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/raw/branch/main/install.sh \
| bash -s -- /your/tdarr/plugins/FlowPlugins
Update a single plugin (e.g. after a bug fix):
curl -fsSL https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/raw/branch/main/install.sh \
| bash -s -- /your/tdarr/plugins/FlowPlugins transcode2PassX265
Update two specific plugins:
curl -fsSL https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/raw/branch/main/install.sh \
| bash -s -- /your/tdarr/plugins/FlowPlugins transcode2PassX265 extractSubtitlesAndOcr
Then restart Tdarr:
docker restart tdarr-server
Alternative — Full ZIP (first install)
PLUGIN_DIR=/path/to/tdarr/plugins/FlowPlugins
curl -fsSL https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/archive/main.zip \
-o /tmp/tdarr-plugins.zip
unzip -q -o /tmp/tdarr-plugins.zip -d /tmp/tdarr-extract
cp -r /tmp/tdarr-extract/Tdarr-plugin/LocalFlowPlugins "${PLUGIN_DIR}/"
cp -r /tmp/tdarr-extract/Tdarr-plugin/FlowHelpers "${PLUGIN_DIR}/"
rm -rf /tmp/tdarr-plugins.zip /tmp/tdarr-extract
docker restart tdarr-server
Alternative — Single raw file
BASE=https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/raw/branch/main
PLUGIN=transcode2PassX265
CATEGORY=video
DEST=/path/to/tdarr/plugins/FlowPlugins/LocalFlowPlugins/${CATEGORY}/${PLUGIN}/1.0.0
mkdir -p "${DEST}"
curl -fsSL "${BASE}/LocalFlowPlugins/${CATEGORY}/${PLUGIN}/1.0.0/index.js" -o "${DEST}/index.js"
| Plugin | Category |
|---|---|
mediaAnalyzerGOP |
utility |
setAnimationFlag |
utility |
extractChaptersXml |
utility |
audioSelectorClamping |
audio |
backupSourceAudio |
audio |
extractSubtitlesAndOcr |
subtitles |
transcode2PassX265 |
video |
Tagged Releases (versioned ZIPs)
Once a release is published by the CI workflow, versioned ZIPs are also available:
VERSION=v1.0.1
curl -L https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/releases/download/${VERSION}/Tdarr-plugins-${VERSION}.zip \
-o tdarr-plugins.zip
unzip -o tdarr-plugins.zip -d "${PLUGIN_DIR}"
rm tdarr-plugins.zip
📁 Directory Layout
LocalFlowPlugins/
├── utility/
│ ├── mediaAnalyzerGOP/1.0.0/index.js
│ ├── setAnimationFlag/1.0.0/index.js
│ └── extractChaptersXml/1.0.0/index.js
├── audio/
│ ├── audioSelectorClamping/1.0.0/index.js
│ └── backupSourceAudio/1.0.0/index.js
├── subtitles/
│ └── extractSubtitlesAndOcr/1.0.0/index.js
└── video/
└── transcode2PassX265/1.0.0/index.js
🔌 Plugin Reference
1. mediaAnalyzerGOP — Media Analyzer & GOP Calculator
Category: utility · Step: 1st in flow
Reads video stream metadata and populates args.variables for all downstream plugins.
| Input | Default | Description |
|---|---|---|
moviePathPatterns |
/Radarr |
Pipe-separated path fragments that identify a Film library (e.g. /Radarr|/films) |
animeSeries |
(empty) | Pipe-separated anime series names to auto-detect (e.g. Naruto|One Piece) |
filmBitrate |
3000 |
Target kbps for live-action films |
seriesBitrate |
3000 |
Target kbps for TV series |
animeBitrateHd |
2000 |
Target kbps for anime ≥720p |
animeBitrateSd |
1000 |
Target kbps for anime <720p |
Outputs: 1 → continue
Variables set: gopKeyint, gopMinKeyint, isAnimation, isMovie, vBitrate, vMaxRate, vBufSize, x265Tune, videoHeight, videoFps
2. setAnimationFlag — Set Animation Flag
Category: utility · Step: optional, after mediaAnalyzerGOP
Manually forces isAnimation=true and x265Tune=animation when a file was not auto-detected as anime. Optionally recalculates bitrate targets.
| Input | Default | Description |
|---|---|---|
animeBitrateHd |
2000 |
Bitrate (kbps) for anime ≥720p |
animeBitrateSd |
1000 |
Bitrate (kbps) for anime <720p |
Outputs: 1 → continue
3. extractChaptersXml — Extract Chapters to XML
Category: utility · Step: before transcode
Runs mkvextract to dump chapter markers to an XML file next to the original source file. Stores the path in variables.chaptersXmlPath for downstream use. Safe to run even when the source has no chapters (mkvextract exit 1 is treated as "no chapters").
No inputs required.
Outputs: 1 → continue
Requires: MKVToolNix (
mkvextract) — automatically located from themkvpropeditPathnode setting.
4. audioSelectorClamping — Audio Selector & Opus Bitrate Clamping
Category: audio · Step: after mediaAnalyzerGOP
Selects the best ITA and ENG audio tracks by codec+bitrate scoring, then calculates clamped Opus target bitrates. No upcoding — output bitrate never exceeds source.
Codec scoring (higher = better): TrueHD 100 · DTS-HD MA 95 · FLAC 90 · EAC3 75 · DTS 60 · AC3 45 · AAC 35 · Opus 30
| Input | Default | Description |
|---|---|---|
filmMultiChannelBitrate |
640 |
Max kbps for 5.1+ film audio |
seriesMultiChannelThreshold |
384 |
kbps threshold: ≥threshold → 384k, else → 256k |
stereoBitrateMax |
128 |
Max kbps for stereo tracks |
Outputs: 1 → ITA or ENG track found · 2 → no target tracks found
Variables set: audioHasIta, audioItaStreamIndex, audioItaOpusBitrate, audioItaChannels, audioItaCodecName, audioHasEng, audioEngStreamIndex, audioEngOpusBitrate, audioEngCodecName
5. backupSourceAudio — Backup Source Audio (DTS / TrueHD ITA)
Category: audio · Step: after audioSelectorClamping
Extracts the ITA audio track as a lossless bitstream copy (-c:a copy) only when the codec is DTS or TrueHD. Output is saved next to the source file. Silently skips if no backup is needed.
No inputs required.
Outputs: 1 → continue
Variables set: audioBackupPath (path of the extracted file, if created)
6. extractSubtitlesAndOcr — Extract Subtitles & OCR Fallback
Category: subtitles · Step: after audioSelectorClamping
Extracts ITA and ENG subtitle streams to SRT files next to the source file.
- Text-based codecs (
subrip,srt,ass,ssa,webvtt,mov_text): direct FFmpeg extraction - Bitmap-based codecs (
hdmv_pgs_subtitle,dvd_subtitle,pgssub,dvbsub): FFmpeg.supextract → SubtitleEdit CLI OCR →.srt
OCR failures are logged as warnings without stopping the pipeline.
Output naming: <basename>.<lang>[.forced][.default][.sdh].srt
| Input | Default | Description |
|---|---|---|
subtitleEditPath |
SubtitleEdit |
Name or full path of SubtitleEdit CLI. Must be in PATH or provide absolute path. |
languages |
ita,eng |
Comma-separated ISO 639-2 language codes to extract |
Outputs: 1 → continue (warnings in log if OCR failed)
Requires: SubtitleEdit CLI for PGS/VOBSUB OCR (Windows workers only).
7. transcode2PassX265 — 2-Pass x265 Transcode
Category: video · Step: last
Performs 2-pass libx265 encoding using VBV parameters from args.variables.
- Video: bound-1080p Lanczos scaling (no letterbox, even dimensions)
- Audio: Opus re-encode with per-track indexed bitrate (ITA default, ENG secondary)
- Subtitles: stripped (
-sn) - Chapters: preserved (
-map_chapters 0) - 2-pass logs: automatically cleaned up after encode
| Input | Default | Description |
|---|---|---|
x265Preset |
slow |
x265 preset (ultrafast … veryslow). Slower = better quality. |
outputContainer |
mkv |
Output file extension |
Outputs: 1 → transcode complete
Reads from variables: gopKeyint, gopMinKeyint, vBitrate, vMaxRate, vBufSize, x265Tune, audioHasIta, audioItaStreamIndex, audioItaOpusBitrate, audioHasEng, audioEngStreamIndex, audioEngOpusBitrate
🔗 Flow Variable Map
mediaAnalyzerGOP ──► gopKeyint, gopMinKeyint, vBitrate, vMaxRate, vBufSize
──► isAnimation, isMovie, x265Tune, videoHeight, videoFps
│
(optional) setAnimationFlag ──► overrides vBitrate, vMaxRate, vBufSize, x265Tune
│
audioSelectorClamping ──► audioHasIta, audioItaStreamIndex, audioItaOpusBitrate, audioItaCodecName
──► audioHasEng, audioEngStreamIndex, audioEngOpusBitrate
│
backupSourceAudio ──► audioBackupPath
│
transcode2PassX265 ◄── all of the above
🛠 Requirements
Tdarr Server (Docker/Linux)
- Tdarr ≥ 2.11.01
- Plugins folder mounted at the path configured in Tdarr settings
Tdarr Worker (Windows)
| Tool | Purpose | Download |
|---|---|---|
| FFmpeg (with libopus) | Video/audio/subtitle processing | https://ffmpeg.org/download.html |
| MKVToolNix | Chapter extraction (mkvextract) |
https://mkvtoolnix.download/ |
| SubtitleEdit CLI | PGS/VOBSUB OCR to SRT | https://www.nikse.dk/subtitleedit |
Add to Windows system PATH: ffmpeg\bin, MKVToolNix, SubtitleEdit
Configure in Tdarr node settings:
- FFmpeg Path:
C:\Tools\ffmpeg\bin\ffmpeg.exe - FFprobe Path:
C:\Tools\ffmpeg\bin\ffprobe.exe - MKVPropedit Path:
C:\Program Files\MKVToolNix\mkvpropedit.exe
🧪 Local Testing
# Prerequisites: Node.js, FFmpeg in PATH
cd /path/to/Tdarr-plugin
# 1. Generate sample test files (requires FFmpeg)
node tests/generate-test-files.js
# 2. Run logic tests (no real encode)
node tests/quick-logic-test.js
# 3. Run full integration tests
node tests/run-tests.js
# 4. Run integration tests skipping real x265 encode
node tests/run-tests.js --skip-transcode
📦 Release & Update
Releases are created automatically via GitHub Actions on every push to main or on git tag v*.
To trigger a manual release from the Actions tab, use "Run workflow" and specify the version (e.g. v1.0.1).
To update plugins on the server to the latest release:
VERSION=latest
PLUGIN_DIR=/path/to/tdarr/plugins/FlowPlugins
curl -L https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/releases/download/${VERSION}/Tdarr-plugins-${VERSION}.zip \
-o tdarr-plugins.zip
unzip -o tdarr-plugins.zip -d "${PLUGIN_DIR}"
rm tdarr-plugins.zip
docker restart tdarr-server