├── MANFEST.in ├── CHANGES.txt ├── ffprobe ├── __init__.py ├── ffprobe-test.py └── ffprobe.py ├── README.md ├── LICENSE.txt ├── MANIFEST ├── README.txt └── setup.py /MANFEST.in: -------------------------------------------------------------------------------- 1 | include *.txt -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | v0.1, 01/06/2013 -- Initial release -------------------------------------------------------------------------------- /ffprobe/__init__.py: -------------------------------------------------------------------------------- 1 | from ffprobe import FFProbe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonh10/ffprobe/HEAD/README.md -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonh10/ffprobe/HEAD/LICENSE.txt -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | README.txt 3 | setup.py 4 | ffprobe\__init__.py 5 | ffprobe\ffprobe-test.py 6 | ffprobe\ffprobe.py 7 | -------------------------------------------------------------------------------- /ffprobe/ffprobe-test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from ffprobe import FFProbe 4 | 5 | m=FFProbe("../structured_data/EDLs/0001T_pull/0001T_PULL.mov") 6 | for s in m.streams: 7 | if s.isVideo(): 8 | framerate=s.frames()/s.durationSeconds() 9 | print framerate 10 | print s.frameSize() 11 | print s.durationSeconds() 12 | print s.frames() 13 | print s.isVideo() -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | ======= 2 | FFProbe 3 | ======= 4 | A wrapper around the ffprobe command to extract metadata from media files. 5 | 6 | Usage:: 7 | 8 | #!/usr/bin/env python 9 | 10 | from ffprobe import FFProbe 11 | 12 | metadata=FFProbe("test-media-file.mov") 13 | 14 | for stream in metadata.streams: 15 | if stream.isVideo(): 16 | print "Stream contains "+stream.frames()+" frames." 17 | 18 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | setup( 6 | name='ffprobe', 7 | version='0.3', 8 | description='Wrapper around ffprobe command to extract metadata from media files', 9 | author='Simon Hargreaves', 10 | author_email='simon@simon-hargreaves.com', 11 | url='http://www.simon-hargreaves.com/ffprobe', 12 | packages=['ffprobe'], 13 | classifiers=[ 14 | 'Development Status :: 3 - Alpha', 15 | 'Environment :: Console', 16 | 'Intended Audience :: Developers', 17 | 'License :: OSI Approved :: MIT License', 18 | 'Operating System :: MacOS :: MacOS X', 19 | 'Operating System :: Microsoft :: Windows', 20 | 'Operating System :: POSIX', 21 | 'Programming Language :: Python', 22 | 'Natural Language :: English', 23 | 'Topic :: Multimedia :: Video', 24 | 'Topic :: Software Development :: Libraries' 25 | ]) -------------------------------------------------------------------------------- /ffprobe/ffprobe.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Filename: ffprobe.py 3 | """ 4 | Python wrapper for ffprobe command line tool. ffprobe must exist in the path. 5 | """ 6 | 7 | 8 | 9 | version='0.1' 10 | 11 | import subprocess 12 | import re 13 | import sys 14 | import os 15 | import pipes 16 | 17 | class FFProbe: 18 | """ 19 | FFProbe wraps the ffprobe command and pulls the data into an object form:: 20 | metadata=FFProbe('multimedia-file.mov') 21 | """ 22 | def __init__(self,video_file): 23 | self.video_file=video_file 24 | try: 25 | with open(os.devnull, 'w') as tempf: 26 | subprocess.check_call(["ffprobe","-h"],stdout=tempf,stderr=tempf) 27 | except: 28 | raise IOError('ffprobe not found.') 29 | if os.path.isfile(video_file): 30 | if str(platform.system())=='Windows': 31 | cmd=["ffprobe","-show_streams",self.video_file] 32 | else: 33 | cmd=["ffprobe -show_streams "+pipes.quote(self.video_file)] 34 | 35 | p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True) 36 | self.format=None 37 | self.created=None 38 | self.duration=None 39 | self.start=None 40 | self.bitrate=None 41 | self.streams=[] 42 | self.video=[] 43 | self.audio=[] 44 | datalines=[] 45 | for a in iter(p.stdout.readline, b''): 46 | if re.match('\[STREAM\]',a): 47 | datalines=[] 48 | elif re.match('\[\/STREAM\]',a): 49 | self.streams.append(FFStream(datalines)) 50 | datalines=[] 51 | else: 52 | datalines.append(a) 53 | for a in iter(p.stderr.readline, b''): 54 | if re.match('\[STREAM\]',a): 55 | datalines=[] 56 | elif re.match('\[\/STREAM\]',a): 57 | self.streams.append(FFStream(datalines)) 58 | datalines=[] 59 | else: 60 | datalines.append(a) 61 | p.stdout.close() 62 | p.stderr.close() 63 | for a in self.streams: 64 | if a.isAudio(): 65 | self.audio.append(a) 66 | if a.isVideo(): 67 | self.video.append(a) 68 | else: 69 | raise IOError('No such media file '+video_file) 70 | 71 | 72 | class FFStream: 73 | """ 74 | An object representation of an individual stream in a multimedia file. 75 | """ 76 | def __init__(self,datalines): 77 | for a in datalines: 78 | (key,val)=a.strip().split('=') 79 | self.__dict__[key]=val 80 | 81 | def isAudio(self): 82 | """ 83 | Is this stream labelled as an audio stream? 84 | """ 85 | val=False 86 | if self.__dict__['codec_type']: 87 | if str(self.__dict__['codec_type']) == 'audio': 88 | val=True 89 | return val 90 | 91 | def isVideo(self): 92 | """ 93 | Is the stream labelled as a video stream. 94 | """ 95 | val=False 96 | if self.__dict__['codec_type']: 97 | if self.codec_type == 'video': 98 | val=True 99 | return val 100 | 101 | def isSubtitle(self): 102 | """ 103 | Is the stream labelled as a subtitle stream. 104 | """ 105 | val=False 106 | if self.__dict__['codec_type']: 107 | if str(self.codec_type)=='subtitle': 108 | val=True 109 | return val 110 | 111 | def frameSize(self): 112 | """ 113 | Returns the pixel frame size as an integer tuple (width,height) if the stream is a video stream. 114 | Returns None if it is not a video stream. 115 | """ 116 | size=None 117 | if self.isVideo(): 118 | if self.__dict__['width'] and self.__dict__['height']: 119 | try: 120 | size=(int(self.__dict__['width']),int(self.__dict__['height'])) 121 | except Exception as e: 122 | print "None integer size %s:%s" %(str(self.__dict__['width']),str(+self.__dict__['height'])) 123 | size=(0,0) 124 | return size 125 | 126 | def pixelFormat(self): 127 | """ 128 | Returns a string representing the pixel format of the video stream. e.g. yuv420p. 129 | Returns none is it is not a video stream. 130 | """ 131 | f=None 132 | if self.isVideo(): 133 | if self.__dict__['pix_fmt']: 134 | f=self.__dict__['pix_fmt'] 135 | return f 136 | 137 | def frames(self): 138 | """ 139 | Returns the length of a video stream in frames. Returns 0 if not a video stream. 140 | """ 141 | f=0 142 | if self.isVideo() or self.isAudio(): 143 | if self.__dict__['nb_frames']: 144 | try: 145 | f=int(self.__dict__['nb_frames']) 146 | except Exception as e: 147 | print "None integer frame count" 148 | return f 149 | 150 | def durationSeconds(self): 151 | """ 152 | Returns the runtime duration of the video stream as a floating point number of seconds. 153 | Returns 0.0 if not a video stream. 154 | """ 155 | f=0.0 156 | if self.isVideo() or self.isAudio(): 157 | if self.__dict__['duration']: 158 | try: 159 | f=float(self.__dict__['duration']) 160 | except Exception as e: 161 | print "None numeric duration" 162 | return f 163 | 164 | def language(self): 165 | """ 166 | Returns language tag of stream. e.g. eng 167 | """ 168 | lang=None 169 | if self.__dict__['TAG:language']: 170 | lang=self.__dict__['TAG:language'] 171 | return lang 172 | 173 | def codec(self): 174 | """ 175 | Returns a string representation of the stream codec. 176 | """ 177 | codec_name=None 178 | if self.__dict__['codec_name']: 179 | codec_name=self.__dict__['codec_name'] 180 | return codec_name 181 | 182 | def codecDescription(self): 183 | """ 184 | Returns a long representation of the stream codec. 185 | """ 186 | codec_d=None 187 | if self.__dict__['codec_long_name']: 188 | codec_d=self.__dict__['codec_long_name'] 189 | return codec_d 190 | 191 | def codecTag(self): 192 | """ 193 | Returns a short representative tag of the stream codec. 194 | """ 195 | codec_t=None 196 | if self.__dict__['codec_tag_string']: 197 | codec_t=self.__dict__['codec_tag_string'] 198 | return codec_t 199 | 200 | def bitrate(self): 201 | """ 202 | Returns bitrate as an integer in bps 203 | """ 204 | b=0 205 | if self.__dict__['bit_rate']: 206 | try: 207 | b=int(self.__dict__['bit_rate']) 208 | except Exception as e: 209 | print "None integer bitrate" 210 | return b 211 | 212 | if __name__ == '__main__': 213 | print "Module ffprobe" 214 | --------------------------------------------------------------------------------