5

ビデオに変換する画像の特定のリストを指定する方法を理解しようとしています。次のようなことができることはわかっています。

ffmpeg -i image_04%d.png

これにより、シーケンスに一致するフォルダーからすべての画像が選択されます。ただし、私の場合、画像ファイルは必ずしもその名前が示す順序になっているとは限りません。その理由は、順序がデータベースで保持され、ファイル名が基本的にデータベースの行 ID であるためです。

正しい入力シーケンスを指定するにはどうすればよいですか? 私は基本的に、コマンドラインからではなく、コードから ffmpeg を呼び出しています。したがって、コードの変更のアイデアも歓迎されます。

ありがとう!

4

4 に答える 4

5

これが私のために働くケビンの考えに沿ったスクリプトです。ファイル名のパターン(shot * .png)と出力ファイル名movie.mp4を置き換えることをお勧めします。すべてのframe_...ファイルは、終了時にスクリプトによって削除されます。

# script to create movie from multiple png files
# taken in choronoligcal order

# start at 0
count=0
# take all files named shot - something ordered by date
for f in `ls -rt shot*.png`
do 
  # get the index in 0000 format
  printf -v counts "%04d" $count
    # link file to a frame_0000  named symbolic link
    ln -s $f frame_$counts.png
    # increment counter
  count=`expr $count + 1`
done
# create movie
# slowed down by factor 5
# ffmpeg -f image2 -i frame_%04d.png -vcodec mpeg4 -vf "setpts=5*PTS" movie.mp4
ffmpeg -i frame_%04d.png movie.mp4
# remove the links
rm frame_*.png
于 2012-12-05T21:03:03.103 に答える
2

次のような正しい順序でファイル名のリストがあるとします。

frames=(
    "5K1OCNKToUu.png"  "kJuKFQS0Fgnp.png" "00v4U4JTyUn.png"  "3sg9sDwPZoX.png"
    "1KsuEk9mboa9.png" "qNrI8zlRBmW.png"  "MOvSca3wlPsP.png" "5rXcxfGQXunY.png"
    "hjruIcoN0aTn.jpg" "OhRttnWtKy.png"   "e2Qj8jCixc.png"   "Uze2H7vzrt4.png"
    "n14qhmjiBW3.png"  "ZDMvY4g1hzgS.png" "ibnb7MxELyGp.png" "9c8QGWmBEDNg.png"
    "STQT0t7oqPEK.png" "jI7UvpbLDWPc.png" "6clazeaUAJHv.png" "ylJ40r9uMK9d.png"
    "RICq5KV00P6.png"  "zjCLrappFMPq.png" "TJQTDv313KBo.png" "Gu3pLpWylsuo.png"
    "Ksym4SB6VYNv.png" "rIyj0LJIjBVX.png" "pSUm2J8xYU.png"   "Rnsr0H0m7p9A.png"
    "x4vVomlOolxt.png" "2W1QURLQUyE8.png" "m3JgtDzQ0VgE.png" "CrjN9TVJKMAU.png"
    "IO6pnF83ivqo.png" "hY15nsYDvr4h.png" "1GagDdBM9L7.png"
)

そして、これらから特定のフレームレートでアニメーション GIF を作成したいと考えていますFPS=30。これは、シンボリックリンクを作成することにより、他の回答と同様に実行できます。たとえば、次の名前001.pngを付けて035.png使用します。

ffmpeg -i 03%d.png

別の方法は、ffmpegconcat-featureを利用することです。残念ながら、この機能はビデオ ストリームを想定しているため、これは言うは易く行うは難しです。つまり、画像を必要なだけループさせる必要があります。

500 ミリ秒間隔で 3 つの画像を連結するコマンドは次のとおりです。

ffmpeg -f concat -safe 0 -i <(cat <<EOF
file '$(pwd)/1KsuEk9mboa9.png'
duration 0.5
file '$(pwd)/hjruIcoN0aTn.png'
duration 0.5
file '$(pwd)/n14qhmjiBW3.png'
duration 0.5
EOF
) -framerate 2 out.gif

