Display number of frames in MP4 video

Started by traycer, May 21, 2023, 06:01:23 AM

Previous topic - Next topic

traycer

I would like to display the number of frames in an MP4 video. It appears that the duration of a video is stored in seconds as a floating point value. I see there is a $FrameCount tag, but it does not appear in the MP4 files I have. There is $VideoFrameRate, so I could calculate that by multiplying that with $Duration. This is where I get stuck.

I've read the Advanced Formatting part of the docs, but can't figure out how to multiply the two tags inside a -printConv. I figure this is a pretty basic operation, so I must be missing something obvious.

I've tried variations like '${Duration;$Duration*$VideoFrameRate}' and '${Duration;GetValue("Duration")*GetValue("VideoFrameRate")}' with no success. However, even a dummy operation like '${Duration;$_+1000}' does not produce expected output:

$ exiftool -m -n -p '$filename ${Duration;$_+1000}' 0501-*
0501-093939.mp4 2.112
0501-173812.mp4 5.005
0501-175421.mp4 5
0501-233527.mp4 5.005

What am I missing here? Ultimately, my goal is to have exiftool generate a list of filenames of videos that are within a range of frames (1828±2 frames, in my specific case).

StarGeek

A quick look over the Tags Names pages, it looks like the FrameCount is specific to some cameras and not a general tag for videos.

Quote from: traycer on May 21, 2023, 06:01:23 AMI've read the Advanced Formatting part of the docs, but can't figure out how to multiply the two tags inside a -printConv. I figure this is a pretty basic operation, so I must be missing something obvious.

It is not.  You have to call directly into the exiftool functions directly.  The construct would along these lines
${TAGNAME;$_=<somecalculation>+$self->GetValue('OTHERTAG')}

I haven't tested it, but I think you want this
${VideoFrameRate;$_*=$self->GetValue('Duration','ValueConv')}

The *= operator takes the current value of VideoFrameRate and multiplies it by what follows.

For the Duration, in order to get the raw number, you need to include the 'ValueConv'

I do something similar in a command I use with downloaded videos. The FileModifyDate ends up as the time the video ended and I want it to be when the video started.
"-FileModifyDate<${FileModifyDate;ShiftTime('-0:0:'.$self->GetValue('Duration','ValueConv'))}"
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

traycer

Yikes! Yeah, I would not have figured that one out on my own. ;D This does indeed work, and is much faster than the ffprobe loop I was using before.

$ exiftool -m -n -p '$FileName $FileSize $Duration $VideoFrameRate ${VideoFrameRate;$_*=$self->GetValue("Duration","ValueConv")}' *
0501-093434.mp4 675237120 61.061 29.97002997003 1830
0501-093535.mp4 675237120 61.0943666666667 29.97002997003 1831
0501-093636.mp4 675237120 61.061 29.97002997003 1830
0501-093737.mp4 675237120 60.8941666666667 29.97002997003 1825
0501-093838.mp4 675237120 61.061 29.97002997003 1830
0501-093939.mp4 22827237 2.1021 29.97002997003 63
0501-173812.mp4 482816500 48.1481 29.97002997003 1443
[...]

Apparently the number of frames is stored in the metadata of an MPEG-4 file, at least in a way that ffmpeg can retrieve it . But that metadata does not exist for MKV containers, while exiftool can still calculate it, so I'll stick with this.

Thanks again for your great insight into some of the trickier aspects of exiftool!

$ for i in *.mp4 ; do ffprobe -v error -select_streams v -show_entries stream=nb_frames $i ; done
[STREAM]
nb_frames=1830
[/STREAM]
[STREAM]
nb_frames=1831
[/STREAM]
[STREAM]
nb_frames=1830
[/STREAM]
[STREAM]
nb_frames=1825
[/STREAM]
[STREAM]
nb_frames=1830
[/STREAM]
[STREAM]
nb_frames=63
[/STREAM]
[STREAM]
nb_frames=1443
[/STREAM]
[...]

StarGeek

Quote from: traycer on May 21, 2023, 07:42:03 PMThis does indeed work, and is much faster than the ffprobe loop I was using before.
...

Apparently the number of frames is stored in the metadata of an MPEG-4 file, at least in a way that ffmpeg can retrieve it .

Yes, exiftool does not read the streams to make sure of the number of frames, just the header.  So sometimes exiftool's results can be inaccurate.  See this GitHub post

If you need complete accuracy, then you have to use ffprobe, as that actually reads the streams.
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype