Batch remove watermarks from videos: one rectangle, four files, three failures

Measured on this machine Every number reproducible No upload, no account

With a folder of clips, the question stops being which tool and becomes which rectangle, and whether it landed on every file. Measured here on four deliveries of one shoot: a rectangle calibrated on a 1920x1080 clip was refused outright by ffmpeg on the 1280x720, 1440x1080 and rotated clips. Clamped inside the frame, it cleaned the 720p file completely (29.23 dB against clean), covered only 75.6% of the mark on the 4:3 file (8.95 dB, a visible ghost) and 0.0% of the rotated one (3.52 dB, the same as doing nothing).

Scaling the rectangle to each frame fixes resolution alone. It still leaves 31.2% of the mark on the 4:3 file, still misses the rotated file completely, and on the 720p file a one-pixel offset costs 14 dB. A batch is not one action repeated; it is a loop with a per-file check, and the check is one line of ffmpeg.

ONE RECTANGLE, FOUR FILES FROM THE SAME SHOOT The rectangle is 160 x 80 px at (1720,960), measured on the 1920x1080 file. A 1920x1080 100% covered B 1280x720 refused, then 100% C 1440x1080 75.6% covered D 720x1280 0.0% covered what the same box did A: the file it was drawn on B: outside the frame, so delogo refuses C: clamped to the corner, 24.4% left D: clamped, lands nowhere near the mark the box is drawn in pixels, so it only fits the file it was measured on inside the mark, against a clean copy (higher is closer to the original) A, box aligned 28.43 dB C, 24.4% of the mark left 8.95 dB D, box missed the mark 3.52 dB never touched at all 3.47 dB a missed box reads the same as an untouched file, which is why the run looks fine

A batch changes the question, not the tool

Everything on the page that separates the three layers still applies to a folder: a container record comes off without re-encoding, and paint on the frames has to be replaced with invented pixels. What changes is the second half. On a single clip, a rectangle that is slightly wrong is something you notice on playback. In a folder it is one line in a log, and the run reports the same success for a file that was cleaned and a file that was not.

Three things vary between deliveries of the same shoot, and they vary independently: resolution (1080p and 720p of the same frame), aspect ratio (16:9 and 4:3 from the same camera), and orientation (a file whose pixels are landscape but whose rotation flag says portrait). A rectangle is a set of four integers in one file's coordinate system. It can be right about one of those three axes and wrong about the others at the same time, which is exactly what the numbers below show.

Four files from one shoot, one watermark

The fixture is one moving background, encoded once, then delivered four ways, with the same mark burned into each at the position a delivery pipeline would use: 160 x 80 px, inset 40 px from the bottom-right corner at 1080p, and scaled with height for the 720p file. Nothing here is a real client folder; it is the smallest set of files that contains all three variations.

FileStored asDisplays asRotation flagWhere the mark is
A1920x10801920x1080none160 x 80 at (1720,960)
B1280x7201280x720none107 x 53 at (1146,640)
C1440x10801440x1080none160 x 80 at (1240,960)
D1280x720720x12809053 x 107 at (640,27)

Row D is the one to read twice. The file is landscape, the picture is portrait, and the mark is not in the corner it was in. Those numbers were not computed from a formula: a frame was decoded to raw luma and the bright rectangle's bounding box was read back from the pixels, which is also how a reader can check their own file. The width and height swap, because the mark is now a tall shape on a tall frame, and the corner changes too: bottom-right in the stored frame, top-right once displayed.

The same rectangle on every file: two refused, one ghost, one untouched

Policy one is what a folder of shell commands usually does: calibrate once, reuse the numbers. The rectangle is 160 x 80 at (1720,960). Three of the four files reject it before any pixel is touched, and the refusal comes from the filter itself, not from a check written for this page.

ffmpeg -i marked.mp4 -vf delogo=x=1720:y=960:w=160:h=80 out.mp4
[Parsed_delogo_0] Logo area is outside of the frame.

That is a good failure, because it is loud. What follows is the bad kind. If the rectangle is clamped back inside the frame, which is what a tool with a drag-and-drop selection does when the selection hangs off the edge, the command runs and the file is written:

FileRectangle after clampingMark coveredResult vs cleanPixels changed
A 1920x1080160 x 80 at (1720,960)100%28.43 dB99.4%
B 1280x720160 x 80 at (1119,639)100%29.23 dB98.9%
C 1440x1080160 x 80 at (1279,960)75.6%8.95 dB74.1%
D 720x1280160 x 80 at (559,960)0.0%3.52 dB0.0%

Read the last two columns together, because they answer different questions. Mark covered is geometry: how much of the true mark the rectangle overlaps. Result vs clean is the outcome: how far the output is from an unmarked copy of the same frame, inside the mark, in decibels, where higher is better. For scale, a file that was never touched reads 3.47 dB on A, 3.47 on B, 3.49 on C and 3.52 on D, and a box that lands reads 28 to 29 dB on this fixture.