でテスト済みffmpeg version 3.0.1-3

説明:

  • concat demuxerは、先頭にキーワードfile. 現在の作業ディレクトリが乱雑にならないように (または、書き込み権限がない可能性もあります)、 process substition を使用します<( ... )。ただし、これによりファイルが作成/dev/fd/され、相対ファイル名が使用されている場合、次のようなエラー メッセージが表示されます。

    [concat @ 0xc181c0] Impossible to open '/dev/fd/5K1OCNKToUu.png'
    

    そのため、絶対パスが指定されています。ただし、デフォルトでは絶対パスは許可されていないため、次のようになります。

    [concat @ 0x17da1c0] Unsafe file name '/home/5K1OCNKToUu.png'
    

    それを解決するために-safe 0使用されます。

  • で入力フレームレートを指定しようとすると-r

    ffmpeg -f concat -safe 0 -r 2 -i <(cat <<EOF
    file '$(pwd)/1KsuEk9mboa9.png'
    file '$(pwd)/hjruIcoN0aTn.png'
    file '$(pwd)/n14qhmjiBW3.png'
    EOF
    ) -framerate 2 out.gif
    

    次のようなエラーが発生します。

    [concat @ 0x1458220] DTS -230575710986777 < 0 out of order
    DTS -230575710986777, next:40000 st:0 invalid dropping
    PTS -230575710986777, next:40000 invalid dropping st:0
    

    とにかく、結果のGIFは期待どおりに機能します。のdurationオプションをconcat明示的に使用すると、これらの警告/エラーが解決されます。

    のコメントに注意してください-r

    入力オプションとして、ファイルに保存されているタイムスタンプを無視し、代わりに一定のフレーム レート fps を想定してタイムスタンプを生成します。これは、image2 や v4l2 などの一部の入力形式に使用される -framerate オプションと同じではありません (以前のバージョンの FFmpeg では同じでした)。疑わしい場合は、入力オプション -r の代わりに -framerate を使用してください。

    これについての私の見解は、画像の再生長が見つからなかったことを通知する concat からの上記の警告は、 との concat 警告の後にフレームレートが強制されるため、悪い動作にはならないということです-r。これは機能しますが、意図した方法ではありません。これは、ffmpeg コマンドを手動で記述するときにのみ使用しますが、スクリプトでは使用しません。

最初に指定されたファイル名のリストを操作する小さなスクリプトをまとめます。

function makeGif() {
    local targetName=$1; shift
    local FPS=$1; shift
    # concat doesn't recognize .33 as returned by bc by default
    local delay=$(bc <<< "scale=5; x=1/$FPS; if (x<1) print 0; x")
    local list
    for file in $@; do
        list+=$(printf "\nfile '$(pwd)/$file'\nduration $delay")
    done
    ffmpeg -f concat -safe 0 -i <(cat <<< "$list") -r $FPS "$targetName".gif
    #ffmpeg -f concat -safe 0 -i <(cat <<< "$list") -r $FPS -c:v libx264 -crf 5 -pix_fmt yuv420p "$targetName".mkv
}
makeGif out 30 ${frames[@]}

上記のコードでコメントを外した行は、H264 でエンコードされた mkv を提供します。

異種のイメージ タイプ

イメージ リストにさまざまなタイプのイメージが含まれている場合 (たとえば、 in に置き換えhjruIcoN0aTn.pnghjruIcoN0aTn.jpg場合frames)、この の使用法は機能しconcatません。最初に指定された以外の形式の画像はドロップされ、次のようなエラーがスローされます。

[png @ 0x1ec8260] Invalid PNG signature 0xFFD8FFE000104A46.
Error while decoding stream #0:0: Invalid data found when processing input

この場合、単純なデマルチプレクサの代わりにconcat フィルタを使用する必要があります。上記の 3 つのファイルを使用するコマンドは、次のように変更する必要があります。

