问题
The following is a hex-ascii dump of the first 300 bytes of an avi xvid file:
|52|49|46|46|8c|79|95|00|41|56|49|20|4c|49|53|54|94|6a|00|00 RIFF.y..AVI LIST.j..
|68|64|72|6c|61|76|69|68|38|00|00|00|40|9c|00|00|00|ec|36|00 hdrlavih8...@.....6.
|00|00|00|00|10|00|00|00|81|01|00|00|00|00|00|00|01|00|00|00 ....................
|df|9e|01|00|d0|02|00|00|40|02|00|00|00|00|00|00|00|00|00|00 ........@...........
|00|00|00|00|00|00|00|00|4c|49|53|54|3c|69|00|00|73|74|72|6c ........LIST<i..strl
|73|74|72|68|38|00|00|00|76|69|64|73|78|76|69|64|00|00|00|00 strh8...vidsxvid....
|00|00|00|00|00|00|00|00|e8|03|00|00|a8|61|00|00|00|00|00|00 .............a......
|81|01|00|00|df|9e|01|00|10|27|00|00|00|00|00|00|00|00|00|00 .........'..........
|d0|02|40|02|73|74|72|66|28|00|00|00|28|00|00|00|d0|02|00|00 ..@.strf(...(.......
|40|02|00|00|01|00|18|00|58|56|49|44|00|f8|25|00|00|00|00|00 @.......XVID..%.....
|00|00|00|00|00|00|00|00|00|00|00|00|73|74|72|64|c0|28|00|00 ............strd.(..
|00|00|00|00|bc|02|00|00|90|b2|08|00|2e|5c|76|69|64|65|6f|2e .............\video.
|70|61|73|73|00|00|2e|00|70|00|61|00|73|00|73|00|00|00|00|00 pass....p.a.s.s.....
|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00 ....................
|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00 ....................
In this particular case I know that the video has a frame rate of 25 frames per second. How can I use this dump to obtain the frame rate? Note, it is straightforward to obtain the frame rate for an avi msvc video file since the data structure is well documented. However, I have yet to find any document that defines the data structure for an avi xvid file.
回答1:
The following is an improved version (IMHO) of my previous answer. This code finds 5 key features of AVI files.
"""
Purpose: To extract 5 important features from AVI files: time between frames,
frames per second, number of frames, width and height of each frame.
Author: V. Stokes (vs@it.uu.se)
Version: 2014.01.01.1
Note:
1. DT (time between samples) in microseconds, bytes: 32,33,34,35
of all AVI files that I tested. Byte 0 is the first byte in the AVI file.
2. SR (sample rate) is equivalent to fps (frames per second) and can be
calculated from the inverse of DT.
3. NF (number of frames), bytes: 48,49,50,51.
4. WD (width of each frame) in pixels, bytes: 64,65,66,67
5. HT (height of each frame) in pixels, bytes: 68,69,70,71
6. This python script works on all the AVI files that I have tested (so far),
which suggests there is some consistency in the different AVI formats.
"""
import os
# laptop desktop
dirpaths = [r'D:/Videos/', r'C:/Videos/']
for path in dirpaths:
if os.path.exists(path):
defDir = path
## All the following videos were "test AVI video downloads" from the Web
#video = 'julius.avi' #CRAM ( 56 frames,320x240,15fps, 66667 microseconds between frames)
#video = 'flyby-xvid.avi' #DIVX (495 frames,320x240,30fps, 33333 microseconds between frames)
#video = 'flyby-xvid-realtime.avi' #DIVX (495 frames,320x240,30fps, 33333 microseconds between frames)
#video = 'flyby-xvid-q5.avi' #DIVX
#video = 'flyby-xvid-mpeg.avi' #DIVX
#video = 'flyby-xvid-mpeg-q2.avi' #DIVX
#video = 'flyby-xvid-default.avi' #DIVX
#video = 'flyby-xvid-2p.avi' #DIVX
#video = 'flyby-divx.avi' #DX50
#video = 'ubAVIxvid10.avi' #XVID (849 frames,640x480,10fps,100000 microseconds between frames)
#video = 'toy_plane_liftoff.mp4' # This is not an AVI and doesn't work
video = 'toy_plane_liftoff.avi' #MJPG (100 frames,640x480,25fps, 40000 microsseconds between frames)
inFile = defDir + video
print 'Input file: %s' %inFile
data = [0,0,0,0]
with open(inFile,'r') as f:
f.seek(32,0) # start reading offset byte 32
data[0] = f.read(4) # get 4 bytes (32,33,34,35) -- DT
f.seek(48,0)
data[1] = f.read(4) # get 4 bytes (48,49,50,51) -- NF
f.seek(64,0)
data[2] = f.read(4) # get 4 bytes (64,65,66,67) -- Width
data[3] = f.read(4) # get 4 bytes (68,69,70,71) -- Height
f.close()
def bufferToHex(num):
for k in range(num):
accumulator = ''
buffer = data[k]
for item in range(4):
accumulator += '%s' % buffer[item]
data[k] = accumulator
# Get 4 hex strings (4 bytes in each string)
bufferToHex(4)
for k in range(4): # loop on DT,NF,WD,HT
prev_kvs = ''
for hexval in data[k]: # loop on each group of 4 bytes
strr = hexval.encode('hex') # hexidecimal string of length 2
kvs = strr + prev_kvs
prev_kvs = kvs
intVal = int(kvs,16)
if k == 0:
# DT
print 'DT = %6d (microseconds)' %intVal
print 'SR = %6d (frames per second)' %round(10.0**6/intVal)
elif k == 1:
# NF
print 'NF = %6d (number of frames)' %intVal
elif k == 2:
# Width
print 'Width = %6d (width in pixels)' %intVal
else:
# Height
print 'Height = %6d (height in pixels)' %intVal
回答2:
The following Python script (Python 2.7, Windows Vista-32 bit) can be used to extract the time between frames from AVI files and in turn the frame rate.
"""
Purpose: To extract the time between frames from AVI files
Author: V. Stokes (vs@it.uu.se)
Version: 2013.12.31.1
Note:
1. DT (time between samples) in microseconds is stored in bytes: 32,33,34,35
of all AVI files that I tested. Byte 0 is the first byte in the AVI file.
2. SR (sample rate) is equivalent to fps (frames per second) and can be
calculated from the inverse of DT.
3. DT is stored as 4 bytes (long C integer) which are in reverse order.
4. This python script works on all the AVI files that I have tested (so far),
which suggests there is some consistency in the different AVI formats.
5. All of the AVI files used for testing can be obtained from me via
an email request.
"""
import os
# laptop desktop
dirpaths = [r'D:/Videos/', r'C:/Videos/']
for path in dirpaths:
if os.path.exists(path):
defDir = path
#
## All of the following files were downloaded from different web "test" AVI file sites
## Bytes: 32,33,34,35 = 35,82,00,00
#video = 'flyby-xvid.avi' #DIVX (495 frames,320x240,30fps, 33333 microseconds between frames)
#video = 'flyby-xvid-realtime.avi' #DIVX (495 frames,320x240,30fps, 33333 microseconds between frames)
#video = 'flyby-xvid-q5.avi' #DIVX
#video = 'flyby-xvid-mpeg.avi' #DIVX
#video = 'flyby-xvid-mpeg-q2.avi' #DIVX
#video = 'flyby-xvid-default.avi' #DIVX
#video = 'flyby-xvid-2p.avi' #DIVX
## Bytes: 32,33,34,35 = 35,82,00,00
#video = 'flyby-divx.avi' #DX50
## Bytes: 32,33,34,35 = a0,86,01,00
#video = 'ubAVIxvid10.avi' #XVID (849 frames,640x480,10fps,100000 microseconds between frames)
#video = 'toy_plane_liftoff.mp4' # This is not an AVI and doesn't work!
#video = 'toy_plane_liftoff.avi' #MJPG (100 frames,640x480,25fps, 40000 microsseconds between frames)
## Bytes: 32,33,34,35 = 6b,04,01,00
video = 'julius.avi' #CRAM ( 56 frames,320x240,15fps, 66667 microseconds between frames)
inFile = defDir+video
print 'Input file: %s' %inFile
with open(inFile,'r') as f:
# Get time between frames (in hex format)
f.seek(32,0) # start reading at byte 32
data = f.read(4) # get 4 bytes (32,33,34,35)
f.close()
def bufferToHex(buffer, start, count):
accumulator = ''
for item in range(count):
accumulator += '%s' % buffer[start + item]
return accumulator
hexc = bufferToHex(data, 0, 4)
timeBetweenFrames = 0
k = -2
for hexval in hexc:
k += 2 # two hex characters
kvs = hexval.encode('hex') # hexidecimal string of length 2
kv = int(kvs,16) # convert to integer base-16 (hexidecimal)
kp = 16**k
timeBetweenFrames += kv*kp
print 'DT = %6d (microseconds)' %timeBetweenFrames
print 'SR = %6d (frames per second)' %round(10.0**6/timeBetweenFrames)
来源:https://stackoverflow.com/questions/20821204/how-can-i-get-the-frames-per-sec-from-the-header-of-an-avi-xvid-video-file