So C is not a partial success, it is a visible ghost: 8.95 dB is much closer to untouched than to clean, and the 24.4% of the mark outside the box is a bright edge on a dark corner, which is the most conspicuous shape a leftover can take. D is worse in a quieter way: 3.52 dB is the untouched number to two decimal places, the file is byte-for-byte a different file, and nothing in the run said anything was wrong.

Scaling the rectangle fixes one axis out of three

Policy two is the obvious repair, and it is the one a careful editor reaches for: express the rectangle as fractions of the frame instead of pixels. Calibrated on A, that is x 0.8958, y 0.8889, width 0.0833, height 0.0741, and every file gets its own integers from those fractions.

FileRectangle after scalingMark coveredResult vs cleanPixels changed
A 1920x1080160 x 80 at (1720,960)100%28.43 dB99.4%
B 1280x720107 x 53 at (1147,640)99.1%14.41 dB97.8%
C 1440x1080120 x 80 at (1290,960)68.8%7.99 dB67.8%
D 720x128060 x 95 at (645,1138)0.0%3.52 dB0.0%

Two of these results are counter-intuitive enough to be worth stating plainly. First, B got worse when the rectangle got more accurate: 14.41 dB against the 29.23 dB the clamped 160 x 80 box reached. The scaled box is 107 x 53 at x=1147, the true mark is 107 x 53 at x=1146, so the overlap is 99.1% and the 0.9% that is missing is a one-pixel column of the mark's left edge. One column is enough to leave a bright vertical line, and a line is more visible than the patch it sits in. Rounding a fraction to an integer is where this error comes from, and it is unavoidable unless the rectangle is measured per file.

Second, C barely moved: 68.8% covered against 75.6% for the absolute box. Scaling assumes the mark scales with the frame, and it does not, because a delivery pipeline sizes a bug against the height while a fraction is applied to width and height separately. On a 4:3 frame those two disagree, and the rectangle slides sideways. This is the same arithmetic that decides which edge to crop on a vertical clip, which the phone page works through, except that here it decides whether a box lands at all.

The rotated file: the rectangle changes shape, not just position

D is the file that makes the point that scaling cannot reach. Its stored pixels are 1280x720 and its rotation flag is 90, so a player shows 720x1280. Any filter that runs after the automatic rotation sees the portrait frame, which means the rectangle has to be written in portrait coordinates: a box 53 px wide and 107 px tall at (640,27). The width and height have swapped, and the corner has moved from bottom-right to top-right.

Written that way, the same mark takes a patch at 28.16 dB and 98.1% of its pixels change, which is the same quality as the aligned box on A. Written as a scaled copy of the landscape calibration, it covers 0.0% and the output is indistinguishable from doing nothing. The difference between those two outcomes is not effort or tooling: it is whether the rotation flag was read before the rectangle was computed. The flag is one line of ffprobe, and it is worth running on the whole folder before any of this starts.

ffprobe -v error -select_streams v:0 -show_entries stream=width,height:stream_side_data=rotation -of default=nw=1 *.mp4

One command per file finds the ones the box missed

A batch needs a check that does not require a clean copy of every clip, because in a real folder there is no clean copy: the marked file is the only one you have. What can be measured without a reference is whether the output differs from its input inside the rectangle. If the mark was there and the box landed, nearly every pixel in the box changes. If the box missed, almost none do.

ffmpeg -hide_banner -i in.mp4 -i out.mp4 -lavfi "[0:v][1:v]blend=all_mode=difference,crop=160:80:1720:960,format=gray,lut=y='if(gt(val\,20),255,0)',signalstats,metadata=print:key=lavfi.signalstats.YAVG" -f null -

The YAVG line is a number from 0 to 255; divide by 255 and it is the share of the rectangle that moved by 20 luma levels or more. On this fixture the files where the box landed read 99.4%, 98.9% and 98.1%, and the files where it missed read 0.0%. A threshold of a few percent is enough to separate them, and it needs nothing beyond ffmpeg.

The check has one honest limit, and it is the reason the numbers above come in pairs. It tells you the box touched the mark; it does not tell you the result looks good. C's clamped run changed 74.1% of the rectangle and still left a ghost, because 24.4% of the mark was outside the box. For quality you need a clean reference, or your eyes on the output at 200%: the page that prices the four pixel routes is the one to read before choosing between a patch and a crop, and the page on what survives a removal checks the parts of the file this measurement ignores, such as the audio track and the frame rate.

What a batch costs, measured

The cost side is simpler than the geometry and worth having in the same place, because it decides whether a folder is a coffee break or an afternoon. These are wall-clock times on this machine for 6-second clips of 180 frames, encoding with libx264 at CRF 18:

