動画コンテンツの切り抜き(トリミング)作業において、Adobe Premiere Pro や DaVinci Resolve といった NLE(非線形編集ソフト)を立ち上げるのは、往々にしてオーバーエンジニアリングだ。単純なカット作業にちょっとした起動時間と、実時間以上のエンコード時間を費やす必要はない。
FFmpeg の「ストリームコピー機能」を活用すれば、ギガバイト級の 4K 動画であっても、わずか数秒で、かつ1 ビットの画質劣化もなく必要なシーンだけを抽出できる。
ffmpeg -y -ss 00:01:30 -to 00:05:30 -i "input.mp4" -c copy "output.mp4"
実戦用スクリプト
再エンコード(画質の変換処理)を行わず、データコピーのみで完了する最速のコマンドだ。
Windows (PowerShell)
# 変数定義
$InputVideo = "input.mp4"
$OutputVideo = "output_cut.mp4"
$StartTime = "00:01:30" # 開始時刻 (HH:MM:SS)
$EndTime = "00:01:40" # 終了時刻 (HH:MM:SS)
# コマンド実行
# -ss : 開始時刻へシーク
# -to : 終了時刻を指定(-t なら「長さ」指定)
# -c copy : 再エンコードせずストリームを複製
ffmpeg -y -ss $StartTime -to $EndTime -i "$InputVideo" -c copy "$OutputVideo"
macOS / Linux (Bash)
#!/bin/bash
INPUT="input.mp4"
OUTPUT="output_cut.mp4"
START="00:01:30" # 開始時刻
END="00:01:40" # 終了時刻
# Input Seeking (-ss を -i の前に配置) により高速シークを実現
ffmpeg -y -ss "$START" -to "$END" -i "$INPUT" -c copy "$OUTPUT"
技術解説:Stream Copy の内部ロジックとトレードオフ
提示したコマンドの核となるのは -c copy(または -c:v copy -c:a copy)オプションだ。
1. デコード/エンコードのバイパス
通常の動画編集は「デコード(解凍)→ 画像処理 → エンコード(再圧縮)」というプロセスを経る。これが画質劣化と処理遅延の主原因だ。
-c copy は、コンテナ(MP4 や MKV)から取り出したエンコード済みのパケットを、デコードせずにそのまま新しいコンテナへ格納する(Demux → Mux)。計算負荷はディスク I/O 速度にほぼ依存するため、CPU 使用率は極めて低く、処理は一瞬で完了する。
具体的な速度感:
- 10GB の 4K 動画(2時間)から 10 秒を切り出す場合、再エンコードなら数分かかる
-c copyなら1〜2 秒で完了する
2. シーク位置と Input Seeking
コマンド内の -ss を -i の前に配置している点に注目してほしい。
- Input Seeking(
-ssを-iの前に配置): 入力ファイルを読み込む段階で、指定時刻のパケット位置までファイルポインタを移動させる。デコード処理をスキップするため爆速だが、後述するキーフレームの制約を受ける。 - Output Seeking(
-ssを-iの後に配置): ファイルを先頭からデコードしながら指定位置まで進む。正確だが、-c copyと組み合わせると挙動が不安定になるため、無劣化カットでは使わない。
3. キーフレーム(I-frame)の制約
無劣化カットには技術的に避けられないトレードオフが存在する。 「カット地点がキーフレームにスナップされる」 という点だ。
GOP 構造の仕組み:
現代の動画コーデック(H.264、H.265、AV1)は、GOP(Group of Pictures)という単位で圧縮されている。GOP は完全な画像情報を持つ「I フレーム(キーフレーム)」から始まり、差分情報しか持たない「P/B フレーム」が続く。
スナップ挙動:
-c copy では P/B フレーム単体では映像を復元できないため、指定した時刻(例: 00:01:30)の直前にある最も近い I フレームまで自動的に開始位置が巻き戻される。
例えば、GOP 長が 5 秒の動画で 00:01:30 からカットしようとした場合:
- 実際の開始位置:
00:01:27(最寄りの I フレーム) - ズレ: 最大で GOP 長分(数秒〜10 秒程度)
結論: 無劣化カットは「秒単位の厳密な編集」には向かない。「大体このあたり」を切り抜く用途に特化しており、開始地点が最大で数秒ズレる可能性があることを許容する必要がある。1 フレーム単位の精度が必要な場合は、-c copy を諦めて再エンコードを選択する。
トラブルシューティング
切り抜いた動画の最初が真っ暗になる、または止まる
プレーヤーの互換性問題だ。無理やり P フレームから開始されたデータになっている可能性がある。Input Seeking(-ss を -i の前に配置)を使用していれば FFmpeg が自動的に直前のキーフレームを拾うが、再生ソフトによってはその余分な数秒をうまく処理できない場合がある。
解決策: より多くのデコーダーと互換性のある出力にするため、わずかに再エンコードする。
# 映像のみ再エンコード(音声はコピー)
ffmpeg -ss 00:01:30 -to 00:05:30 -i input.mp4 \
-c:v libx264 -preset fast -crf 23 \
-c:a copy \
output.mp4
-t と -to の違いは?
-t 10: 開始地点から「10 秒間」切り抜く(Duration 指定)-to 00:01:40: 動画のタイムスタンプで「1 分 40 秒」の地点まで切り抜く(End Time 指定)
「ここからここまで」を指定したい場合は -to が直感的だ。
注意: -ss を -i の前に置いた場合(Input Seeking)、-to は入力ファイルの絶対タイムスタンプを参照する。例えば -ss 00:01:30 -to 00:05:30 と指定した場合、1分30秒から5分30秒までが切り出される(開始地点からの相対時刻ではない)。
音声と映像がずれる
-c copy では音声と映像のタイムスタンプをそのままコピーするため、カット位置によってはわずかなズレが生じることがある。
解決策: -avoid_negative_ts make_zero オプションを追加する。
ffmpeg -ss 00:01:30 -to 00:05:30 -i input.mp4 \
-c copy \
-avoid_negative_ts make_zero \
output.mp4
バッチ処理への応用
複数の動画を一括でカットしたい場合のスクリプト例だ。
Bash でのバッチカット:
#!/bin/bash
# CSVファイル形式: 入力ファイル,開始時間,終了時間,出力ファイル
# clips.csv:
# video1.mp4,00:01:30,00:05:00,clip1.mp4
# video2.mp4,00:00:10,00:02:30,clip2.mp4
while IFS=',' read -r input start end output; do
ffmpeg -y -ss "$start" -to "$end" -i "$input" -c copy "$output"
echo "完了: $output"
done < clips.csv
PowerShell でのバッチカット:
# clips.csv の各行を処理
Import-Csv -Path "clips.csv" -Header "Input","Start","End","Output" | ForEach-Object {
ffmpeg -y -ss $_.Start -to $_.End -i $_.Input -c copy $_.Output
Write-Host "完了: $($_.Output)"
}
まとめ
動画の「無劣化カット」は、画質の維持と作業効率の最大化において最強のアプローチだ。
| 目的 | 推奨手法 |
|---|---|
| 大体の位置でカット(数秒のズレ許容) | -c copy(本記事の方法) |
| 厳密な時刻でカット(フレーム精度) | -c:v libx264 -preset fast などで再エンコード |
| 大量ファイルのバッチカット | スクリプト化 + -c copy |
FFmpeg の -c copy を使いこなすことは、動画データを「映像」としてではなく「パケットの塊」として扱うエンジニアリングの第一歩だ。SNS へのシェアや、会議録画のアーカイブ整理など、厳密な精度よりもスピードが求められるシーンで、このコマンドは圧倒的なパフォーマンスを発揮する。