2

I am using ffmpeg to extract frame and save it into jpg files as follow.

ffmpeg -i video.avi -r 1 -f image2 -q 1 %05d.jpg

However, how can I get the timestamps information of each extracted frame. For example, I would like to save the jpg file with filename as hh_mm_ss.jpg?

  • Take a look at this question asked on Stack Overflow. The accepted answer provides a work-around using ImageMagick, because FFmpeg is not able to do this by itself. – Nick van Tilborg May 27 '13 at 11:24
  • @NickvanTilborg I think that the question is asking for timestamps taken from within the video (PTS, Presentation Time Stamp) - so a frame taken from 1 minute 30 seconds into the video would have a filename like 00_01_30.jpg - rather than the timestamp for the system time at which the file was created. – evilsoup May 27 '13 at 11:34
  • Ah right, but then a simple rename script should do the trick. @MinSun, can you please confirm what you want? – Nick van Tilborg May 27 '13 at 14:44
  • I have the same question, specifically what I believe he's asking (as I am) is for the timestamp from the video, i.e. a frame taken 20 seconds into the video would have a filename with: image-00_20_00.jpg – davidparks21 May 16 '14 at 4:59
1

Well, it seems like ffmpeg can't handle this (nor can other popular solutions like VLC media player). A workaround solution I used is to get the duration of the video from ffmpeg -i video_file.mp4 and divide that by the number of frames.

For reference and example here's a bash script I wrote that batch processes a set of videos, splits them into frames (@ 30 fps) and renames the files so they have both the video timestamp (in milliseconds from start of video) and the frame number originally.

I'm sure the script could be more efficient, but it works well enough for my purposes, so hopefully it finds use (since this question is coming up on google searches):

# Regular expression definitions to get frame number, and to get video duration from ffmpeg -i
FRAME_REGEX="frame-([0-9]*)\.jpeg"
LEN_REGEX="Duration: ([0-9]*):([0-9]*):([0-9]*)\.([0-9]*), start"

# Loops through the files passed in command line arguments, 
# example: videotoframes video-*.mp4
#      or: videotoframes file1.mp4 file2.mp4 file3.mp4
for vf in "$@"; do
    video_info=$(ffmpeg -i $vf 2>&1)                                                                                                                        # Get the video info as a string from ffmpeg -i
    [[ $video_info =~ $LEN_REGEX ]]                                                                                                                         # Extract length using reges; Groups 1=hr; 2=min; 3=sec; 4=sec(decimal fraction)
    LENGTH_MS=$(bc <<< "scale=2; ${BASH_REMATCH[1]} * 3600000 + ${BASH_REMATCH[2]} * 60000 + ${BASH_REMATCH[3]} * 1000 + ${BASH_REMATCH[4]} * 10")          # Calculate length of video in MS from above regex extraction

    mkdir frames-$vf                                                # Make a directory for the frames (same as the video file prefixed with "frames-"
    ffmpeg -i $vf -r 30 -f image2 frames-$vf/frame-%05d.jpeg        # Convert the video file to frames using ffmpeg, -r = 30 fps
    FRAMES=$(ls -1 frames-$vf | wc -l)                              # Get the total number of frames produced by the video (used to extrapolate the timestamp of the frame in a few lines)

    # Loop through the frames, generate a timestamp in milliseconds, and rename the files
    for f in frames-$vf/frame-*; do
        [[ $f =~ $FRAME_REGEX ]]                                                        # Regex to grab the frame number for each file
        timestamp=$(bc <<< "scale=0; $LENGTH_MS/$FRAMES*${BASH_REMATCH[1]}")            # Calculate the timestamp (length_of_video / total_frames_generated * files_frame_number)
        `printf "mv $f frames-$vf/time-%07d-%s" $timestamp $(basename $f)`              # Execute a mv (move) command, uses the `printf ...` (execute command returned by printf) syntax to zero-pad the timestamp in the file name
    done;
done;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.