OperationTimeWhat it touches
stream copy, metadata dropped0.09 scontainer records only, no frame
crop, 1080p to 1920x10008.04 severy frame re-encoded
delogo, 1080p, one box8.19 severy frame re-encoded
three files in one loop6.96 s per fileevery frame of every file

The ratio that matters is the first row against the others: the layer that is a file costs 0.09 s and the layer that is a picture costs about 1.4 times the clip's own length for a 1080p file on this CPU, or 1.2 times across the three files in the loop. A hundred six-second clips is therefore around twelve minutes of encoding by this rate, before any checking, and a folder of ten-minute clips is a different job entirely. The metadata side of this is on the page about what each method leaves behind, and the tool that does it in the browser is on the free video watermark remover page.

What this page does not claim

The fixture is built on this machine: one background, encoded once, delivered four ways, with the mark burned in by ffmpeg. There was no client folder, no stock-site account and no download from any platform, so the numbers describe frames and container flags, not any particular supplier's delivery pipeline. Every figure comes from a real run of the script named below and can be reproduced with ffmpeg alone.

No commercial batch tool was tested, so this page makes no claim about what any of them do with a mixed folder, what they charge, or whether they clamp a rectangle, scale it, or refuse the file. The refusal quoted above is ffmpeg's own delogo filter and nothing else. The readable search results for this query are mostly tool landing pages and how-to guides; the ones that do mention mixed folders say to group files by resolution and keep a separate preset for each group, which is good advice and is the qualitative version of what is measured here.

Nothing here changes who owns a video. A mark that is gone does not make an unlicensed copy licensed, and the page on AI watermark law covers which marks are required and when. This is not legal advice.

Frequently asked questions

Can I remove watermarks from multiple videos at once?

Split the answer by layer. If the mark is a record in the container, yes: a stream copy per file, measured at 0.09 s for a 6-second 1080p clip, and no pixel is touched. If the mark is in the picture, every file is a re-encode and the rectangle has to be right for that file. In the test on this page one rectangle calibrated on a 1920x1080 clip was refused outright by ffmpeg on the 1280x720, 1440x1080 and rotated clips, and once clamped inside the frame it left 24.4% of the mark on the 4:3 file and 100% of it on the rotated one. So "at once" is a loop with a check, not a single action.

Why does a watermark remover work on one video and not the next?

Because the rectangle is stored in pixels, not in percentages. A box measured on a 1920x1080 frame at (1720,960) lies outside a 1280x720 frame, and ffmpeg's delogo refuses it with the message "Logo area is outside of the frame". Clamped back inside, the same box covers the mark on the 720p file completely and the result reads 29.23 dB against a clean copy, but on a 1440x1080 file it covers 75.6% and reads 8.95 dB, which is nearer the 3.49 dB of a file that was never touched than the 28 dB a box that lands reaches: the mark is still there, and the run reported success.

Why does the same rectangle fail on a vertical video?

Because the frame you see is not the frame stored in the file. The test file is coded 1280x720 with a rotation flag of 90 degrees, so it displays as 720x1280, and the mark that sits in the bottom-right of the coded frame appears in the top-right of the displayed one as a rectangle 53 px wide and 107 px tall at (640,27): the width and height swap. A box scaled from the landscape calibration covers 0.0% of it, and the file reads 3.52 dB against clean, which is identical to doing nothing. Measured on the displayed frame, the same mark takes a patch at 28.16 dB.

How do I check a whole folder for watermarks that were not removed?

Compare each output with the file it came from, inside the rectangle, and count the pixels that moved by 20 luma levels or more. On this fixture a box that landed changed between 98.9% and 99.4% of the pixels in the rectangle, while a box that missed changed 0.0%. So a number near zero on a file that had a mark means the box missed it, and the check is one line of ffmpeg per file. What it cannot tell you is whether the patch looks good: for that you need a clean reference or your own eyes, because a box can land and still leave a visible repair.

Does scaling the rectangle to each video keep the watermark gone?

It fixes resolution and nothing else. Scaled to the 720p file the box covers 99.1% of the mark, but the 0.9% it misses is a one-pixel column, and the result reads 14.41 dB against clean instead of the 28 to 29 dB an aligned box reaches. On the 4:3 file scaling covers 68.8% and the result reads 7.99 dB, a visible ghost. On the rotated file it covers 0.0% and changes nothing at all. Resolution, aspect ratio and orientation vary independently, and one proportional rectangle can only follow the first.

How long does it take to clean a folder of videos?

On this machine, with ffmpeg and libx264 at CRF 18, a 6-second 1080p clip took 8.19 s through delogo and 8.04 s through crop, while a stream copy with the metadata dropped took 0.09 s. Three files in one loop took 20.88 s, or 6.96 s per file. By that rate a hundred six-second clips is about twelve minutes. That is one CPU's measurement and not a promise about any product, and longer clips scale roughly with their length rather than with the number of files.