32blogby Studio Mitsu

fqmpegで形状操作: リサイズ・クロップ・回転

fqmpegの14動詞で動画の形を変える。resize/crop/pad/rotate/zoom/backdrop などの実装と落とし穴をソース読みで解説。

by omitsu30 min read
目次

fqmpeg の C5 クラスタは動画の形を変える 14 個の動詞だ。サイズを変える (resize, scale2x)・見える範囲を切り取る (crop, crop-detect)・キャンバスを変える (pad, aspect, backdrop)・向きを変える (rotate, transpose, mirror)・ズームのモーションを付ける (zoom)・フィールド構造を扱う (deinterlace, interlace, field-order) — 「撮影」と「公開」の間にある「絵を正しい形に整える」操作を一通りカバーする。

この記事では各動詞について、生成される FFmpeg フィルタ・デフォルト値・出力名規則・実装由来の罠(scale-2 トリック、padforce_original_aspect_ratio チェイン、zoom の 1920×1080 ハードコード)まで踏み込む。すべて fqmpeg 3.0.2src/commands/ を実読して検証している。

この記事で得られるもの

  • 14 動詞をタスクで選ぶ早見表(スケール / クロップ / パディング / 回転 / モーション / インターレース)
  • 各動詞が生成する FFmpeg コマンドの実出力(--dry-run で検証済み)
  • すべての動詞のデフォルト値・許容値・出力ファイル名
  • 縦動画→YouTube、レターボックス除去、古い映像の修復という実用パイプライン3本

14 動詞の全体図

クラスタは 6 つのタスクグループに綺麗に分かれる。グループから入って動詞を選べばいい。

グループ動詞やること
リサイズ・拡大resize, scale2xピクセル寸法の変更、またはピクセルアート向け 2× 拡大
クロップcrop, crop-detect矩形領域を切り出す、または黒帯を自動検出する
パディング・アスペクトpad, aspect, backdropレターボックス/ピラーボックス、DAR 変更、縦動画→16:9 のぼかし背景
回転・反転rotate, transpose, mirror90/180/270 回転、水平/垂直反転、左右ミラー
モーションzoomKen Burns 風のズームイン/ズームアウト(1920×1080@30 固定)
インターレースdeinterlace, interlace, field-orderコーミング除去、インターレース化、フィールドオーダー設定

読み始める前に押さえておきたい3つのポイント:

  1. resize は自動側に -2 を使う。 -w 1280 を指定すると高さは -2 になる。これは「アスペクトを維持しつつ偶数に丸める」という意味だ。x264/x265/VP9 などのほとんどのコーデックは偶数寸法を要求するため、ナイーブに -1 を渡したときに出る width not divisible by 2 エラーを -2 が事前に防いでくれる。
  2. pad はスケールしてからパディングする。 フィルタは scale=W:H:force_original_aspect_ratio=decrease,pad=W:H:... だ。1280×720 のソースに pad input.mp4 1920x1080 をかけると、まず 1920×1080 にフィットするまで拡大されてからパディングされる — 純粋なパディングではない。スケールなしのリテラルなパディングが欲しいなら、--dry-run で出した出力を編集する必要がある。
  3. zoom は常に 1920×1080@30 で出力される。 フィルタの s=1920x1080:fps=30 がハードコードされていて、オプションでは上書きできない。別の出力サイズや fps が欲しい場合は、--dry-run の出力をコピーしてその値を直接書き換える運用になる。

リサイズ・拡大

resize — 幅または高さを指定してリサイズ

定番のスケーラ。-w で目標幅(高さ自動)、-h で目標高さ(幅自動)を指定する。自動側は -2 になるので出力は偶数寸法に丸められる。

  • ソース: src/commands/resize.js
  • フィルタ: scale=W:-2 または scale=-2:H
  • -w-h のどちらかは必須 — 指定しないと Error: specify --width (-w) or --height (-h). で終了する
引数 / オプションデフォルト補足
<input>必須入力動画
-w, --width <px>目標幅。高さは自動
-h, --height <px>目標高さ。幅は自動
-o, --output <path><入力名>-<N>w.<拡張子> または -<N>h.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg resize input.mp4 -w 1280 --dry-run

  ffmpeg -i input.mp4 -vf scale=1280:-2 -c:a copy input-1280w.mp4
