Skip to content

Commit b03db1d

Browse files
committed
Packaging update
Package updates and pushed to pypi
1 parent a0d7147 commit b03db1d

File tree

4 files changed

+146
-33
lines changed

4 files changed

+146
-33
lines changed

ffprobe/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from ffprobe import FFProbe

ffprobe/ffprobe-test.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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()

ffprobe/ffprobe.py

+118-32
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#!/usr/bin/python
22
# Filename: ffprobe.py
3+
"""
4+
Python wrapper for ffprobe command line tool. ffprobe must exist in the path.
5+
"""
6+
7+
38

49
version='0.1'
510

@@ -9,90 +14,171 @@
914
import os
1015

1116
class FFProbe:
17+
"""
18+
FFProbe wraps the ffprobe command and pulls the data into an object form::
19+
metadata=FFProbe('multimedia-file.mov')
20+
"""
1221
def __init__(self,video_file):
1322
self.video_file=video_file
14-
p = subprocess.check_output(["ffprobe","-show_streams",self.video_file],stderr=subprocess.PIPE,shell=True)
15-
self.format=None
16-
self.created=None
17-
self.duration=None
18-
self.start=None
19-
self.bitrate=None
20-
self.streams=[]
21-
self.video=[]
22-
self.audio=[]
23-
datalines=[]
24-
for a in str(p.decode(sys.stdout.encoding)).split('\n'):
25-
if re.match('\[STREAM\]',a):
26-
datalines=[]
27-
elif re.match('\[\/STREAM\]',a):
28-
self.streams.append(FFStream(datalines))
29-
datalines=[]
30-
else:
31-
datalines.append(a)
32-
for a in self.streams:
33-
if a.isAudio():
34-
self.audio.append(a)
35-
if a.isVideo():
36-
self.video.append(a)
23+
try:
24+
with open(os.devnull, 'w') as tempf:
25+
subprocess.check_call(["ffprobe","-h"],stdout=tempf,stderr=tempf)
26+
except:
27+
raise IOError('ffprobe not found.')
28+
if os.path.isfile(video_file):
29+
p = subprocess.check_output(["ffprobe","-show_streams",self.video_file],stderr=subprocess.PIPE,shell=True)
30+
self.format=None
31+
self.created=None
32+
self.duration=None
33+
self.start=None
34+
self.bitrate=None
35+
self.streams=[]
36+
self.video=[]
37+
self.audio=[]
38+
datalines=[]
39+
for a in str(p.decode(sys.stdout.encoding)).split('\n'):
40+
if re.match('\[STREAM\]',a):
41+
datalines=[]
42+
elif re.match('\[\/STREAM\]',a):
43+
self.streams.append(FFStream(datalines))
44+
datalines=[]
45+
else:
46+
datalines.append(a)
47+
for a in self.streams:
48+
if a.isAudio():
49+
self.audio.append(a)
50+
if a.isVideo():
51+
self.video.append(a)
52+
else:
53+
raise IOError('No such media file '+video_file)
54+
55+
3756
class FFStream:
57+
"""
58+
An object representation of an individual stream in a multimedia file.
59+
"""
3860
def __init__(self,datalines):
3961
for a in datalines:
4062
(key,val)=a.strip().split('=')
4163
self.__dict__[key]=val
64+
4265
def isAudio(self):
66+
"""
67+
Is this stream labelled as an audio stream?
68+
"""
4369
val=False
4470
if self.__dict__['codec_type']:
4571
if str(self.__dict__['codec_type']) == 'audio':
4672
val=True
4773
return val
74+
4875
def isVideo(self):
76+
"""
77+
Is the stream labelled as a video stream.
78+
"""
4979
val=False
5080
if self.__dict__['codec_type']:
5181
if self.codec_type == 'video':
5282
val=True
5383
return val
84+
5485
def isSubtitle(self):
86+
"""
87+
Is the stream labelled as a subtitle stream.
88+
"""
5589
val=False
5690
if self.__dict__['codec_type']:
5791
if str(self.codec_type)=='subtitle':
5892
val=True
5993
return val
94+
6095
def frameSize(self):
61-
size=(0,0)
96+
"""
97+
Returns the pixel frame size as an integer tuple (width,height) if the stream is a video stream.
98+
Returns None if it is not a video stream.
99+
"""
100+
size=None
62101
if self.isVideo():
63102
if self.__dict__['width'] and self.__dict__['height']:
64103
size=(int(self.__dict__['width']),int(self.__dict__['height']))
65104
return size
105+
66106
def pixelFormat(self):
107+
"""
108+
Returns a string representing the pixel format of the video stream. e.g. yuv420p.
109+
Returns none is it is not a video stream.
110+
"""
67111
f=None
68112
if self.isVideo():
69113
if self.__dict__['pix_fmt']:
70114
f=self.__dict__['pix_fmt']
71115
return f
116+
72117
def frames(self):
118+
"""
119+
Returns the length of a video stream in frames. Returns 0 if not a video stream.
120+
"""
73121
f=0
74122
if self.isVideo() or self.isAudio():
75123
if self.__dict__['nb_frames']:
76124
f=int(self.__dict__['nb_frames'])
77125
return f
126+
78127
def durationSeconds(self):
128+
"""
129+
Returns the runtime duration of the video stream as a floating point number of seconds.
130+
Returns 0.0 if not a video stream.
131+
"""
79132
f=0.0
80133
if self.isVideo() or self.isAudio():
81134
if self.__dict__['duration']:
82135
f=float(self.__dict__['duration'])
83-
return f
136+
return f
137+
84138
def language(self):
139+
"""
140+
Returns language tag of stream. e.g. eng
141+
"""
85142
lang=None
86143
if self.__dict__['TAG:language']:
87144
lang=self.__dict__['TAG:language']
88145
return lang
89-
90-
class VideoStream:
91-
def __init__(self,probe_line):
92-
pass
93-
class AudioStream:
94-
def __init__(self,probe_line):
95-
pass
146+
147+
def codec(self):
148+
"""
149+
Returns a string representation of the stream codec.
150+
"""
151+
codec_name=None
152+
if self.__dict__['codec_name']:
153+
codec_name=self.__dict__['codec_name']
154+
return codec_name
155+
156+
def codecDescription(self):
157+
"""
158+
Returns a long representation of the stream codec.
159+
"""
160+
codec_d=None
161+
if self.__dict__['codec_long_name']:
162+
codec_d=self.__dict__['codec_long_name']
163+
return codec_d
164+
165+
def codecTag(self):
166+
"""
167+
Returns a short representative tag of the stream codec.
168+
"""
169+
codec_t=None
170+
if self.__dict__['codec_tag_string']:
171+
codec_t=self.__dict__['codec_tag_string']
172+
return codec_t
173+
174+
def bitrate(self):
175+
"""
176+
Returns bitrate as an integer in bps
177+
"""
178+
b=0
179+
if self.__dict__['bit_rate']:
180+
b=int(self.__dict__['bit_rate'])
181+
return b
96182

97183
if __name__ == '__main__':
98184
print "Module ffprobe"

setup.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,17 @@
99
author='Simon Hargreaves',
1010
author_email='[email protected]',
1111
url='http://www.simon-hargreaves.com/ffprobe',
12-
packages=['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+
])

0 commit comments

Comments
 (0)