How can I get the frames per sec from the header of an avi xvid video file?

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-13 04:22:43

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!