bash
$ npx fqmpeg resize input.mp4 -h 720 --dry-run

  ffmpeg -i input.mp4 -vf scale=-2:720 -c:a copy input-720h.mp4

ソースのアスペクトに関係なく両方の寸法を固定したい(例: 1280×720 ピッタリ)場合は、padaspect --mode stretch を使う。resize はあえてアスペクトを保つ仕様だ。

scale2x — super2xsai で 2× 拡大

FFmpeg の super2xsai フィルタを使ってピクセル寸法を2倍にする。元々はピクセルアートや低解像度のゲーム映像向けに設計されたフィルタで、エッジを保ちつつ拡大する。バイリニア/バイキュービックでは出ないシャープさが出るので、レトロゲームのキャプチャ・スプライトシート・ハードエッジな素材で有用。写真的な素材なら resize -w <2倍> のデフォルト Lanczos のほうが見栄えがいい。

引数 / オプションデフォルト補足
<input>必須入力動画
-o, --output <path><入力名>-2x.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg scale2x input.mp4 --dry-run

  ffmpeg -i input.mp4 -vf super2xsai -c:a copy input-2x.mp4

super2xsai は 2× 固定。3× や 4× が欲しいなら出力に対してもう一度 scale2x を適用してチェイン。AI アップスケーラ(Real-ESRGAN, Topaz Video AI)はディテール復元では super2xsai を上回るが、super2xsai は CPU でリアルタイム処理できる。

クロップ

crop — 矩形領域を切り出す

ソースから固定サイズの矩形を切り出す。デフォルトの位置は中央。--pos x:y で左上の座標を上書きできる。

引数 / オプションデフォルト補足
<input>必須入力動画
<size>必須クロップサイズ WxH
--pos <x:y>center左上座標。center(in_w-W)/2:(in_h-H)/2 を計算
-o, --output <path><入力名>-cropWxH.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg crop input.mp4 1280x720 --dry-run

  ffmpeg -i input.mp4 -vf crop=1280:720:(in_w-1280)/2:(in_h-720)/2 -c:a copy input-crop1280x720.mp4
bash
$ npx fqmpeg crop input.mp4 800x600 --pos 100:50 --dry-run

  ffmpeg -i input.mp4 -vf crop=800:600:100:50 -c:a copy input-crop800x600.mp4

--pos は数値の x:y のみ受け付ける。「右上から各辺 20px のマージン」のような相対位置が必要なら、--dry-run の出力を編集して crop=W:H:in_w-W-20:20 のような FFmpeg 式を直接書く。

crop-detect — 最適なクロップ領域を検出

ファイルを書き出さない。FFmpeg の cropdetect フィルタをソースに対して走らせて、推奨されるクロップ座標を stderr に出力する。レターボックス/ピラーボックスでダウンロードされた動画から黒帯を剥がすときに便利だ — 出力を crop 呼び出しに渡せばいい。

  • ソース: src/commands/crop-detect.js
  • フィルタ: cropdetect=limit=N:round=2:reset=0null muxer へ
  • --limit: 0–255、デフォルト 24。これより暗いピクセルを「黒帯」とみなす
引数 / オプションデフォルト補足
<input>必須入力動画
--limit <n>24黒判定閾値(0–255)。高いほどアグレッシブにクロップする
bash
$ npx fqmpeg crop-detect input.mp4 --dry-run

  ffmpeg -i input.mp4 -vf cropdetect=limit=24:round=2:reset=0 -f null -

実行すると [Parsed_cropdetect_0 @ ...] x1:0 x2:1919 y1:140 y2:939 w:1920 h:800 x:0 y:140 crop=1920:800:0:140 のような行が出る。最後の crop=... がそのまま crop --pos にコピペできる値だ。ノイズが多いソースで検出されないときは --limit を 30–40 に上げる。

パディング・アスペクト

pad — 目標キャンバスにレターボックス/ピラーボックス

