ffmpeg のコマンド

(2025-02-06)

ffmpeg はとても便利なものですが、コマンドが難しく覚えられません。 使うものをいくつか記録しておきます。

動画を一定時間切り取る

再生 15 秒後から 10 秒間を切り取ります。

ffmpeg -ss 00:00:15 -i input.mp4 -t 10 output.mp4

でも、長い動画だととても時間がかかります。 そういう場合は、開始と終了を指定してやれば一瞬で終了します。

ffmpeg -i input.mp4 -ss 00:00:34 -to 00:00:47 -c copy output.mp4

でも、このコードでも思い通りにカットできないことがあります。

chatGPT に質問すると、

-c copy は再エンコードせずにフレームをそのままコピーします。
動画は**キーフレーム(Iフレーム)**を基準に再生されます。
キーフレーム以外のフレーム(Pフレーム、Bフレーム)は前後のフレームに依存するため、
キーフレームのない場所から切ると、ffmpegはその前のキーフレームから出力を始めてしまいます。
そのため「17秒から始めたい」としても、実際は 直前のキーフレーム時刻から切れてしまい、ずれが発生します。

いや、そんな少しのズレではないんですけどね。

そして、以下のようなコードを提示してきました。

ffmpeg -ss 00:00:17 -to 00:00:25 -i input.mp4 -c copy output.mp4

以前のコードと似ていますが、-ss の位置などが違います。
以前のコードだと、場合によっては 1 秒にも満たないことがあり間違いだったことがわかりました。

ざっくり処理するならこれが最速だと思います。

動画の音声レベルを編集

基本構文は、

ffmpeg -i input.mp4 -af "volume=1.5" output.mp4
  1. volume=1.5 → 音量を1.5倍にする(+50%)
  2. volume=0.5 → 音量を0.5倍にする(-50%)

dB(デシベル)で調整するのは、

ffmpeg -i input.mp4 -af "volume=5dB" output.mp4
  1. volume=5dB → 音量を約1.78倍(+5デシベル)
  2. volume=-10dB → 音量を小さくする(-10デシベル)

動画→静止画

再生 5 秒後から 0.1 秒間の静止画を作成。

#!/bin/sh
mkdir -p after
for ext in mkv mp4 webm; do
for file in before/*."$ext"; do
[ -f "$file" ] || continue
basename=$(basename "$file")
name="${basename%.*}" # 拡張子除去
ffmpeg -y -ss 2 -i "$file" -frames:v 1 "after/${name}.jpg"
done
done

動画のクロップ

動画のある部分を切り取ります。

ffmpeg -i aaa.MP4 -vf crop=w=294:h=471:x=885:y=585 output.mp4

動画のサイズ変更

大きなサイズの動画を小さくしたいことがあります。

まずは、動画の解像度などを取得します。

ffprobe -v error -show_entries stream=width,height,duration -of default=noprint_wrappers=1 input.mp4

input.mp4 の解像度を 1280✕720 に変更します。

ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4

アスペクト比をそのままにして変更する場合には、

ffmpeg -i input.mp4 -vf scale=640:-1 output.mp4

品質を保つためのオプション。

ffmpeg -i input.mp4 -vf scale=640:-1 -c:v libx264 -crf 23 -preset fast output.mp4

(-crf は画質(0〜51、小さいほど高画質、23がデフォルト)-preset はエンコード速度(ultrafast, fast, slow, veryslowなど))

safari などで閲覧可能な動画へ一括変換

#!/bin/sh
for file in `find ./before -name "*.mp4"`; do
faname_ext="${file##*/}"
fname="${faname_ext%.*}"
echo $fname
ffmpeg -i $file -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" ./after/$fname.mp4
ffmpeg -i $file -ss 1 -t 1 -r 1 -f image2 ./after/$fname.png
done