Skip to content

Commit 8d05ad6

Browse files
committed
feat: add watermark and denoise commands, link to 32blog command generator
1 parent 17eba89 commit 8d05ad6

5 files changed

Lines changed: 127 additions & 2 deletions

File tree

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ npx ffmpeg-quick compress input.mp4
6868
| `trim` | Cut a section from a video |
6969
| `resize` | Resize video to a target width or height |
7070
| `crop` | Crop a region from the video |
71+
| `watermark` | Add image watermark overlay |
72+
| `denoise` | Reduce noise from video or audio |
73+
74+
> Prefer a visual interface? Try the [FFmpeg Command Generator](https://32blog.com/en/tools/ffmpeg-command-generator) on 32blog — build commands by clicking options instead of typing flags.
7175
7276
### Usage
7377

@@ -116,6 +120,12 @@ npx ffmpeg-quick resize input.mp4 -w 1280
116120

117121
# Crop center 1280x720 region
118122
npx ffmpeg-quick crop input.mp4 1280x720
123+
124+
# Add watermark (bottom-right, 10px margin)
125+
npx ffmpeg-quick watermark input.mp4 logo.png
126+
127+
# Denoise video (medium strength)
128+
npx ffmpeg-quick denoise input.mp4 --strength medium
119129
```
120130

121131
### Common Options
@@ -176,6 +186,15 @@ npx ffmpeg-quick crop input.mp4 1280x720
176186
- `<size>` — Crop size as WxH (e.g. 1280x720)
177187
- `--pos <x:y>` — Top-left position (default: center)
178188

189+
**watermark**
190+
- `<image>` — Watermark image file (PNG recommended)
191+
- `--position <pos>` — Position: topleft, top, topright, left, center, right, bottomleft, bottom, bottomright (default: bottomright)
192+
- `--margin <n>` — Margin from edge in pixels (default: 10)
193+
194+
**denoise**
195+
- `--target <type>` — Target: video or audio (default: video)
196+
- `--strength <level>` — Strength: light, medium, strong (default: medium)
197+
179198
### The Hard Stuff, Made Easy
180199

181200
These commands solve problems that send you down a rabbit hole every time:
@@ -293,6 +312,10 @@ npx ffmpeg-quick compress input.mp4
293312
| `trim` | 動画の一部を切り出し |
294313
| `resize` | 解像度を変更 |
295314
| `crop` | 動画の一部を切り抜き |
315+
| `watermark` | 透かし画像をオーバーレイ |
316+
| `denoise` | 映像/音声のノイズ除去 |
317+
318+
> GUIでコマンドを組み立てたい場合は、32blogの [FFmpegコマンドジェネレーター](https://32blog.com/ja/tools/ffmpeg-command-generator) をどうぞ。
296319
297320
### 使い方
298321

@@ -341,6 +364,12 @@ npx ffmpeg-quick resize input.mp4 -w 1280
341364

342365
# 中央を1280x720で切り抜き
343366
npx ffmpeg-quick crop input.mp4 1280x720
367+
368+
# 透かし追加(右下、マージン10px)
369+
npx ffmpeg-quick watermark input.mp4 logo.png
370+
371+
# ノイズ除去(映像、中程度)
372+
npx ffmpeg-quick denoise input.mp4 --strength medium
344373
```
345374

346375
### 共通オプション
@@ -401,6 +430,15 @@ npx ffmpeg-quick crop input.mp4 1280x720
401430
- `<size>` — 切り抜きサイズ WxH(例: 1280x720)
402431
- `--pos <x:y>` — 左上の位置(デフォルト: center)
403432

433+
**watermark**
434+
- `<image>` — 透かし画像ファイル(PNG推奨)
435+
- `--position <pos>` — 位置: topleft, top, topright, left, center, right, bottomleft, bottom, bottomright(デフォルト: bottomright)
436+
- `--margin <n>` — 端からのマージン(px、デフォルト: 10)
437+
438+
**denoise**
439+
- `--target <type>` — 対象: video または audio(デフォルト: video)
440+
- `--strength <level>` — 強度: light, medium, strong(デフォルト: medium)
441+
404442
### 面倒なやつ、全部やります
405443

406444
毎回ググるハメになるやつを1コマンドに:

bin/ffmpeg-quick.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ import { register as stabilize } from "../src/commands/stabilize.js";
1616
import { register as trim } from "../src/commands/trim.js";
1717
import { register as resize } from "../src/commands/resize.js";
1818
import { register as crop } from "../src/commands/crop.js";
19+
import { register as watermark } from "../src/commands/watermark.js";
20+
import { register as denoise } from "../src/commands/denoise.js";
1921

2022
const program = new Command();
2123

2224
program
2325
.name("ffmpeg-quick")
2426
.description("Quick FFmpeg presets for common video tasks")
25-
.version("1.1.0");
27+
.version("1.2.0");
2628

2729
compress(program);
2830
gif(program);
@@ -39,5 +41,7 @@ stabilize(program);
3941
trim(program);
4042
resize(program);
4143
crop(program);
44+
watermark(program);
45+
denoise(program);
4246

4347
program.parse();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ffmpeg-quick",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"description": "Quick FFmpeg presets for common video tasks / FFmpegプリセットCLI",
55
"type": "module",
66
"bin": {

src/commands/denoise.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { run } from "../run.js";
2+
import { outputName } from "../utils.js";
3+
4+
const VIDEO_STRENGTH = {
5+
light: "3:2:3:2",
6+
medium: "5:4:5:4",
7+
strong: "7:6:7:6",
8+
};
9+
10+
const AUDIO_NOISE_FLOOR = {
11+
light: "-20",
12+
medium: "-30",
13+
strong: "-40",
14+
};
15+
16+
export function register(program) {
17+
program
18+
.command("denoise")
19+
.description("Reduce noise from video or audio")
20+
.argument("<input>", "Input video file")
21+
.option("--target <type>", "Target: video or audio", "video")
22+
.option("--strength <level>", "Strength: light, medium, strong", "medium")
23+
.option("-o, --output <path>", "Output file path")
24+
.option("--dry-run", "Print the FFmpeg command without running it")
25+
.option("-y", "Overwrite output without asking")
26+
.action((input, opts) => {
27+
const out = opts.output || outputName(input, "denoised");
28+
const args = ["-i", input];
29+
30+
if (opts.target === "audio") {
31+
const nf = AUDIO_NOISE_FLOOR[opts.strength] || AUDIO_NOISE_FLOOR.medium;
32+
args.push("-af", `afftdn=nf=${nf}`, "-c:v", "copy");
33+
} else {
34+
const params = VIDEO_STRENGTH[opts.strength] || VIDEO_STRENGTH.medium;
35+
args.push("-vf", `hqdn3d=${params}`, "-c:a", "copy");
36+
}
37+
38+
if (opts.y) args.push("-y");
39+
args.push(out);
40+
run(args, { dryRun: opts.dryRun });
41+
});
42+
}

src/commands/watermark.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { run } from "../run.js";
2+
import { outputName } from "../utils.js";
3+
4+
const POS_MAP = {
5+
topleft: (m) => `${m}:${m}`,
6+
top: (m) => `(W-w)/2:${m}`,
7+
topright: (m) => `W-w-${m}:${m}`,
8+
left: (m) => `${m}:(H-h)/2`,
9+
center: () => "(W-w)/2:(H-h)/2",
10+
right: (m) => `W-w-${m}:(H-h)/2`,
11+
bottomleft: (m) => `${m}:H-h-${m}`,
12+
bottom: (m) => `(W-w)/2:H-h-${m}`,
13+
bottomright: (m) => `W-w-${m}:H-h-${m}`,
14+
};
15+
16+
export function register(program) {
17+
program
18+
.command("watermark")
19+
.description("Add image watermark overlay to video")
20+
.argument("<input>", "Input video file")
21+
.argument("<image>", "Watermark image file (PNG recommended)")
22+
.option("--position <pos>", "Position: topleft, top, topright, left, center, right, bottomleft, bottom, bottomright", "bottomright")
23+
.option("--margin <n>", "Margin from edge in pixels", "10")
24+
.option("-o, --output <path>", "Output file path")
25+
.option("--dry-run", "Print the FFmpeg command without running it")
26+
.option("-y", "Overwrite output without asking")
27+
.action((input, image, opts) => {
28+
const out = opts.output || outputName(input, "watermarked");
29+
const posFn = POS_MAP[opts.position] || POS_MAP.bottomright;
30+
const overlay = posFn(opts.margin);
31+
const args = [
32+
"-i", input,
33+
"-i", image,
34+
"-filter_complex", `overlay=${overlay}`,
35+
"-c:a", "copy",
36+
];
37+
if (opts.y) args.push("-y");
38+
args.push(out);
39+
run(args, { dryRun: opts.dryRun });
40+
});
41+
}

0 commit comments

Comments
 (0)