LoginSignup
0
1

More than 1 year has passed since last update.

【ffmpeg】fps情報がおかしい動画ファイルの修正

Last updated at Posted at 2023-01-08

概要

次のようなフレームレート(fps)がおかしい動画ファイルの修正を実施。
image.png

原因

恐らく、PTSやDTSといった情報が不整合を起こしているためこのようになっていると思われる。
参考:ffmpeg を使うなら知っておきたい話 PTSとかDTSの話:音ずれ問題や時間が変になるときのために ヽ(゚ー゚*ヽ)(ノ*゚ー゚)ノわぁい - Qiita

前提

  • ffmpeg及びffprobeを導入済みであること

  • ffmpeg/ffprobe version
    version N-105859-g37480b1b85-20220305

  • 対象とする動画ファイル名は「inputFile.mp4」とする

解決方法

音声ストリーム、動画ストリームをそれぞれを書き出し、fpsを指定して結合(Mux)し直す。

手順1 ファイル情報の確認

Windowsではファイルのプロパティから最初の図のようにフレームレートを確認することができるが、
念のためffprobeを用いて確認する。

ffprobe -i inputFile.mp4 -hide_banner

image.png

手順2 元の動画ファイルのフレームレートを確認する

元の動画ファイルのフレームレートが不明な場合はffprobeを使用して求める。
※フレームレートが判明している場合はこの手順は不要

手順2-1 総フレーム数の取得

ffprobe -v error -select_streams v -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 inputFile.mp4

ここで得られたフレーム数を「108000」とする。

各種オプションの補足
  • -v error
    ffprobeの出力結果のみにする
  • -select_streams v
    動画ストリームのみを選択
  • -show_entries stream=nb_frames
    エントリーの表示。 stream=nb_freamsでフレーム数の表示。
  • -of default=nokey=1:noprint_wrappers=1
    default=nokey=1:キーの非表示
    noprint_wrappers=1:セクションの非表示

手順2-2 再生時間の取得

音声ファイルは正常と考え、音声ストリームの再生時間を取得する。(単位は秒)

ffprobe -v error -select_streams a -show_entries stream=duration -of default=nokey=1:noprint_wrappers=1 inputFile.mp4

ここで得られた再生時間を「3600」とする。

各種オプションの補足
  • -select_streams a
    音声ストリームのみを選択
  • -show_entries stream=duration
    エントリーの表示。 stream=durationで再生時間の表示。

手順2-3 フレームレートの算出

手順2-1で取得した総フレーム数を、
手順2-2で取得した再生時間で割る。

108000 / 3600 = 30

よって元動画ファイルのフレームレートは「30fps」となる。

手順3 音声ファイルのみを抜き出す

「audio.aac」というファイル名で音声ファイルを抜き出す

ffmpeg -i inputFile.mp4 -vn -c:a copy audio.aac
各種オプションの補足
  • -vn
    動画ストリームを無効にする。
  • -c:a copy
    入力ファイルの音声コーデックと出力ファイルのコーデックを同じにする。
    -codec:a copy-acodec copyと同等

手順4 動画ストリームだけを抜き出す

H.264形式で書き出す。

ffmpeg -i inputFile.mp4 -an -c:v copy -f h264 noaudio.h264
各種オプションの補足
  • -an
    音声ストリームを無効にする
  • -c:v copy
    入力ファイルの動画コーデックと出力ファイルのコーデックを同じにする。
    -codec:v copy-vcodec copyと同等
  • -f h264
    フォーマットを指定する。「H264」を指定する。

image.png
上図のようにエラーが出る場合があるが無視。
※DTSは増加していく情報であるが、そのようになっていないフレームがあるとのエラーのよう。
「Application provided~」のログレベルはエラーに設定されているが、処理が止まることはなく問題なく出力される。
ソースコードを見ると、今回はそれ以外の原因でエラーとなっている気がする。
https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/mux.c#L540-L549

手順5 音声と動画を結合(Mux)する

手順3で作成した音声ファイルと、手順4で作成した動画ファイルを結合する。
-r 30には、元ファイルと同じフレームレートを指定する。(今回は30)

ffmpeg -r 30 -i noaudio.h264 -i audio.aac -c:v copy -c:a copy outputFile.mp4
各種オプションの補足
  • -r
    フレームレートの指定

image.png
noaudio.h264ファイルにPTS情報がないので警告が出ているが、ffmpegがいい感じにやってくれる。

完成

です。

蛇足

  • 手順2でフレームレートを算出しているが、手順4で作成した.h264ファイルに対して
ffprobe -v error -show_entries stream=r_frame_rate -of default=nokey=1:noprint_wrappers=1 noaudio.h264

とすることでフレームレートがわかる。

  • そもそもフレームレートを算出しておかなくても、手順5の出力時に-rで指定しなければ.h264ファイルのフレームレート情報を見に行ってか、ffmpegがなんかいい感じにやってくれる。
    今回はなんとなく指定した。

  • 可変フレームレートの場合は知りません。

  • ストリームの順番が入力ファイルと異なってしまって困る場合は、-mapオプションを使用して、明示的に指定してください。

参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1