ソースをアスペクト保持で WxH にフィットさせ、余った空間を単色で埋める。フィルタチェインは scale=W:H:force_original_aspect_ratio=decrease,pad=W:H:(ow-iw)/2:(oh-ih)/2:color=<color> で、ソースは縮小されてキャンバスを超えない範囲でフィットしてから中央配置でパディングされる。

  • ソース: src/commands/pad.js
  • フィルタ: scale=...:force_original_aspect_ratio=decrease,pad=...:color=<color>
  • --color 形式: FFmpeg の色名または16進(black, white, 0x808080
引数 / オプションデフォルト補足
<input>必須入力動画
<size>必須目標キャンバスサイズ WxH
--color <hex>blackパディング色
-o, --output <path><入力名>-padWxH.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg pad input.mp4 1920x1080 --dry-run

  ffmpeg -i input.mp4 -vf scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=black -c:a copy input-pad1920x1080.mp4
bash
$ npx fqmpeg pad input.mp4 1920x1080 --color white --dry-run

  ffmpeg -i input.mp4 -vf scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=white -c:a copy input-pad1920x1080.mp4

force_original_aspect_ratio=decrease がポイントだ。これによりスケール後の寸法のうち大きい側が目標値と一致するまで縮小され、小さい側がパディングされる。だから 1280×720 のソースを 1920×1080 にパディングすると 1920×1080 にフィットして黒帯ゼロになる(同アスペクトなので拡大される)。一方で 720×1280 の縦動画を 1920×1080 にすると 608×1080 が中央に来て両側にピラーボックスが入る。

aspect — 表示アスペクト比を変更

目標アスペクト比に合わせるための3モード: pad(レターボックス)、crop(切り抜き)、stretch(潰す/伸ばす)。

  • ソース: src/commands/aspect.js
  • <ratio> 形式: W:H(例: 16:9, 4:3, 1:1, 21:9
  • --mode: pad(デフォルト)/ crop / stretch
引数 / オプションデフォルト補足
<input>必須入力動画
<ratio>必須目標アスペクト W:H
--mode <mode>padpad レターボックス / crop 切り抜き / stretch 歪ませる
--color <hex>blackパディング色(pad モードのみ)
-o, --output <path><入力名>-WxH.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg aspect input.mp4 16:9 --dry-run

  ffmpeg -i input.mp4 -vf scale=iw:iw*9/16:force_original_aspect_ratio=decrease,pad=iw:iw*9/16:(ow-iw)/2:(oh-ih)/2:color=black,setsar=1 -c:a copy input-16x9.mp4
bash
$ npx fqmpeg aspect input.mp4 1:1 --mode crop --dry-run

  ffmpeg -i input.mp4 -vf crop='min(iw,ih*1/1)':'min(ih,iw*1/1)' -c:a copy input-1x1.mp4
bash
$ npx fqmpeg aspect input.mp4 21:9 --mode stretch --dry-run

  ffmpeg -i input.mp4 -vf scale=iw:iw*9/21,setsar=1 -c:a copy input-21x9.mp4

setsar=1 でサンプルアスペクト比を 1:1 に戻している。これがないと SAR を尊重するプレイヤーは元の表示アスペクトでレンダリングしてしまう。ここの pad モードは独立した pad 動詞とは挙動が違う点に注意。aspect --mode pad は入力幅と目標比から目標寸法を導出する一方、独立した pad はリテラルなピクセル寸法を取る。

backdrop — 縦動画を 16:9 に(ぼかし背景付き)

「スマホで撮った縦動画を YouTube 用に直す」専用の動詞。ソースを拡大→クロップ→ぼかしたコピーを背景にして、その上に元の縦動画をオーバーレイする。フィルタグラフは3段階: 背景用の scale-and-crop-and-blur、前景用の scale-fit、最後の overlay で中央合成。

  • ソース: src/commands/backdrop.js
  • フィルタ: [0:v]scale=W:H:force_original_aspect_ratio=increase,crop=W:H,boxblur=N[bg];[0:v]scale=W:H:force_original_aspect_ratio=decrease[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2
引数 / オプションデフォルト補足
<input>必須縦動画ファイル
--size <WxH>1920x1080出力キャンバス
--blur <n>20boxblur 強度(高いほどソフトに)
-o, --output <path><入力名>-backdrop.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg backdrop portrait.mp4 --dry-run

  ffmpeg -i portrait.mp4 -filter_complex [0:v]scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080,boxblur=20[bg];[0:v]scale=1920:1080:force_original_aspect_ratio=decrease[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2 -c:a copy portrait-backdrop.mp4
bash
$ npx fqmpeg backdrop portrait.mp4 --size 1920x1080 --blur 30 --dry-run

  ffmpeg -i portrait.mp4 -filter_complex [0:v]scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080,boxblur=30[bg];[0:v]scale=1920:1080:force_original_aspect_ratio=decrease[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2 -c:a copy portrait-backdrop.mp4

4:3 横向きで出したいなら --size 1440x1080 を渡す。ぼかしは(速いが粗い)boxblur を使っているので、もっと綺麗な(が遅い)ガウシアンぼかしが欲しいなら --dry-run 出力の boxblur=20gblur=sigma=20 に書き換える。

回転・反転

rotate — 90/180/270 回転または反転

引数で5モードから選ぶ: 90, 180, 270(時計回り回転)、hflip(水平反転)、vflip(垂直反転)。

  • ソース: src/commands/rotate.js
  • フィルタ: transpose=1(90)、transpose=1,transpose=1(180)、transpose=2(270)、hflipvflip
引数 / オプションデフォルト補足
<input>必須入力動画
<angle>必須90 / 180 / 270 / hflip / vflip
-o, --output <path><入力名>-rot<angle>.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg rotate input.mp4 90 --dry-run

  ffmpeg -i input.mp4 -vf transpose=1 -c:a copy input-rot90.mp4
bash
$ npx fqmpeg rotate input.mp4 hflip --dry-run

  ffmpeg -i input.mp4 -vf hflip -c:a copy input-rothflip.mp4

180 は transpose=4 フラグではなく 90度時計回りを2回(transpose=1,transpose=1)として実装されている。結果は同じだがフィルタを2回通す分わずかに遅い。1ファイルなら誤差レベルだが、1000本のバッチ処理なら --dry-run 編集で vflip,hflip を直接使う手もある。

transpose — 転置の方向を直接指定

rotate の低レベル版。FFmpeg の transpose フィルタを直接公開している: 0 = 90度反時計回り + 垂直反転、1 = 90度時計回り、2 = 90度反時計回り、3 = 90度時計回り + 垂直反転。

引数 / オプションデフォルト補足
<input>必須入力動画
--dir <n>10/1/2/3 — 上記参照
-o, --output <path><入力名>-transposed.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg transpose input.mp4 --dir 2 --dry-run

  ffmpeg -i input.mp4 -vf transpose=2 -c:a copy input-transposed.mp4

rotatetranspose の使い分けで迷ったら、rotate 90transpose --dir 1 は同じ出力だ。transpose を選ぶ理由は rotate が公開していない「回転 + 反転」の合成方向(03)が欲しいときだけ。

mirror — 元画像と反転をサイドバイサイド

入力を2つに分割して片方を反転、左右(horizontal)または上下(vertical)に並べる。出力は入力の縦か横が2倍になり、片側に元画像、もう片側にミラーコピーが来る — 万華鏡風の背景や対称的な MV ショットでよく見るルックだ。

  • ソース: src/commands/mirror.js
  • フィルタ(horizontal): [0:v]split[left][right];[right]hflip[flipped];[left][flipped]hstack
  • フィルタ(vertical): [0:v]split[top][bottom];[bottom]vflip[flipped];[top][flipped]vstack
引数 / オプションデフォルト補足
<input>必須入力動画
--direction <dir>horizontalhorizontal(hstack)または vertical(vstack)
-o, --output <path><入力名>-mirror.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg mirror input.mp4 --dry-run

  ffmpeg -i input.mp4 -filter_complex [0:v]split[left][right];[right]hflip[flipped];[left][flipped]hstack -c:a copy input-mirror.mp4
bash
$ npx fqmpeg mirror input.mp4 --direction vertical --dry-run

  ffmpeg -i input.mp4 -filter_complex [0:v]split[top][bottom];[bottom]vflip[flipped];[top][flipped]vstack -c:a copy input-mirror.mp4

反転だけが欲しい(幅が2倍にならない)場合は rotate hflip を使う。mirror は常に指定した軸の寸法を2倍にする。

モーション

zoom — Ken Burns ズームイン/ズームアウト

モーショングラフィックス用の動詞。FFmpeg の zoompan フィルタでフレームの中心に向かってゆっくりズームインまたはズームアウトする。出力は 1920×1080@30 でハードコードされている — 冒頭の「3つのポイント #3」を参照。

  • ソース: src/commands/zoom.js
  • フィルタ: scale=8000:-1,zoompan=z='min(zoom+<speed>,1.5)':d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=1920x1080:fps=30(ズームイン)
  • 出力は常に 1920×1080@30 — ソースのサイズや fps に関わらず
  • 事前に 8000:-1 にスケール する理由は、zoompan に高解像度の作業コピーを渡してズーム後もシャープさを保つため
引数 / オプションデフォルト補足
<input>必須入力動画(または静止画)
--direction <dir>inin は 1.5× へズームイン、out は 1.5× から開始して引く
--speed <n>0.002フレーム当たりのズーム量、0.0010.01(低いほど遅い)
-o, --output <path><入力名>-zoom-<dir>.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg zoom input.mp4 --direction in --dry-run

  ffmpeg -i input.mp4 -vf scale=8000:-1,zoompan=z='min(zoom+0.002,1.5)':d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=1920x1080:fps=30 -c:a copy input-zoom-in.mp4
bash
$ npx fqmpeg zoom input.mp4 --direction out --speed 0.005 --dry-run

  ffmpeg -i input.mp4 -vf scale=8000:-1,zoompan=z='if(eq(on,1),1.5,max(zoom-0.005,1))':d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=1920x1080:fps=30 -c:a copy input-zoom-out.mp4

speed 0.002(デフォルト)は 250 フレーム(30fps で約 8 秒)かけて 1.5× に到達する。speed 0.005 なら 100 フレーム(約 3.3 秒)。静止画から Ken Burns シーケンスを作るなら、入力を loop で先に伸ばすか FFmpeg の -loop 1 -t <秒数> を使う — zoom 自体は再生時間を伸ばさない。

インターレース

deinterlace — コーミングを除去

アルゴリズムは2択: yadif(デフォルト — 速くて品質も十分)または bwdif(Bob Weaver Deinterlacing Filter — 新しめで品質がわずかに上、速度もわずかに遅い)。最近の素材でインターレースに出会うのはアーカイブ・放送キャプチャくらいだが、どちらのモードでも問題なく扱える。

引数 / オプションデフォルト補足
<input>必須入力動画
--mode <mode>yadifyadif または bwdif
-o, --output <path><入力名>-deinterlaced.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg deinterlace input.mp4 --dry-run

  ffmpeg -i input.mp4 -vf yadif -c:a copy input-deinterlaced.mp4
bash
$ npx fqmpeg deinterlace input.mp4 --mode bwdif --dry-run

  ffmpeg -i input.mp4 -vf bwdif -c:a copy input-deinterlaced.mp4

ソースに目に見えるコーミング(横方向の動きでギザギザのエッジが出る)があれば、これは最初に走らせるべきコマンドだ — 圧縮やカラーグレーディングの前に。再エンコード後にやると、コームのパターンが既にコーデックに焼き込まれてしまうため、残留アーティファクトが出やすい。

interlace — プログレッシブをインターレース化

逆方向の処理。放送系のパイプラインや、インターレース入力を要求するレガシーハードウェア向けの納品でしか使い道はない。Web/モバイル/ストリーミング向けは全部プログレッシブ — このコマンドには触らないでいい。

引数 / オプションデフォルト補足
<input>必須入力動画
-o, --output <path><入力名>-interlaced.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg interlace input.mp4 --dry-run

  ffmpeg -i input.mp4 -vf interlace -c:a copy input-interlaced.mp4

FFmpeg の interlace フィルタのデフォルトのフィールドオーダーは TFF(top-field-first)だ。納品スペックで BFF が必要なら、続けて field-order をかける。

field-order — TFF/BFF を設定

出力が TFF(tff)か BFF(bff)になるようにフィールドにタグを付けるか並べ直す。インターレース素材がカクついて見える原因がフィールドオーダータグの誤りなら、逆向きに変えるだけで直ることが多い。

引数 / オプションデフォルト補足
<input>必須入力動画
<order>必須tff または bff
-o, --output <path><入力名>-<order>.<拡張子>出力ファイル名上書き
bash
$ npx fqmpeg field-order input.mp4 tff --dry-run

  ffmpeg -i input.mp4 -vf fieldorder=tff -c:a copy input-tff.mp4

最近のインターレース素材(1080i 放送、DV)はほぼ TFF。古いキャプチャでディスク上は BFF だが TFF を意図していた(あるいは逆)というケースで field-order を使うと、後段の deinterlace が正しいアルゴリズムを適用できるようにタグが書き換えられる。

実用ユースケース

各レシピは複数の動詞を組み合わせた、実際に使うワークフローだ。

Recipe 1: 縦動画スマホ素材を YouTube 向け 16:9 に

スマホで縦に撮ったクリップ(1080×1920)を、巨大なピラーボックス(左右の黒帯)なしで 16:9 に出したい。backdrop がソースのぼかしコピーで背景を埋め、その上に元動画を重ねる。

bash
# Step 1: 1080x1920 縦 → 1920x1080 ぼかし背景付き
npx fqmpeg backdrop phone-clip.mp4 --blur 25
# → phone-clip-backdrop.mp4 (1920x1080、ぼかし背景+前景動画)

# Step 2 (任意): アップロード用に圧縮
npx fqmpeg compress phone-clip-backdrop.mp4 --crf 23
# → phone-clip-backdrop-compressed.mp4

スマホクリップに残したい動きがあるなら --blur を 10–15 に下げる(背景に動きが出て「動く壁紙」のような効果になる)。逆に --blur を 25–40 にすると背景がほぼ静止して、視聴者の注意が前景に集中する。

Recipe 2: ダウンロード動画から黒帯を剥がす

古いダウンロード素材にはレターボックスが焼き込まれていることが多い。crop-detect で実コンテンツの矩形を見つけ、crop で外側を消す。

bash
# Step 1: クロップ矩形を検出
npx fqmpeg crop-detect movie.mp4
# 探すべき出力: [Parsed_cropdetect_0 @ ...] crop=1920:800:0:140
# (意味: x=0, y=140 から始まる 1920x800 の領域を残す)

# Step 2: 検出されたクロップを適用
npx fqmpeg crop movie.mp4 1920x800 --pos 0:140
# → movie-crop1920x800.mp4

crop-detect は入力全体を読む。出力される値は全フレームを通じて最頻出した検出値だ。ロゴやウォーターマークが冒頭にだけレターボックスされているような素材だと検出がズレることがある — その場合は --limit 30 以上を渡して暗いピクセルを「黒帯」と判定する閾値を上げる。

Recipe 3: 古いインターレース素材を綺麗なプログレッシブ 1080p に修復

古いカムコーダの DV や 1080i キャプチャがあるとして、目標はクリーンなプログレッシブ H.264 でアップロード可能にすること。順番が大事 — リサイズや圧縮の前に必ずデインターレース(圧縮するとコームのパターンがコーデックに焼き込まれる)。

bash
# Step 1: まずデインターレース - 圧縮の前に必ずこれ
npx fqmpeg deinterlace dv-capture.avi --mode bwdif
# → dv-capture-deinterlaced.avi (元の DV 解像度のまま)

# Step 2: 1080 高さにリサイズ(幅は自動でアスペクト維持)
npx fqmpeg resize dv-capture-deinterlaced.avi -h 1080
# → dv-capture-deinterlaced-1080h.avi

# Step 3: 黒帯があれば検出して除去
npx fqmpeg crop-detect dv-capture-deinterlaced-1080h.avi
# 検出された座標を適用:
npx fqmpeg crop dv-capture-deinterlaced-1080h.avi <WxH> --pos <x>:<y>
# → dv-capture-deinterlaced-1080h-crop<WxH>.avi

アーカイブ素材では bwdif のほうが時間をかける価値がある — 「デインターレースのアーティファクトの上に圧縮アーティファクトが乗る」状態を防げて、後でストリーミング向けに再エンコードしたときの劣化が抑えられる。3 つのジオメトリ処理が終わったら compress --crf 20 で仕上げ。

よくある質問

resize が自動側に -1 ではなく -2 を使うのはなぜ?

ほとんどのコーデックが偶数寸法を要求するからだ。-1 は「アスペクト維持」と FFmpeg に伝えるが、結果として 537 のような奇数値が出ることがある。エンコーダがそれを width not divisible by 2 で拒否したらレンダリングが無駄になる。-2 は「アスペクトを維持しつつ偶数に丸める」という意味で、ほぼ常にこちらが欲しい挙動だ。fqmpeg が -2 をハードコードしているのは、このトリップを未然に防ぐため。

pad input.mp4 1920x1080 を 1280×720 のソースにかけたら拡大されたんだけど、なぜ?

pad のフィルタチェインが scale=1920:1080:force_original_aspect_ratio=decrease から始まるからだ。これはソースをアスペクト維持で目標キャンバスにフィットするまで拡大する — 1280×720 のソースなら 1920×1080 にぴったり拡大されてパディングは入らない(同アスペクトだから)。リテラルなパディング(拡大なし)が欲しいなら、--dry-run の出力をコピーして scale=... 部分を削除し、pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=black だけ残す。

zoom が 1920×1080@30 でロックされているのはなぜ?

zoompan フィルタの式の中に s=1920x1080:fps=30 がハードコードされていて、オプションで上書きする手段が露出していない。別の出力サイズや fps が必要な場合は、--dry-run の出力をコピーして s=...:fps=... の値を直接編集する。1080p@60 でズームしたいなら s=1920x1080:fps=60 に書き換える。

ソースにコーミングが見える。deinterlace を実行するのは常に安全?

実際にインターレースされたソースには安全。プログレッシブだが誤ってインターレースとタグ付けされたソース(あるいは逆)に deinterlace をかけると、絵が眠くなりアーティファクトが入ることがある。ffprobe -show_streams input.mp4 | grep field_order でタグを確認し、横方向の動きにコームが目視できるかをチェック。プログレッシブなのにインターレースとタグ付けされているなら、まず field-order でタグを修正してから手を入れる。

crop-detect を最初の 30 秒だけに走らせられる?

fqmpeg からは直接できない — crop-detect は常にファイル全体を読む。回避策は先に trimtrim source.mp4 --start 0 --duration 30 -o probe.mp4)してから crop-detect probe.mp4 を走らせること。長尺のファイルだとこれで何分も節約できる。

aspect --mode padpad 動詞の違いは?

aspect 16:9 --mode pad はソース幅と目標比からキャンバスを導出する(1280×720 のソースなら 1280×720 のキャンバス — もう 16:9 なので何も変わらない。1280×960 のソースなら 1280×720 キャンバス+上下のレターボックス)。一方の独立した pad 1920x1080 はソースアスペクトに関わらず常にリテラルな 1920×1080 にパディングする(必要ならスケールも入る)。「比」を気にするなら aspect、「正確なピクセル寸法」を気にするなら pad

EXIF の向き情報を見て回転させたい

fqmpeg ではできない — どのジオメトリ動詞も回転メタデータを読まない。ただし FFmpeg 自体はトランスコード時に rotate メタデータを尊重するので、compress 等のエンコードを通せば回転タグ付きのソースは縦向きにレンダリングされ直す。明示的に回転タグだけ落としたい(実際に回転はしない)場合は FFmpeg を直接: ffmpeg -i input.mp4 -metadata:s:v:0 rotate=0 -c copy output.mp4

フォルダ全体を一括リサイズしたい

シェルループが標準:

bash
for v in raw/*.mp4; do
  npx fqmpeg resize "$v" -h 720 -o "resized/$(basename "$v" .mp4)-720p.mp4"
done

crop-detect してから crop するバッチは、各ファイルごとの検出結果をキャプチャして反映する必要があるのでワンライナーにはならない。find から while read で回すパターンが定番。

まとめ

C5 の 14 動詞は、典型的な「絵を整える」パスで触る形状操作を一通りカバーする:

  • resize, scale2x で寸法変更(-2 の偶数トリック、super2xsai はピクセルアートやエッジの硬い素材向け)
  • crop, crop-detect で可視領域の切り出し(crop のデフォルト位置は中央、crop-detect は cropdetect フィルタを走らせて推奨座標を表示)
  • pad, aspect, backdrop でキャンバス変更(pad はスケール→パディング、aspect は3モード、backdrop は縦動画→16:9 専用)
  • rotate, transpose, mirror で向き(rotate で 90/180/270/hflip/vflip、transpose --dir 0--dir 3 は回転+反転の合成)
  • zoom で Ken Burns モーション(出力は常に 1920×1080@30 — 別サイズには --dry-run 編集)
  • deinterlace, interlace, field-order でフィールド構造(再エンコード前に deinterlace、誤タグソースの修正に field-order

すべての動詞は --dry-run で生成される FFmpeg コマンドを表示するので、デフォルトが合わない場合(別サイズの zoom、スケールなしのリテラルな pad など)はその出力をコピーして編集→FFmpeg を直接実行できる。fqmpeg 全体の俯瞰は fqmpeg 完全ガイド を参照。