録画ファイルや配信のダウンロード、複数ファイルの結合を扱っていると、FFmpegが突然 Application provided invalid, non monotonically increasing dts to muxer というエラーを吐いて止まる、あるいは大量に警告を出しながら出力ファイルの再生がガタつく――そんな経験はないでしょうか。これらはすべて タイムスタンプ(PTS/DTS) の不整合が原因です。本記事ではエラーの意味を整理したうえで、状況別に4通りの修復コマンドを紹介します。

動作確認: ffmpeg 6.1 で確認済み


この記事でわかること

  • non monotonically increasing dts / invalid PTS/DTS というメッセージが 何を意味しているのか
  • タイムスタンプが壊れる 典型的な原因(VFRソース、不連続なタイムスタンプ、concat、録画中断など)
  • 状況別の 4つの修復アプローチ
    • -fflags +genpts でタイムスタンプを再生成
    • -avoid_negative_ts make_zero で負のタイムスタンプを0起点に補正
    • -fps_mode cfr でVFR(可変フレームレート)をCFR(固定)化
    • setpts / asetpts で先頭を0に揃える
  • -c copy で直るケース(タグの付け直しだけで済む)と 再エンコードが必要なケース(VFR→CFRなど)の見分け方

エラーの意味と原因

よく出るメッセージ

[mp4 @ 0x...] Application provided invalid, non monotonically increasing dts to muxer in stream 0
Invalid timestamps stream=0, pts=..., dts=..., size=...
Non-monotonous DTS in output stream 0:0; previous: ..., current: ...; changing to ...

PTSとDTSとは

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

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

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

主な原因

原因説明
VFR(可変フレームレート)ソーススマホ録画・画面キャプチャ・ゲーム配信などはフレーム間隔が一定でない。muxerが想定するタイムスタンプとずれやすい
壊れた/不連続なタイムスタンプTSストリームやダウンロード途中のファイルでPTS/DTSが欠落・巻き戻りを起こす
異なるストリームのconcat別々に録画したファイルをそのまま連結すると、2本目の先頭が0付近に戻り過去のDTSになる
録画の中断配信のキャプチャや録画が途中で切れると、末尾のタイムスタンプが破損する
負のタイムスタンプTS→MP4変換などで先頭が負の時刻から始まり、muxerが嫌う

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


解決①genptsで再生成

PTS/DTSが欠落・破損しているだけで、フレームそのものは正常なケースで第一に試す方法です。-fflags +genpts を付けると、FFmpegが 欠落・破損したPTSをフレームレートやコンテナ情報から推定して再生成 します。

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

これは多くの non monotonically increasing dts を、再エンコードなしで解消できる最も軽い手段です。まずこれを試して、それでも警告が残る場合に次のステップへ進みます。

なぜ最初にこれを試すべきかというと、再生成はコンテナのタイムスタンプ情報を作り直すだけで、映像・音声のデータ本体には一切手を加えないからです。-c copy と組み合わせれば数秒で完了し、画質も音質もまったく劣化しません。ダウンロードしたTSや配信のキャプチャなど「中身は無事だがタイムスタンプ情報だけが怪しい」ファイルの大半は、この一手で問題なく再生できるようになります。逆に言えば、これで直らない場合はタイムスタンプの「値」ではなく「フレームの並びそのもの」に問題があるサインなので、後述のVFR→CFR化へ進む判断材料になります。

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


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

.ts(MPEG-TS)ファイルをMP4などに変換するとき、ストリームの先頭が 負の時刻 から始まっていると、muxerが弾いたり再生開始位置がずれたりします。これを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になるよう全体をシフト する
  • -c copy — 再エンコードなし。タイムスタンプのシフトだけなので無劣化

make_zero は「先頭フレームのタイムスタンプを0にする」のではなく「最も小さいタイムスタンプを0に合わせて全体を平行移動する」挙動です。TSからの変換でA/Vの頭がずれる、頭が欠けるといった症状に効きます。

