如何从avi xvid视频文件的标题中获取每秒帧数?

时间:2013-12-29 01:24:13

标签: avi frame-rate

以下是avi xvid文件的前300个字节的hex-ascii转储:

|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 ....................

在这种特殊情况下,我知道视频的帧速率为每秒25帧。如何使用此转储来获取帧速率?注意,由于数据结构已有详细记录,因此可以直接获得avi msvc视频文件的帧速率。但是,我还没有找到任何定义avi xvid文件数据结构的文档。

2 个答案:

答案 0 :(得分:1)

以下是我之前回答的改进版本(恕我直言)。此代码查找AVI文件的5个主要功能。

"""
  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

答案 1 :(得分:0)

以下Python脚本(Python 2.7,Windows Vista-32位)可用于从AVI文件中提取帧之间的时间,从而提取帧速率。

"""
  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)