Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

Post your working scripts, libraries and tools for AHK v1.1 and older
Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 11:25

This small function returns the number of video frames in a given AVI video file.
Maybe somebody was looking for that.

Usage like

msgbox % "myvideo.avi has " . getAVIFrames("c:\desktop\myvideo.avi") . " Frames"

by Hotte

Code: Select all

getAviFrames(avifullpath)
{	fileObj := FileOpen(avifullpath,"r")		; Open file for read
	if (fileObj = 0)
    	Return 0
	fileObj.Seek(48,0)					; set filepointer to position 48
	fileObj.RawRead(x, 4)				; read 4 Bytes from position 48 into variable x. This is the number of frames 
	frames := NumGet(x,0,"UInt")			; convert x (DWord=UInt) into a decimal
	fileObj.Close()						; close AVI file
	Return frames
}
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 11:35

Thanks, Hotte. Just tried it, works great.
Regards,
burque505
EDIT: A humble little script based on it.

Code: Select all

#Persistent
#SingleInstance, force

Gui, New
Gui, Add, Text, w60, File path
Gui, Add, Button, x+5 Default, Select_File
Gui, Add, Edit, x5 w500 +ReadOnly vFilePath
Gui, Add, Text, y+5 w100, Number of frames
Gui, Add, Edit, y+5 w100 +ReadOnly vFrames

Gui, Show

return

Escape::
GuiClose:
ExitApp

ButtonSelect_File:
FileSelectFile, Path, , , Select an AVI vile, Video (*.avi)
GuiControl, , FilePath, %Path%
GuiControl, , Frames, % getAviFrames(Path)
return

getAviFrames(avifullpath)
{	fileObj := FileOpen(avifullpath,"r")		; Open file for read
	if (fileObj = 0)
    	Return 0
	fileObj.Seek(48,0)					; set filepointer to position 48
	fileObj.RawRead(x, 4)				; read 4 Bytes from position 48 into variable x. This is the number of frames 
	frames := NumGet(x,0,"UInt")			; convert x (DWord=UInt) into a decimal
	fileObj.Close()						; close AVI file
	Return frames
}
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 12:02

something is probably eluding me, but if a DWORD is 4 bytes, shouldnt the struct look like this:

Code: Select all

https://msdn.microsoft.com/en-us/library/windows/desktop/dd318180

typedef struct _avimainheader {
  FOURCC fcc;						;  0 byte
  DWORD  cb;						;  4 byte
  DWORD  dwMicroSecPerFrame;		;  8 byte
  DWORD  dwMaxBytesPerSec;			; 12 byte
  DWORD  dwPaddingGranularity;		; 16 byte
  DWORD  dwFlags;					; 20 byte
  DWORD  dwTotalFrames;				; 24 byte
  DWORD  dwInitialFrames;			; 28 byte
  DWORD  dwStreams;					; 32 byte
  DWORD  dwSuggestedBufferSize;		; 36 byte
  DWORD  dwWidth;					; 40 byte
  DWORD  dwHeight;					; 44 byte
  DWORD  dwReserved[4];				; 48 byte
} AVIMAINHEADER;
why the doubling?
Last edited by swagfag on 06 Jun 2018, 13:18, edited 2 times in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 12:53

Cool. Nice example burque505 :thumbup:.

FYI, file object has readNumType method, so you can get frames like this,

Code: Select all

frames := fileObj.readUint()
Thanks for sharing, cheers.
Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 12:57

@burque505, Thanks, very nice little tool!

@swagfaq, puh, not sure... position was a bit trial&error but works fine. Has it sth to do with 16 bit instead of 8 ?
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 13:13

Avi header: 56-byte header, starting at offset 32 within the file:
avi header.PNG
avi header.PNG (10.79 KiB) Viewed 2688 times
So, 32 plus 16 for the number of frames gives 48.
@Helgef, thanks for that tip. I need lots of work on OOP.\
:) EDIT: And with that in mind, a work in progress (all credit to Hotte),
Spoiler
AviInfo.ahk (thanks again, Hotte!)
Spoiler
Regards,
burque505
Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 14:03

Thank you very much, Burque - very useful solutions. :bravo:

It's always great to see, how the community contributes and makes things grow

If you are interested in two timecode conversion routines that really work right, let me know.
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 14:30

@burque505, only a suggestion: you might want to open the file only once, read all the info, store all the info in an associated array and return the array. This would reduce the file open/close steps significantly.
Just my 2 cents
ciao
toralf
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 14:33

Toralf, you are absolutely right. Let me work on that.
EDIT:
et voilà !
Spoiler
EDIT: Added bitrate.
Regards,
burque505
Last edited by burque505 on 06 Jun 2018, 16:37, edited 1 time in total.
Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Re: Get number of frames in an AVI Video File (learn about the usage of file read & pointers & number conversion)

06 Jun 2018, 15:21

Ok, this is mabye 'bit off topic, but I do not want to make autohotkey a video-solution forum, so do not want to start a new thread and it pairs well with the number of frames issue above.

This is a function that converts a video timecode into the proper framenumber.

Input:
tc = timecode as string either hh:mm:ss:ff OR hh:mm:ss:xms // ff = framenumber 0-30 max (1-2 digits!) xms = milliseconds 000 - 999 (3 or more digits!)
frmrate = correct playback framerate (necessary)
mode = either "n" = NonDropFrame (default only for NTSC-Rates 29.97 or 59.94. Adds 1 Frame every 33.33 / 16.66 s) or empty

Output Frame-Number (counted from 0 = 1st frame)

Examples:
msgbox % FrmNrFromTC("00:04:13:22") returns FrameNr 12694 (Video runs at functions' default 50p)
msgbox % FrmNrFromTC("00:01:00:00",29.97,"n") returns FrameNr 1799.2 => round with ceil() to geht shown frameNr (1800)
msgbox % FrmNrFromTC("00:01:00:00",29.97,"") returns FrameNr 1798.2 => round with ceil() to geht shown frameNr (1799)
msgbox % FrmNrFromTC("00:01:00:080",25,"") returns FrameNr 1502. 080 is millisecond-input. Has to have 3 digits to be recognized as such (leading zeros required). framenr is always precise, no rounding.

There maybe room for improved code, however it is more the knowhow aspect that counts here.

by Hotte

Code: Select all

FrmNrFromTC(tc, frmrate:=50, mode:="n")
{	frmNr := SubStr(tc,1,2) * 3600 * frmrate
	frmNr := frmNr + SubStr(tc,4,2) * 60 * frmrate
	frmNr := frmNr + SubStr(tc,7,2) * frmrate
	if (StrLen(tc) <= 11)								; Timecode as hh:mm:ss:ff (1-2 digits framenr)
	{	frmNr := frmNr + SubStr(tc,10)
		if (frmrate > 30)							; 50p and 60p doubling
			frmNr := frmNr + SubStr(tc,10)
    	if (frmrate = 29.97) and (mode = "n")					; Non-Drop-Frame-Input 
        	frmNr := frmNr + floor(frmNr / 29.97 / 33.33333333)	; 	compensate for Non-Drop Timecode
    	if (frmrate = 59.94) and (mode = "n")					; Non-Drop-Frame-Input 
        	frmNr := frmNr + floor(frmNr / 59.94 / 16.66666666)	; 	compensate for Non-Drop Timecode
    }
	else
		frmNr :=  ceil(frmNr + SubStr(tc,10) / (1000 / frmrate)) ; Timecode as hh:mm:ss:milliseconds (>= 3 digits)
	
    Return (frmNr)												
}

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 126 guests