MPEG-TSは放送波やストリーミングを想定した形式で、PCR(Program Clock Reference)という独自の基準時刻を持つため、MP4のような0起点を前提としたコンテナへ移すと先頭が負の値になりやすいという事情があります。負のタイムスタンプを放置したままMP4化すると、プレーヤーによっては冒頭が再生されなかったり、音声と映像の頭がわずかにずれたりします。make_zero で起点を揃えておくと、こうした再生環境ごとの差を未然に防げます。

genpts と合わせて使う

タイムスタンプが壊れていて、かつ負の起点も持っている――というケースでは両方をまとめて指定できます。

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

-fflags +genpts(入力側)でPTSを作り直し、-avoid_negative_ts make_zero(出力側)で起点を0へ寄せる、という二段構えです。TSの修復ではこの組み合わせが定番になります。


解決③VFR→CFR化

ここまでの -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で再エンコード

VFR起因の「再生がカクつく」「編集ソフトで音ズレする」「muxerがDTS警告を連発する」といった症状は、CFR化でまとめて解消できることが多いです。

VFRは記録効率の面では優れた仕組みですが、フレーム間隔が一定でないぶん、固定フレームレートを前提とする編集ソフトや一部のプレーヤーと相性が悪く、トラブルの温床になります。CFR化では、間隔が空いたところにフレームを複製で補い、詰まったところは間引くことで、すべてのフレームを等間隔に並べ直します。これによりタイムスタンプも規則正しく増加するようになり、DTS警告が根本から消えます。目標fpsはソースのおおよそのフレームレートに合わせるのが無難で、スマホ録画なら30、映画的な素材なら24、ゲーム配信なら60といった値を選ぶとよいでしょう。元より高い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 aacsetpts/asetptsフィルタ なので、適用には再エンコードが必須

setpts は映像フィルタ、asetpts は音声フィルタで、必ずペアで指定して映像・音声の起点を揃えます。genpts が「壊れた値を推定して作る」のに対し、setpts=PTS-STARTPTS は「既存の値はそのまま、原点だけを0へ平行移動する」点が違いです。


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

修復コマンドを選ぶうえで最も重要なのが、再エンコードが必要かどうか の見極めです。

状況適切な対処再エンコード
PTS/DTSが欠落・破損しているだけ-fflags +genpts-c copy不要
先頭が負のタイムスタンプ(TS変換など)-avoid_negative_ts make_zero-c copy不要
VFRソースで間隔が不揃い-fps_mode cfr -r N(libx264等で再圧縮)必要
先頭を0起点に揃え直したいsetpts=PTS-STARTPTS / asetpts=PTS-STARTPTS必要(フィルタのため)

判断の流れはシンプルです。

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

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


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

テスト済みバージョン: ffmpeg 6.1.1
対象OS: Ubuntu 24.04 / macOS / Windows(コマンドは共通)
-fps_mode が使えない古いビルドでは -vsync cfr で代替できます。


よくある質問(FAQ)

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

ソースがVFRである可能性が高いです。genpts はタイムスタンプを推定再生成するだけで、フレーム間隔そのものは均しません。-fps_mode cfr -r 30(解決③)で固定フレームレート化を試してください。なお -fflags は入力フラグなので -i に置けているかも再確認しましょう。

Q2. -avoid_negative_ts make_zerosetpts=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 が出ます

別々に録画した動画を連結すると、2本目以降の先頭タイムスタンプが過去に戻り、DTSの単調増加が崩れるのが典型例です。concat demuxer で結合する場合は -fflags +genpts を併用するか、結合後に本記事の修復コマンドを通すと安定します。結合自体の手順は関連記事「複数の動画を連結する」も参照してください。

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

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


関連記事


動作確認: ffmpeg 6.1.1 / Ubuntu 24.04
一次ソース: ffmpeg.org/ffmpeg.html / ffmpeg.org/ffmpeg-filters.html / trac.ffmpeg.org/wiki/ChangingFrameRate