ffmpeg-cut-concat
ffmpegを使用して、メディアのトリミング、カット、分割、セグメント化、結合を実行します(可能な限りストリームコピーを使用し、カット境界では再エンコード)。ユーザーがビデオのトリミング、クリップのカット、タイムスタンプによるセグメント抽出、セクションの削除、ファイルの分割、ビデオの結合・マージ、ファイルの連結、またはセグメント化されたHLSスタイルのプレイリスト構築を依頼した場合に使用します。
description の原文を見る
Trim, cut, split, segment, and concatenate media with ffmpeg (stream copy when possible, re-encode across cut boundaries). Use when the user asks to trim a video, cut a clip, extract a segment by timestamps, remove a section, split into parts, join/merge videos, concatenate files, or build a segmented HLS-style playlist.
SKILL.md 本文
Ffmpeg Cut Concat
コンテキスト: $ARGUMENTS
クイックスタート
- 高速トリミング(キーフレーム配置済み): → ステップ1 → トリムモード(
-c copy使用) - フレーム精度トリミング: → ステップ1 → トリムモード、再エンコード(
--accurate使用) - 1つのファイルをN個に分割: → ステップ1 → セグメントモード
- 同一コーデックのファイルを結合: → ステップ1 → concat-copyモード
- 異なるコーデックのファイルを結合: → ステップ1 → concat-filterモード
使用する場面
- 2つのタイムスタンプ間からクリップを抽出する場合(例:
00:01:30から00:02:00) - 長いファイルをN秒のチャンクに分割する場合(ポッドキャスト、HLS準備)
- 複数の録画をエンドツーエンドで結合する場合
- 動画の最初/最後のN秒を削除する場合
- 複数のソースファイルからハイライトリールを作成する場合
ステップ1 — 戦略の選択
| 目的 | モード | コマンドスケルトン |
|---|---|---|
| 1つのファイルから1つのクリップをトリミング | trim | ffmpeg -ss T1 -i in -to T2 -c copy out |
| 1つのファイルを等しいサイズの部分に分割 | segment | ffmpeg -i in -f segment -segment_time N out_%03d.mp4 |
| 同じコーデックのファイルを結合 | concat-copy | ffmpeg -f concat -safe 0 -i list.txt -c copy out |
| コーデックが異なるファイルを結合 | concat-filter | -filter_complex "concat=n=N:v=1:a=1" |
コーデック、解像度、SAR、フレームレート、またはサンプルレートが異なるファイルにはconcat デマルチプレクサを使用しないでください。マックスされますがサイレント再生が中断されます。代わりに concat フィルタを使用してください。
ステップ2 — ストリームコピーと再エンコードの選択
- ストリームコピー(
-c copy) は約100倍高速でロスレスですが、カットは要求されたタイムスタンプの直前の最も近いキーフレームで行われます。00:01:30.000でのクリップ要求は実際には00:01:28.5で開始するかもしれません。 - 再エンコード(
-c copyを削除し、-c:v libx264 -c:a aacを追加)はフレーム精度ですが遅くロッシーです。 - デフォルトルール:
−c copyで開始します。ユーザーが「フレーム精度」「正確」と言う場合、またはテスト後に最初のフレームが間違っている場合のみ再エンコードに切り替えます。
入力サイドと出力サイドのシーク:
-ss T -i in.mp4(-iの前) — 入力シーク。高速。ffmpeg はコンテナ内のT以前のキーフレームへシークし、デコード開始します。-c copyでは、出力はそのキーフレームから開始されます。-i in.mp4 -ss T(-iの後) — 出力シーク。開始からデコードし、T までのフレームを破棄します。遅いですが正確です。最新のffmpeg はデフォルトで-accurate_seekを使用して正確な入力シークを実行するため、ほとんど不要です。
再エンコードでの正確なカットには入力シークも使用してください。デコード開始後は高速かつ正確です。
ステップ3 — コマンドの実行
3a. トリミング(ストリームコピー、キーフレーム配置)
ffmpeg -ss 00:01:30 -i input.mp4 -to 00:02:00 -c copy -avoid_negative_ts make_zero out.mp4
-to は絶対入力時間です。-ss 00:01:30 -to 00:02:00 と記述した場合、30秒の出力が得られます。
持続時間を直接指定するには、-to の代わりに -t 30 を使用してください(両方が設定されている場合は -t が優先されます)。
3b. トリミング(フレーム精度、再エンコード)
ffmpeg -ss 00:01:30 -i input.mp4 -to 00:02:00 \
-c:v libx264 -crf 18 -preset veryfast \
-c:a aac -b:a 192k \
out.mp4
3c. セグメント化(N秒の部分に分割)
ffmpeg -i input.mp4 -c copy -map 0 \
-f segment -segment_time 60 -reset_timestamps 1 \
out_%03d.mp4
セグメントはキーフレームで分割されます。正確に60.000秒の部分が必要な場合は、強制キーフレームで再エンコードしてください:-force_key_frames "expr:gte(t,n_forced*60)"。
3d. Concat デマルチプレクサ(同じコーデック パラメータ)
list.txt を作成します:
file 'clip1.mp4'
file 'clip2.mp4'
file 'clip3.mp4'
実行します:
ffmpeg -f concat -safe 0 -i list.txt -c copy out.mp4
-safe 0 は絶対パスと .. を許可します。CWD 内の通常のファイル名以外で必要です。
3e. Concat フィルタ(異なるコーデック/解像度)
ffmpeg -i a.mp4 -i b.mp4 -i c.mp4 \
-filter_complex "[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" \
-c:v libx264 -crf 18 -c:a aac -b:a 192k \
out.mp4
各入力は v ビデオストリームと a オーディオストリームを提供します。i=0..n-1 の順序で [i:v][i:a] として参照してください。
ステップ4 — 期間の確認
ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 out.mp4
ストリームコピーの場合、報告される期間は、キーフレーム配置のため、要求された期間よりも少し短いか長いかもしれません。不一致が約2秒以上ある場合、GOP サイズが大きいため再エンコードしてください。
利用可能なスクリプト
scripts/cut.py—--dry-runと--verboseを備えた4つのモード(trim、segment、concat-copy、concat-filter)の単一エントリポイント。
ワークフロー
# 高速トリミング
uv run ${CLAUDE_SKILL_DIR}/scripts/cut.py trim \
--input in.mp4 --start 00:01:30 --end 00:02:00 --output clip.mp4
# フレーム精度
uv run ${CLAUDE_SKILL_DIR}/scripts/cut.py trim \
--input in.mp4 --start 00:01:30 --end 00:02:00 --accurate --output clip.mp4
# 60秒チャンクに分割
uv run ${CLAUDE_SKILL_DIR}/scripts/cut.py segment \
--input in.mp4 --seconds 60 --pattern out_%03d.mp4
# 同じコーデックのファイルを連結
uv run ${CLAUDE_SKILL_DIR}/scripts/cut.py concat-copy \
--inputs a.mp4 b.mp4 c.mp4 --output joined.mp4
# 混合コーデックのファイルを連結(再エンコード)
uv run ${CLAUDE_SKILL_DIR}/scripts/cut.py concat-filter \
--inputs a.mp4 b.webm --output joined.mp4
リファレンスドキュメント
references/patterns.mdを読んで、正確なlist.txtエスケープルール、2パス-ssレシピ、-copytsマックス精度カット、および ffprobe によるキーフレーム検査を確認してください。
よくある落とし穴
- Concat デマルチプレクサはミスマッチについてサイレントです。 ファイルは同じコーデック、解像度、SAR、ピクセルフォーマット、フレームレート、サンプルレート、チャネルレイアウトを備えている必要があります。そうでない場合、出力は不正に再生されます(フリーズした動画、オーディオ非同期)警告なし。最初にプローブしてください:
ffprobe -v error -show_streams a.mp4 b.mp4コーデック/fps/sar フィールドを diff してください。 -safe 0は必須です 絶対パスまたは..を持つ連結リストエントリの場合。これがないとUnsafe file nameが表示されます。- list.txt でのシングルクォートエスケープ。 各パスは
'...'で囲まれています。リテラル'を含めるには、クォートを閉じ、バックスラッシュエスケープし、再度開きます:file 'it'\''s.mp4'。 - 入力シーク +
-c copyは負のタイムスタンプを生成できます。 最初のパケットの PTS はカット ポイントより前の場合があります。-avoid_negative_ts make_zeroを追加してください。プレイヤーが最初の1秒が空白になる場合があります。 - ストリームコピー トリミングはキーフレームで開始されます。
00:01:30を要求しましたが、最も近い前のキーフレームが00:01:28.5にある場合、出力は00:01:28.5で開始されます。正確にスナップするには再エンコードしてください。 -toは絶対、-tは持続時間です。-ss 60 -to 90= 30秒クリップ。-ss 60 -t 90= 90秒クリップ。それらを混ぜると、1つのフォームを暗記した人は混乱します。- Concat フィルタは入力ごとに一致するストリーム数が必要です。
concat=n=3:v=1:a=1は[0:v][0:a][1:v][1:a][2:v][2:a]を想定しています。サイレント入力にはanullsrcダミーまたはa=0が必要です。 - ロスレスカットはキーフレームでのみ機能します。
ffprobe -select_streams v -show_frames -skip_frame nokey -show_entries frame=pkt_pts_timeを実行してそれらを見つけてください。 -ssの位置が一部のフォーマット(特にraw/TS)で-iの前 シークは不正確です。クリップが間違った場所で開始される場合、-ssを-iの後に移動して、デコードベースのシークを強制します。
例
例1: 30秒クリップを高速カット
ffmpeg -ss 00:01:30 -i lecture.mp4 -to 00:02:00 \
-c copy -avoid_negative_ts make_zero \
highlight.mp4
例2: 最初の10秒を削除、フレーム精度
ffmpeg -ss 10 -i raw.mov \
-c:v libx264 -crf 18 -preset veryfast -c:a aac -b:a 192k \
trimmed.mp4
例3: ポッドキャストを10分チャンクに分割
ffmpeg -i podcast.m4a -c copy -f segment -segment_time 600 \
-reset_timestamps 1 part_%02d.m4a
例4: 3つの同じ形式のクリップを結合
cat > list.txt <<'EOF'
file 'intro.mp4'
file 'main.mp4'
file 'outro.mp4'
EOF
ffmpeg -f concat -safe 0 -i list.txt -c copy final.mp4
例5: 1080p mp4 と 720p webm をマージ
ffmpeg -i a.mp4 -i b.webm \
-filter_complex "[0:v]scale=1280:720,setsar=1[v0];[1:v]setsar=1[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" -c:v libx264 -crf 20 -c:a aac mix.mp4
トラブルシューティング
エラー: Unsafe file name
原因: -safe 0 なしで、CWD の外のパスを拒否する concat デマルチプレクサ。
解決策: -i list.txt の前に -safe 0 を追加するか、CWD に相対的なファイル名を使用します。
出力が要求された -ss より前で開始される、または最初のフレームが黒い
原因: -c copy によるキーフレーム配置 + 負の初期 PTS。
解決策: -avoid_negative_ts make_zero を追加してください。正確な開始では、-c copy を削除して再エンコードしてください。
Concat デマルチプレクサ出力がフリーズ動画またはオーディオ非同期である
原因: 入力ファイルがコーデック/解像度/fps/sar/サンプルレートで異なります。
解決策: それらをプローブしてください(ffprobe -show_streams)、ミスマッチを確認し、再エンコードで concat フィルタに切り替えるか、-c:v libx264 -vf "scale=W:H,fps=F,setsar=1" -ar 48000 -ac 2 で最初に入力を正規化してください。
Stream specifier ':a' matches no streams
原因: 1つの入力にオーディオトラックがないが、concat フィルタは a=1 を想定しています。
解決策: そのセルフのためのサイレンスを生成するか(-f lavfi -i anullsrc=cl=stereo:r=48000)、a=0 を設定し、オーディオを別に処理します。
-segment_time 60 にもかかわらずセグメントが不均等な長さ
原因: セグメンタはキーフレームでのみ分割されます。GOP が60秒より長いまたは不規則です。
解決策: -force_key_frames "expr:gte(t,n_forced*60)" で再エンコードしてからセグメント化します(または同じパスで)。
[concat @ ...] DTS ... < ... out of order
原因: 連結時の重複または減少するタイムスタンプ。
解決策: -fflags +genpts を -i list.txt の前に追加するか、最初に各入力を -c copy を通じて再マックスしてタイムスタンプを正規化します。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- damionrashford
- ライセンス
- MIT
- 最終更新
- 2026/5/9
Source: https://github.com/damionrashford/media-os / ライセンス: MIT