ffmpeg \
-f image2 -loop 1 -thread_queue_size 4096 -framerate 30 -t 0.5 -i "$(pwd)/1KsuEk9mboa9.png"  \
-f image2 -loop 1 -thread_queue_size 4096 -framerate 30 -t 0.5 -i "$(pwd)/hjruIcoN0aTn.jpg"  \
-f image2 -loop 1 -thread_queue_size 4096 -framerate 30 -t 0.5 -i "$(pwd)/n14qhmjiBW3.png"   \
-filter_complex 'concat=n=3:v=1 [vmerged]' \
-map '[vmerged]' -r 30 out.gif

説明:

  • 使用される各オプションは、ここで非常によく説明されています。このオプションは画像インポーター-framerateに固有のものであり、少なくとも技術的には とは異なることに注意してください。この場合、実際には同じ結果が得られます。-r

  • 1 つの-thread_queue_sizeイメージを非常に長い 500 ミリ秒延長すると、次のエラー メッセージが表示されるため、これが必要と思われます。

    [image2 @ 0x18856e0] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
    [image2 @ 0x188a100] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
    [image2 @ 0x188b9e0] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
    

    オプションの説明は、過度に大きな遅延が原因であると考える理由を与えてくれました:

    -thread_queue_size サイズ (入力) このオプションは、ファイルまたはデバイスから読み取るときにキューに入れられるパケットの最大数を設定します。低遅延/高レートのライブ ストリームでは、パケットがタイムリーに読み取られない場合、パケットが破棄される可能性があります。この値を上げると回避できます。

これらすべてを再びスクリプトに入れます。

function makeGif() {
    local targetName=$1; shift
    local FPS=$1; shift
    local delay=$(bc <<< "scale=5; x=1/$FPS; if (x<1) print 0; x")
    local list=()
    local nFiles=0
    for file in $@; do
        list+=( -f image2 -loop 1 -thread_queue_size 4096 -framerate $FPS -t $delay -i "$(pwd)/$file" )
        nFiles=$((nFiles+1))
    done
    ffmpeg ${list[@]} -filter_complex "concat=n=$nFiles:v=1 [vmerged]" -map '[vmerged]' -r $FPS "$targetName".gif
    #ffmpeg ${list[@]} -filter_complex "concat=n=$nFiles:v=1 [vmerged]" -map '[vmerged]' -r $FPS -c:v libx264 -crf 5 -pix_fmt yuv420p "$targetName".mkv
}
makeGif out 30 ${frames[@]}

非常に奇妙な理由により、上記のコマンドはそのままでは機能しません!!! . 私の場合、指定された 35 フレームのうち 33 フレームが警告やエラー メッセージなしでドロップされました。

frame=    2 fps=0.0 q=-0.0 Lsize=       2kB time=00:00:00.07 bitrate= 179.7kbits/s dup=0 drop=33 speed=0.155x

これが奇妙である理由は、2倍の遅延を意図したように完全に機能するためです。つまり、各画像が2フレーム表示されます。つまり、次のように変更1/$FPSされ2/$FPSます。

frame=   70 fps=0.0 q=-0.0 Lsize=     701kB time=00:00:02.33 bitrate=2465.4kbits/s speed= 2.9x 

この事実は、簡単な回避策を示唆しています。フレームレートを 2 倍にしてエンコードし、各画像を 2 フレーム表示します。しかし、それは無駄であり、どうせ好ましいことではありません。

于 2016-05-29T18:40:01.787 に答える
1

アプリケーションは、元のフレームの順序を尊重する 0001 から始まるシンボリック リンクを作成し、そのシーケンスを ffmpeg に渡すことができます。ビデオが完成したら、シンボリックリンクを削除して完了です。

于 2012-04-29T03:13:07.260 に答える
0

解決策は、選択する番号のリストをサポートするように image2 クラスにパッチを適用することでした。入力を読み取るために指定された順序で数値の配列とともに入力ファイルパターンをffmpegに提供したよりも。これは完璧に機能しました。

于 2012-05-17T16:31:06.180 に答える