FFmpegが Application provided invalid, non monotonically increasing dts to muxer というエラーで止まる、または大量の警告を出して出力ファイルの再生がガタつく場合は、状況に合わせて4通りの修復コマンドを使い分けます。録画ファイルや配信のダウンロード、複数ファイルの結合を扱うときに起きやすい症状で、原因はどれも タイムスタンプ(PTS/DTS) の不整合です。

エラーの意味と原因

よく出るメッセージ

[mp4 @ 0x...] Application provided invalid, non monotonically increasing dts to muxer in stream 0
Invalid timestamps stream=0, pts=..., dts=..., size=...
[aost#0:1/copy @ 0x...] Non-monotonic DTS; previous: 96256, current: 96000; changing to 96257. This may result in incorrect timestamps in the output file.

PTSとDTSとは

  • PTS(Presentation Time Stamp) … そのフレームを「いつ表示するか」を示す時刻
  • DTS(Decoding Time Stamp) … そのフレームを「いつデコードするか」を示す時刻

muxer(多重化器)は、各ストリームのDTSが 単調増加(monotonically increasing) であること、つまり「前のフレームより必ず時刻が進んでいる」ことを前提に動作します。ここで前のフレームと同じか過去のDTSが渡されると、non monotonically increasing dts エラーになります。

通常の動画では各フレームのタイムスタンプは順に増加していくため、このエラーが出ることはありません。ところが録画の中断やストリームの結合が絡むと、タイムスタンプの並びが乱れたり、欠落した部分を後から補ったときに時刻が前後したりします。muxerはこうした「時間が巻き戻る」入力を整合性の壊れたデータとみなし、エラーや警告を出します。なお dts と表示されていても、根本の原因はPTS側の破損であることも多いため、両者はセットで考えます。

主な原因

原因 説明
VFR(可変フレームレート)ソース それだけでは原因にならない。VFRはフレームの間隔が変わるだけで、タイムスタンプは順に増える
壊れた/不連続なタイムスタンプ TSストリームやダウンロード途中のファイルでPTS/DTSが欠落・巻き戻りを起こす
ファイルのconcat concat demuxerは各ファイルを前のファイルの後ろに並べる。それでもファイル内の映像と音声の始まりや終わりがそろっていないと、つなぎ目でDTSが少し戻ることがある
録画の中断 配信のキャプチャや録画が途中で切れると、末尾のタイムスタンプが破損する
負のタイムスタンプ Bフレームがあると最初のDTSは0より前になる。FFmpegが標準で処理するので、TS→MP4のコピーでは通常オプションは要らない

原因によって「タグを付け直すだけ(-c copy)で直る」のか「フレームを並べ直す=再エンコードが要る」のかが変わります。

解決①genptsで欠けたPTSを補う

フレームそのものは正常で、PTSだけが欠けているとき(Bフレームを含むAVIなど)に最初に試す方法です。-fflags +genpts を付けると、FFmpegが 欠けているPTSをDTSから補います。すでにあるPTSやDTSは変えません。

ffmpeg -fflags +genpts -i input.mp4 -c copy output.mp4
  • -fflags +genpts — 欠けているPTSを生成(generate PTS)するフラグ。入力側に付けるため -i より前に置く
  • -c copy — 映像・音声を再エンコードせずコピー。無劣化かつ高速

最も軽い手段ですが、DTSはそのままなので、non monotonically increasing dts はこれでは直りません。警告が残る場合は次のステップへ進みます。

最初にこれを試すのは、欠けているPTSを補うだけで、映像・音声のデータ本体には手を加えないからです。-c copy と組み合わせれば数秒で終わり、画質も音質も劣化しません。これで直らない場合は、ファイルにすでにあるタイムスタンプの値が間違っています。後述の解決③で再エンコードし、映像のフレームに新しいタイムスタンプを付けます。

注意: -fflags は入力ファイルに対するフラグなので、必ず -i input.mp4 の 前 に書きます。後ろに置くと出力側のフラグと解釈され、効きません。

解決②負のタイムスタンプ補正

タイムスタンプは0から始まるとは限りません。Bフレームがあるとデコードの順番と表示の順番が異なり、最初のフレームを0で表示する前からデコードが始まるため、最初のDTSは 0より前(負の時刻) になります。起点を0へ寄せるのが -avoid_negative_ts make_zero です。

ffmpeg -i input.ts -c copy -avoid_negative_ts make_zero output.mp4
  • -avoid_negative_ts make_zero — 最初のタイムスタンプが0になるよう、全体を同じ量だけシフト する。起点が0より後ろでもシフトする
  • -c copy — 再エンコードなし。タイムスタンプのシフトだけなので無劣化

make_zero は「先頭フレームのタイムスタンプだけを0にする」のではなく、全体を同じ量だけ平行移動します。映像と音声の開始位置の差はそのまま残るので、音ズレは直りません。0になるのは最初のDTSなので、Bフレームがあると0より少し後ろから始まることがあります。

TSをMP4へコピーするだけなら、通常これは要りません。MPEG-TSのタイムスタンプはふつう0より大きい値から始まりますが、FFmpegは標準で各入力の開始位置を0に移します。負の最初のDTSも、FFmpegが自動で処理します。

genpts と合わせて使う

PTSが欠けていて、しかも起点を0にしたい場合は、両方をまとめて指定できます。

ffmpeg -fflags +genpts -i input.ts -c copy -avoid_negative_ts make_zero output.mp4

-fflags +genpts(入力側)で欠けているPTSを補い、-avoid_negative_ts make_zero(出力側)で起点を0へ寄せる、という二段構えです。

解決③固定フレームレートで再エンコード

ここまでの -c copy 系で直らない場合は、ファイルにすでにあるタイムスタンプが間違っていて、コピーではそのまま残ります。固定フレームレートで再エンコード します。VFR(可変フレームレート)だけでは原因になりません。タイムスタンプが正しいVFRのファイルは、コピーしてもこの警告は出ません。

ffmpeg -i input.mp4 -fps_mode cfr -r 30 -c:v libx264 -preset veryfast -c:a aac output.mp4
  • -fps_mode cfr — 出力を CFR(固定フレームレート) にする。フレームを必要に応じて複製・間引きして等間隔に整える
  • -r 30 — 目標フレームレートを30fpsに指定(ソースに合わせて 24 25 60 などへ変更)
  • -c:v libx264 — フレームを並べ直すため映像は再エンコード(コピー不可)
  • -preset veryfast — エンコード速度と品質のバランス
  • -c:a aac — 音声はAACで再エンコード

映像のフレームに一定間隔の新しいタイムスタンプが付くので、映像のDTSは再び順に増えます。VFRを扱えない編集ソフトやプレーヤーにも、同じ変換が役立ちます。

CFR化では、間隔が空いたところにフレームを複製で補い、詰まったところは間引くことで、すべてのフレームを等間隔に並べ直します。目標fpsは、機器の種類ではなく、録画設定と編集ソフトや配信先の指定から選びます。元より高いfpsを指定してもフレームが複製されるだけで、動きは滑らかになりません。低すぎると動きが粗くなります。

古いFFmpegの場合: -fps_mode は比較的新しいオプションです。古いビルドでは利用できないことがあるので、その場合は従来の -vsync cfr を使ってください(ffmpeg -i input.mp4 -vsync cfr -r 30 -c:v libx264 -c:a aac output.mp4)。動作は同等です。

解決④setpts/asetptsでリセット

「先頭の時刻が0から始まっていない」「切り出しや結合で時刻がずれた」場合に、タイムスタンプを先頭0起点へ揃え直す フィルタが setpts / asetpts です。

ffmpeg -i input.mp4 -vf setpts=PTS-STARTPTS -af asetpts=PTS-STARTPTS -c:v libx264 -c:a aac output.mp4
  • -vf setpts=PTS-STARTPTS — 映像の各フレームから先頭PTS(STARTPTS)を引き、先頭を0にリセット
  • -af asetpts=PTS-STARTPTS — 音声側で同じ処理を行う(a 付きが音声用)
  • -c:v libx264 / -c:a aac — setpts/asetpts は フィルタ なので、適用には再エンコードが必須

setpts は映像フィルタ、asetpts は音声フィルタで、ペアで指定します。それぞれが自分のストリームを0から始まるように動かすので、入力で映像と音声の開始位置がずれていると、その差がなくなり、同じ量だけ音ズレが変わります。genpts が「欠けているPTSだけを補う」のに対し、setpts=PTS-STARTPTS は「既存の値はそのまま、原点だけを0へ平行移動する」点が違いです。

-c copyで直る場合と再エンコードが要る場合

修復コマンドを選ぶときは、まず 再エンコードが必要かどうか を見極めます。

状況 適切な対処 再エンコード
PTSが欠けている -fflags +genpts + -c copy 不要
先頭が負のタイムスタンプ -avoid_negative_ts make_zero + -c copy 不要
コピー系で直らない、または編集ソフトがCFRを要求する -fps_mode cfr -r N(libx264等で再圧縮) 必要
先頭を0起点に揃え直したい setpts=PTS-STARTPTS / asetpts=PTS-STARTPTS 必要(フィルタのため)

判断の順番は次のとおりです。

  1. まず -c copy で軽く試す(genpts、avoid_negative_ts)。これで直れば無劣化・高速で終わる
  2. それでも警告が消えない、再生が不安定なら -fps_mode cfr で再エンコード
  3. 切り出し・結合後に時刻がずれているだけなら setpts/asetpts でリセット

-c copy はビット列をそのままコピーして コンテナのタグだけを書き換える ため画質劣化ゼロですが、フレームの並びそのものは変えられません。フレームの間引き・複製・並べ直しが要るVFR→CFR化やフィルタ適用は、原理上 copy では実現できず再エンコードが必要になります。

テスト済みバージョン / 対象OS

対象OS: Ubuntu 24.04 / macOS / Windows(コマンドは共通)
-fps_mode が使えない古いビルドでは -vsync cfr で代替できます。

よくある質問(FAQ)

Q1. -fflags +genpts を付けても警告が消えません

genpts は欠けているPTSを補うだけで、DTSは変えないため、逆行したDTSは直せません。-fps_mode cfr -r 30(解決③)で再エンコードし、映像のフレームに新しいタイムスタンプを付けてください。なお -fflags は入力フラグなので、-i の 前 に置いているかも確認してください。

Q2. -avoid_negative_ts make_zero と setpts=PTS-STARTPTS はどう違いますか

-avoid_negative_ts make_zero は コンテナ(muxer)レベル でタイムスタンプの起点を0へ寄せる出力オプションで、-c copy のまま使えます。setpts=PTS-STARTPTS は フィルタ で各フレームのPTSを書き換えるため再エンコードが必要です。まずは軽い avoid_negative_ts を試し、フィルタチェーンの一部として0起点化したいときに setpts を使う、という使い分けが基本です。

Q3. concatで結合したら non monotonically increasing dts が出ます

よくある症状です。concat demuxer は各ファイルを前のファイルの後ろに並べますが、次のファイルの音声が映像より少し前から始まっている場合などに、つなぎ目でDTSが少し戻ることがあります。-fflags +genpts はDTSを変えないので効きません。-c copy の代わりに -c:v libx264 -c:a aac で再エンコードしながら結合すると、たいてい出なくなります。結合の手順は関連記事「複数の動画を連結する」を参照してください。

Q4. -fps_mode というオプションが存在しないと言われます

お使いのFFmpegが古い可能性があります。-fps_mode は比較的新しいオプション名で、それ以前は -vsync が同じ役割を担っていました。-fps_mode cfr を -vsync cfr に置き換えて実行してください。ffmpeg -version でバージョンを確認し、できれば新しいビルドに更新してください。

関連記事