FFmpeg エッセンシャル
常に最初にプローブを行い、入力ファイルを上書きせず、特に指示がない限りカット時には再エンコードしてください。
プローブ
# 人間向けサマリ
ffprobe -v error -show_entries stream=codec_type,codec_name,width,height,r_frame_rate,sample_rate -show_entries format=duration,size -of default=nw=1 input.mp4
# 機械可読
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
トリミング
# 30秒から開始、15秒間保持。再エンコード:正確で安全。
ffmpeg -i input.mp4 -ss 00:00:30 -t 15 -c:v libx264 -crf 20 -c:a aac out/clip.mp4
# 高速、再エンコードなし。キーフレームの位置にしか合わせられないため、開始位置が数秒ずれる可能性あり。
ffmpeg -ss 00:00:30 -i input.mp4 -t 15 -c copy out/clip.mp4
-ss を -i の前に置くと高速シーク。後ろに置くと正確だが低速。最近の FFmpeg では再エンコード時はどちらでも問題ありません。
結合
# 同じコーデック、解像度、フレームレートの場合:即時、ロスレス
printf "file 'a.mp4'\nfile 'b.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy out/joined.mp4
# 異なるソース:結合時に正規化
ffmpeg -i a.mp4 -i b.mp4 -filter_complex \
"[0:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,fps=30,setsar=1[v0];\
[1:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,fps=30,setsar=1[v1];\
[0:a][1:a]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" -c:v libx264 -crf 20 -c:a aac out/joined.mp4
PowerShell では Set-Content で list.txt を作成し、バックティック行継続または1行で記述してください(\ は使えません)。
リサイズとフレーム変更
# 1920x1080 内に収め、余白を追加
-vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2"
# 1920x1080 を埋め、はみ出し部分をクロップ
-vf "scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080"
# 幅 1280、高さは自動で偶数に
-vf "scale=1280:-2"
圧縮
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k -movflags +faststart out/small.mp4
| 用途 | CRF | プリセット |
|---|---|---|
| マスター / アーカイブ | 16-18 | slow |
| プロダクション | 20-22 | medium |
| Web / プレビュー | 23-26 | fast |
| クイック下書き | 28+ | veryfast |
CRF が低いほど高品質・大容量になります。特定のファイルサイズにしたい場合は、CRF の代わりに2パス -b:v を使用してください。
速度変更
# 2倍速、映像と音声
ffmpeg -i in.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" out/fast.mp4
# 0.5倍スローモーション
ffmpeg -i in.mp4 -filter_complex "[0:v]setpts=2.0*PTS[v];[0:a]atempo=0.5[a]" -map "[v]" -map "[a]" out/slow.mp4
# 映像のみ
ffmpeg -i in.mp4 -an -filter:v "setpts=0.25*PTS" out/timelapse.mp4
setpts の倍数 = 1 / 再生速度。atempo は1フィルタあたり 0.5~2.0 まで対応。さらに高速にするにはチェーン:atempo=2.0,atempo=2.0 で 4倍速。
フェード
# 10秒のクリップに1秒のイン、1秒のアウト
ffmpeg -i in.mp4 -vf "fade=t=in:st=0:d=1,fade=t=out:st=9:d=1" -af "afade=t=in:st=0:d=1,afade=t=out:st=9:d=1" out/faded.mp4
音声
ffmpeg -i in.mp4 -vn -c:a libmp3lame -q:a 2 out/audio.mp3 # mp3 抽出
ffmpeg -i in.mp4 -vn -c:a copy out/audio.m4a # 再エンコードせず抽出(AAC ソース)
ffmpeg -i video.mp4 -i voice.wav -map 0:v -map 1:a -c:v copy -c:a aac -shortest out/dubbed.mp4 # 音声置換
ffmpeg -i in.mp4 -an -c:v copy out/silent.mp4 # 音声削除
GIF
ffmpeg -i in.mp4 -t 5 -vf "fps=15,scale=480:-1:flags=lanczos,split[a][b];[a]palettegen[p];[b][p]paletteuse" out/preview.gif
静止画
ffmpeg -ss 5 -i in.mp4 -frames:v 1 -q:v 2 out/frame.jpg # 1フレーム
ffmpeg -framerate 30 -i frames/%04d.png -c:v libx264 -pix_fmt yuv420p out/from-frames.mp4
ffmpeg -loop 1 -i still.png -t 5 -c:v libx264 -pix_fmt yuv420p -r 30 out/still.mp4
トラブルシューティング
| 症状 | 修正方法 |
|---|---|
height not divisible by 2 | scale=trunc(iw/2)*2:trunc(ih/2)*2 を追加 |
| VLC では再生できるが、ブラウザやスマホで再生できない | -c:v libx264 -pix_fmt yuv420p -movflags +faststart |
| 速度変更後に音声がずれる | setpts と atempo を filter_complex 内で一緒に使用 |
| 可変フレームレートのスマホクリップで音声がずれる | -vsync cfr -r 30(または -fps_mode cfr)を追加 |
-c copy トリミング後、最初のフレームが黒い | ストリームコピーではなく再エンコード |
| 出力が 0 バイト | -v error でエラー全文を確認。ストリームマッピングをチェック |
| パスにスペースがある | 引用符で囲む:"my clip.mp4" |
| 上書き確認プロンプトが自動化を妨げる | -y(上書き)または -n(しない)を追加 |
安全な習慣
out/に書き出し、入力パスには決して書き込まない。- スクリプトでは
-hide_banner -loglevel errorを追加、-statsで進捗表示。 - 結果は
ffprobeとvideo-qaスキルで確認する。