Search code examples
encodingffmpegscreenshotframe-ratevsync

Create video from PNGs with FFMPEG and variable per image timestamps


I'm trying to take a pile of screenshot PNGs, and the timestamp of each screenshot, and create a video with ffmpeg that recreates the timing of the screenshots.

According to the ffmpeg help, -vsync 0 seems to be what I need,

-vsync parameter

0, passthrough Each frame is passed with its timestamp from the demuxer to the muxer.

Does anyone know how to pass this timestamp information into ffmpeg? Presently each screenshot has the recording time in milliseconds as the filename.

The below example doesn't accept any timing information that I can tell, so I'm looking for the proper format to pipe to the command.

ffmpeg -vsync 0 -pattern_type glob -i '*.png' -c:v libx264 output.mp4


Solution

  • Script: get time from filename, minus previous filetime = duration of temp video, then concat videos

    #!/bin/bash
    LST=($(ls -1tr Screenshot*.png))
    TOT=${#LST[*]}
    f="${LST[0]}"
    #Screenshot_20201115_135335.png
    FNM="${f%.*}"
    SEC="${FNM:24:2}"
    MIN="${FNM:22:2}"
    HOU="${FNM:20:2}"
    echo $f $HOU $MIN $SEC
    BEG=$(echo "$HOU * 3600 + $MIN * 60 + $SEC" | bc -l)
    echo $f $BEG
    INP=("-i" "$f")
    OUT="${f%.*}.mkv"
    TXT=list.txt
    echo "#png to mkv" > $TXT
    
    for (( i=1; i<=$(( $TOT -1 )); i++ )); do
      f="${LST[$i]}"
      FNM="${f%.*}"
      SEC="${FNM:24:2}"
      MIN="${FNM:22:2}"
      HOU="${FNM:20:2}"
      TIM=$(echo "$HOU * 3600 + $MIN * 60 + $SEC" | bc -l)
      DUR=$(echo "$TIM - $BEG" | bc -l)
      echo $f $TIM $DUR
      ffmpeg -y -hide_banner -loop 1 "${INP[@]}" -t $DUR "/tmp/${OUT}"
      echo "file '/tmp/${OUT}'" >> $TXT
      BEG=$TIM
      INP=("-i" "$f")
      OUT="${f%.*}.mkv"
    done
    
    ffmpeg -y -hide_banner -loop 1 "${INP[@]}" -t 5 "/tmp/${OUT}"
    echo "file '/tmp/${OUT}'" >> $TXT
    
    cat "$TXT"
    ffmpeg -hide_banner -f concat -safe 0 -i "$TXT" -c:v h264_nvenc -cq 20 -y /tmp/output.mkv
    ffplay /tmp/output.mkv