4
# Copyright 2007 Joe Friedrichsen <pengi.films@gmail.com>
6
# This file is part of tovid.
8
"""Relate a video's bitrate, size, and play time
10
A video file (a/v stream) has three related characteristics:
13
3. Encoded (average) bitrate
14
These are related by their units: bitrate = size / length. This module
15
provides ways to calculate these values.
17
You can predict/calculate any one of these characteristics given the
18
other two. By default, a new AVstream object assumes you want to find
19
the average bitrate from a known play length and final size:
21
>>> avs = playtime.AVstream()
33
Usually when putting video on a disc, the final output size is well
34
defined and non-changing. By default, AVstream fixes this characteristic so
35
that you can see how the bitrate changes for different amounts of time on
38
>>> avs.set_play_length(180)
42
However, if you know the video is a certain length, you can fix that instead
43
and find how bitrates change according to different output sizes:
45
>>> avs.set_fixed_param('LENGTH')
46
>>> avs.set_final_size(2000)
50
Finally, you're not limited to finding bitrates. You can fix the bitrate and
51
see how output size and play length are related:
53
>>> avs.set_bitrate(1152, 'kbps')
54
>>> avs.set_fixed_param('RATE')
55
>>> avs.set_final_size(700)
58
>>> avs.set_play_length(120)
65
"""Video file bitrate/size/length calculator object
67
An AVstream object lets you calculate a video's bitrate, final size, or
68
play length given the other two. Usually, you want to find the bitrate,
69
and this is what AVstream does by default.
71
Once instantiated, the bitrate can be accessed in three different units:
72
AVstream.bitrate.kbps -- kilobits per second (conventional)
73
AVstream.bitrate.MiBpm -- Mibibytes per minute
74
AVstream.bitrate.GiBph -- Gibibytes per hour
76
There are four attributes:
77
play_length -- the length of the video in minutes
78
final_size -- the size of the video in MiB
79
bitrate -- the bitrate of the video
80
fixed_param -- the fixed characteristic
82
Each of these attributes have a 'set_NAME' method that should be used
83
to make changes so that the other attributes are updated automatically.
86
def __init__(self, play_length=120.0, final_size=4400.0):
87
"""Create a new AVstream object
90
[opt] play_length -- the length in minutes (default = 120.0)
91
[opt] final_size -- the final size in MiB (default = 4400.0)
94
self.play_length = play_length
95
self.final_size = final_size
96
self.bitrate = Bitrate( (final_size/play_length), 'MiBpm')
97
self.fixed_param = "SIZE"
99
def set_bitrate(self, bitrate, units):
100
"""Set the bitrate for the stream and recalculate the variables
101
according to the fixed parameter.
104
bitrate: number (integer or float ok)
105
units: the units that the bitrate is in. Valid unit arguments are
106
kbps (kilobits per second)
107
MiBpm (Mibibytes per minute)
108
GiBph (Gibibytes per hour)
111
self.bitrate.set(bitrate, units)
112
if self.fixed_param == "RATE":
114
elif self.fixed_param == "LENGTH":
115
self._calculate_final_size()
116
elif self.fixed_param == "SIZE":
117
self._calculate_play_length()
119
def set_play_length(self, play_length):
120
"""Set the play length in minutes and recalculate variables according
121
to the fixed parameter.
124
play_length -- how long the video is (minutes)
127
self.play_length = play_length
128
if self.fixed_param == "RATE":
129
self._calculate_final_size()
130
elif self.fixed_param == "LENGTH":
132
elif self.fixed_param == "SIZE":
133
self._calculate_bitrate()
135
def set_final_size(self, final_size):
136
"""Set the final size in MiB (Mebibytes) and recalculate variables
137
according to the fixed parameter.
140
final_size -- how large the final size can/should be (MiB)
143
self.final_size = final_size
144
if self.fixed_param == "RATE":
145
self._calculate_play_length()
146
elif self.fixed_param == "LENGTH":
147
self._calculate_bitrate()
148
elif self.fixed_param == "SIZE":
151
def set_fixed_param(self, param):
152
"""Set the fixed parameter of the AVstream object.
155
param -- the parameter to fix. Valid arguments are
156
RATE (the bitrate of the AVstream)
157
LENGTH (the play length of the AVstream)
158
SIZE (the final size of the AVstream)
161
valid_params = ["RATE", "SIZE", "LENGTH"]
162
if param in valid_params:
163
self.fixed_param = param
165
print "%s: bad new fixed_param -- %s" % ('playtime', param)
166
print "%s: keeping old fixed_param -- %s" \
167
% ('playtime', self.fixed_param)
169
def _calculate_bitrate(self):
170
"""Find the bitrate given the length and size"""
171
self.bitrate.set( (self.final_size/self.play_length), 'MiBpm')
173
def _calculate_final_size(self):
174
"""Find the final size give the bitrate and length"""
175
self.final_size = self.bitrate.MiBpm * self.play_length
177
def _calculate_play_length(self):
178
"""Find the length given the bitrate and size"""
179
self.play_length = self.final_size / self.bitrate.MiBpm
182
"""Convert between different bitrate units
184
A Bitrate object stores a bitrate in three different units:
185
kbps -- kilobits per second (the conventional unit)
186
MiBpm -- Mibibytes per minute (uses for S/VCD sizes)
187
GiBph -- Gibibytes per hour (useful for DVD sizes)
189
Access these by name:
190
>>> br = playtime.Bitrate(3300)
198
Once instantiated or set with a given bitrate and unit, the other
199
remaining bitrates are automatically calculated and updated:
201
>>> br.set(1, 'GiBph')
206
def __init__(self, bitrate, unit='kbps'):
207
"""Create a new Bitrate object
210
bitrate: the bitrate (int or float ok)
211
[opt] units: a string for units that bitrate is in (default: kbps).
213
kbps (kilobits per second)
214
MiBpm (Mibibytes per minute)
215
GiBph (Gibibytes per hour)
218
self.set(bitrate, unit)
220
def set(self, bitrate, unit):
221
"""Set the bitrate in 'unit' units.
224
bitrate: new bitrate (integer or float ok)
225
units: string for units that bitrate is in. Valid arguments are
226
kbps (kilobits per second)
227
MiBpm (Mibibytes per minute)
228
GiBph (Gibibytes per hour)
230
Once set with a given bitrate and unit, the other remaining
231
bitrates are automatically calculated.
234
valid_units = ["kbps", "MiBpm", "GiBph"]
235
if unit in valid_units:
237
if self.unit == 'kbps':
241
elif self.unit == 'MiBpm':
245
elif self.unit == 'GiBph':
250
print "%s: bad new units -- %s" % ('playtime', unit)
251
print "%s: keeping old units -- %s" % ('playtime', self.unit)
252
print "%s: keeping old bitrate -- %s" % \
253
('playtime', getattr(self, self.unit))
256
"""Convert the bitrate to kbps"""
257
if self.unit == 'kbps':
259
elif self.unit == 'MiBpm':
260
bitrate = self.MiBpm * (8.0*1024.0*1024.0) / (60.0*1000.0)
261
elif self.unit == 'GiBph':
262
bitrate = self.GiBph * (8.0*1024.0*1024.0*1024.0) / (60.0*60.0*1000.0)
267
"""Convert the bitrate to MiBpm"""
268
if self.unit == 'kbps':
269
bitrate = self.kbps * (60.0*1000.0) / (8.0*1024.0*1024.0)
270
elif self.unit == 'MiBpm':
272
elif self.unit == 'GiBph':
273
bitrate = self.GiBph * 1024.0 / 60.0
278
"""Convert the bitrate to GiBph"""
279
if self.unit == 'kbps':
280
bitrate = self.kbps * (60.0*60.0*1000.0) / (8.0*1024.0*1024.0*1024.0)
281
elif self.unit == 'MiBpm':
282
bitrate = self.MiBpm * 60.0 / 1024.0
283
elif self.unit == 'GiBph':