I found an amazing program I-DeClone to find duplicates in your library because of different naming and size of files. Really fast and not a single bad duplicate and I guess 100% found. Worth each penny. Freed up 300gb with over 400 duplicates found. Almost impossible to find them manually. Even automarks as you wish for example keep larger files.
For those of you using Stash, I made a ELO based ranking plugin for a funner way to sort through my collection: Stash Battle - Plugins - Stash
My hope is this will help me get through my backlog and weed out the videos I actually don’t like eventually ![]()
This got me curious so I had to check. I only got 9 out of 30 TB free on my nas!!! So i’ll likely need some more by the end of this year. As for deleting, it’s kinda rare for me. pretty much only delete bad quality or heresphere 1 stars in regards to pron. But honestly Storage is cheap, and an old 6700k makes a great cheap Nas so I don’t delete much. That said, I’m a little more picky on what I download. It has to be good resolution, and appealing to my tastes. I don’t waste my time on things like the flood of 12 second animations or Gif’s looped for 20 minutes.
Stash has an amazing dupe checker after scanning. So no I-declone necessary. Even shows codec.
tools/duplicate scenes
hahahaha that’s brilliant. I have ZERO plugins for stash other than scrapers. This might be my first.
I noticed you said you used claude to vibe code this,… I tried claude, then bought a subscription… But then refunded it almost instantly when i realized chat gpt cost the same and had no limits…
claude usage limits are too ambiguous and random and I can only do a few prompts each session before i hit my limit…
which tier do you subscribe to? and how do you deal with usage limits?
chat GPT is getting worse and worse at following my instructions for coding, I’m thinking about going back to claude but… man… those usage limits hurt.
Not a plugin its in tools by default,
oh no, i was replying to dtt.
I hope you enjoy the plugin!
I sub to the pro tier for Claude for my main chat activities and used it to build this plugin all in chat but for coding I also pay for Cursor Pro when I’m actually working on professional/personal projects.
For Claude I only ever hit the daily limit once a few weeks ago? And use Opus 4.5 for everything now. The limits are kind of ambiguous at times, I think it has to do with the current demand on the servers because sometimes I look at my usage tab and there’s no limits at all.
For Cursor I’m also using Opus 4.5 when I can but if I’m approaching the limit for the month I just switch to whatever’s free or Auto or Sonnet.
Thats what I do as well…I have an Icy box filled with 18TB harddrives. It is getting full at the moment so I am expanding with a second one ![]()
I both buy more storage and limit what I download. There are several kinds of videos that don’t interest me.
- NonPOV Scenes. Since I watch entirely in VR these - except for PMVs - aren’t as interesting.
- Black male scenes. I’m looking to imagine myself in the scene and this is immersion breaking.
- Blowjob/titfuck/handjob/facesitting/feet/softcore only. These activities by themselves are just not enough to hold my interest.
- Watersports, cuckolds, additional guys AKA Devil’s threesomes. Not my thing.
There are some exceptions, but most of these get skipped or deleted. The nice thing about making up your own rules is you can break them whenever you want!
I generally hang on to compilations as the variety helps for example. Also anything by certain performers.
deleting videos ![]()
getting more storage ![]()
If I have to delete stuff, I go through the folder during post-nut clarity where I become very critical about their artistic quality, then I know exactly which ones to delete..
delete? I’ve never heard of this term, sounds scary to me.
This is brilliant, definitely gonna have to try this out
Compressing everything to AV1 almost doubles your space.
That’s a good callout for sure! tdarr is a free program that lets you transcode your videos in the background on multiple devices. Great for updating the porn collection to AV1 gradually in the background.
Yeah learned it from the evil clown. Now TDARR is a backgound conversion monster. I am not into the app but the conversion we need does not seem to exist. What is needed is plugin that converts to
AV1 60% if bitrate is over 4000
AV1 100% if bitrate is under 4000
First to MPEG then to AV1 100% if not possible to convert to AV1 directly.
That would cover 99.9% of all files.
Can someone compose that flow or plugin for TDARR for us all? Will ask chatgpt later but it always lies.
Edit this is what Chatty spits out but its better not me confirming this to be OK
/* eslint-disable no-unused-vars */
/*
Tdarr Classic Plugin (v2)
- Tiered AV1 target bitrate: 60% if > threshold, else 100%
- Optional MPEG/H.264 bridge stage then re-queue so next cycle can do AV1
*/
const details = () => ({
id: 'Tdarr_Plugin_Custom_AV1_Tiered_Bitrate_With_Bridge',
Stage: 'Pre-processing',
Name: 'AV1 tiered bitrate (60% > threshold, 100% <=) + optional MPEG bridge',
Type: 'Video',
Operation: 'Transcode',
Description:
'Transcodes to AV1 with target bitrate based on source video bitrate. Optionally performs an H.264 bridge first (re-queues) then AV1 in next cycle.',
Version: '1.0',
Tags: 'ffmpeg,av1,svt-av1,bitrate,tiered,bridge',
Inputs: [
{
name: 'bitrate_threshold_kbps',
type: 'number',
defaultValue: 4000,
inputUI: { type: 'text' },
tooltip: 'Threshold in kbps. If source video bitrate > this, target bitrate = src * high_bitrate_percent.',
},
{
name: 'high_bitrate_percent',
type: 'number',
defaultValue: 0.60,
inputUI: { type: 'text' },
tooltip: 'Multiplier applied when bitrate is above threshold. 0.60 = 60%.',
},
{
name: 'low_bitrate_percent',
type: 'number',
defaultValue: 1.00,
inputUI: { type: 'text' },
tooltip: 'Multiplier applied when bitrate is at/below threshold. 1.00 = 100%.',
},
{
name: 'av1_encoder',
type: 'string',
defaultValue: 'libsvtav1',
inputUI: { type: 'text' },
tooltip:
'FFmpeg AV1 encoder name (e.g., libsvtav1, libaom-av1, av1_nvenc, rav1e). Default: libsvtav1.',
},
{
name: 'svt_preset',
type: 'number',
defaultValue: 8,
inputUI: { type: 'text' },
tooltip:
'Only used for libsvtav1. Typical range 0–13 (lower = slower/better). Default 8.',
},
{
name: 'output_container',
type: 'string',
defaultValue: 'mkv',
inputUI: { type: 'text' },
tooltip: 'Output container extension (mkv or mp4). Default: mkv.',
},
{
name: 'enable_mpeg_bridge',
type: 'boolean',
defaultValue: false,
inputUI: { type: 'dropdown', options: ['false', 'true'] },
tooltip:
'If true: for selected “problem” codecs, do an H.264 bridge first (re-queue), then AV1 in next cycle.',
},
{
name: 'bridge_codecs_csv',
type: 'string',
defaultValue: 'vc1,wmv3,msmpeg4v3,mpeg4,mpeg2video',
inputUI: { type: 'text' },
tooltip:
'Comma-separated list of source video codecs that should be bridged to H.264 first when enable_mpeg_bridge=true.',
},
],
});
const plugin = (file, librarySettings, inputs, otherArguments) => {
// Import Tdarr helper to load defaults safely
const importFresh = require('import-fresh');
const { loadDefaultValues } = importFresh('../methods/lib');
inputs = loadDefaultValues(inputs, details);
const response = {
processFile: false,
preset: '',
container: `.${(inputs.output_container || 'mkv').replace('.', '')}`,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
file,
removeFromDB: false,
updateDB: false,
};
// ---- Helpers ----
const getFirstVideoStream = () => {
const streams = (file.ffProbeData && file.ffProbeData.streams) || [];
return streams.find((s) => s.codec_type === 'video');
};
const safeNumber = (v) => {
const n = Number(v);
return Number.isFinite(n) ? n : 0;
};
const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
// ---- Gather source info ----
const vStream = getFirstVideoStream();
if (!vStream) {
response.infoLog = 'No video stream found -> skipping';
return response;
}
const srcCodec = (vStream.codec_name || '').toLowerCase();
// Skip if already AV1
if (srcCodec === 'av1') {
response.infoLog = 'Already AV1 -> skipping';
return response;
}
// Prefer stream bitrate; fallback to format bitrate if needed
// stream.bit_rate / format.bit_rate are bits/sec
const streamBitrateBps = safeNumber(vStream.bit_rate);
const formatBitrateBps = safeNumber(file.ffProbeData?.format?.bit_rate);
const srcBitrateBps = streamBitrateBps > 0 ? streamBitrateBps : formatBitrateBps;
if (srcBitrateBps <= 0) {
response.infoLog =
'Could not determine bitrate from ffprobe (stream/format bit_rate missing) -> skipping';
return response;
}
const srcKbps = Math.round(srcBitrateBps / 1000);
const threshold = safeNumber(inputs.bitrate_threshold_kbps) || 4000;
const highPct = safeNumber(inputs.high_bitrate_percent) || 0.6;
const lowPct = safeNumber(inputs.low_bitrate_percent) || 1.0;
const pct = srcKbps > threshold ? highPct : lowPct;
const targetKbps = Math.max(250, Math.round(srcKbps * pct)); // avoid silly low values
// ---- Optional MPEG/H.264 bridge logic ----
const enableBridge = String(inputs.enable_mpeg_bridge) === 'true' || inputs.enable_mpeg_bridge === true;
const bridgeList = String(inputs.bridge_codecs_csv || '')
.split(',')
.map((s) => s.trim().toLowerCase())
.filter(Boolean);
const needsBridge = enableBridge && bridgeList.includes(srcCodec);
// Tdarr runs plugin stacks cyclically until conditions are met.
// Bridge step: create H.264 output, reQueueAfter=true so next cycle can encode to AV1.
if (needsBridge) {
response.processFile = true;
response.reQueueAfter = true;
response.infoLog = `Bridge enabled: ${srcCodec} -> H.264 (then AV1 next cycle). src=${srcKbps}kbps`;
// Keep audio/subs, re-encode video to H.264 at ~100% of src video bitrate
// (you requested "MPEG then AV1 100%" -> bridge keeps bitrate ~same)
response.preset =
`,-map 0 -map_metadata 0 -c:s copy -c:a copy ` +
`-c:v libx264 -preset medium -b:v ${srcKbps}k -maxrate ${Math.round(srcKbps * 1.2)}k -bufsize ${Math.round(srcKbps * 2)}k ` +
`<io> -max_muxing_queue_size 9999`;
return response;
}
// ---- AV1 transcode ----
const encoder = String(inputs.av1_encoder || 'libsvtav1').trim();
const svtPreset = clamp(safeNumber(inputs.svt_preset) || 8, 0, 13);
response.processFile = true;
response.infoLog =
`AV1 transcode: encoder=${encoder}, src=${srcKbps}kbps, threshold=${threshold}kbps, pct=${pct}, target=${targetKbps}kbps`;
// Build encoder options
// For libsvtav1 we add -preset. For others we don’t assume preset flags.
const encoderOpts =
encoder === 'libsvtav1'
? `-c:v ${encoder} -preset ${svtPreset}`
: `-c:v ${encoder}`;
// Keep audio/subs as-is, only video re-encode
response.preset =
`,-map 0 -map_metadata 0 -c:s copy -c:a copy ` +
`${encoderOpts} -b:v ${targetKbps}k -maxrate ${Math.round(targetKbps * 1.2)}k -bufsize ${Math.round(targetKbps * 2)}k ` +
`<io> -max_muxing_queue_size 9999`;
return response;
};
module.exports.details = details;
module.exports.plugin = plugin;
I hated tdarr personally, got used to fileflows before they became so paywalled. It’s still a good alternative, even free, just not as good as it once was where it could crank out transcodes on two machines simultaneously.
I built a flow for my xxx library that does a resolution check on my videos, then filters them by acceptable bitrates afterwards. If a file is within acceptable bitrates for its resolution or if the codec is already av1 it gets skipped, otherwise it runs an av1 transcode on it. I ran into a lot of issues with CQP/QP/CQ on nvenc_av1 encoding so I stuck to VBR encoding when doing my library.
It has the bonus effect of auto converting mkv to mp4 without losing any embedded subtitles. My phone tends to hate .mkv playback.
ffmpeg custom flags
4k> 60+Mbps becomes
av1_nvenc -rc vbr -cq 26 -b:v 38M -maxrate 54M -bufsize 108M -preset p5 -spatial-aq 1
4k> 40+Mbps becomes
av1_nvenc -rc vbr -cq 26 -b:v 28M -maxrate 42M -bufsize 84M -preset p5 -spatial-aq 1
4k> 30+Mbps becomes
av1_nvenc -rc vbr -cq 28 -b:v 18M -maxrate 26M -bufsize 52M -preset p5 -spatial-aq 1
4k 22+Mbps becomes
av1_nvenc -rc vbr -cq 26 -b:v 12M -maxrate 18M -bufsize 36M -preset p5 -spatial-aq 1
1080p 6+Mbps becomes
av1_nvenc -rc vbr -cq 27 -b:v 5M -maxrate 8M -bufsize 16M -preset p5 -spatial-aq 1
720p 3+Mbps becomes
av1_nvenc -rc vbr -cq 28 -b:v 2.5M -maxrate 4M -bufsize 8M -preset p5 -spatial-aq 1
The whole thing seems too complicated to me honestly.
It’s just messy so I could fit it all in a screenshot but simplifying a bit it does
Is video AV1? Yes = Skip encode, check mp4
Else
What resolution is the video?
Continue
What Bitrate is the video?
Continue
Is the bitrate already low enough to be acceptable for its resolution? Yes = skip encode, check mp4
Else
Transcode to AV1 with standardized parameters, replace original file.

