Files
Tdarr-plugin/README.md
T
PickleRick 778d6e51ed
Release Plugins / Package & Release (push) Failing after 12s
fix: use Gitea git archive URLs in README (no release dependency)
2026-09-19 14:03:56 +02:00

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 via curl

How it works: Gitea serves a real ZIP of any branch at /archive/<branch>.zip. This is a built-in git archive — no release workflow required, always up to date.

Full Suite (all 7 plugins)

PLUGIN_DIR=/path/to/tdarr/plugins/FlowPlugins

# Download a live ZIP of the main branch directly from Gitea
curl -fsSL https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/archive/main.zip \
  -o /tmp/tdarr-plugins.zip

# Extract and copy into your plugin directory
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

After extracting, restart the Tdarr server so it picks up the new plugins:

docker restart tdarr-server

One-liner (copy-paste for Docker hosts)

PLUGIN_DIR=/your/tdarr/plugins/FlowPlugins && \
curl -fsSL https://git.cdtech.freeddns.org/PickleRick/Tdarr-plugin/archive/main.zip -o /tmp/tp.zip && \
unzip -q -o /tmp/tp.zip -d /tmp/tpx && \
cp -r /tmp/tpx/Tdarr-plugin/LocalFlowPlugins "${PLUGIN_DIR}/" && \
cp -r /tmp/tpx/Tdarr-plugin/FlowHelpers     "${PLUGIN_DIR}/" && \
rm -rf /tmp/tp.zip /tmp/tpx && \
docker restart tdarr-server && echo "Done."

Individual Plugin (single raw file)

Each plugin is a single index.js file. Download just what you need:

# Example: transcode2PassX265
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 Path segment
mediaAnalyzerGOP utility LocalFlowPlugins/utility/mediaAnalyzerGOP/1.0.0/index.js
setAnimationFlag utility LocalFlowPlugins/utility/setAnimationFlag/1.0.0/index.js
extractChaptersXml utility LocalFlowPlugins/utility/extractChaptersXml/1.0.0/index.js
audioSelectorClamping audio LocalFlowPlugins/audio/audioSelectorClamping/1.0.0/index.js
backupSourceAudio audio LocalFlowPlugins/audio/backupSourceAudio/1.0.0/index.js
extractSubtitlesAndOcr subtitles LocalFlowPlugins/subtitles/extractSubtitlesAndOcr/1.0.0/index.js
transcode2PassX265 video LocalFlowPlugins/video/transcode2PassX265/1.0.0/index.js

Tagged Releases (optional, requires CI push)

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 in workDir. 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 the mkvpropeditPath node 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 .sup extract → 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