4 Base classes for the external programs API.
16 Abstraction of the API class for the transcoder program.
25 # Recommended formats.
34 # File extensions by container. First value is for audio files and the
35 # second one is for (audio-)video files.
37 "avi": ["avi", "avi"],
38 "flv": ["flv", "flv"],
39 "mp4": ["mp4", "mp4"],
40 "ogg": ["oga", "ogv"],
41 "webm": ["webm", "webm"],
42 "mpegts": ["mts", "mts"]
54 def __init__(self, input_file, name=None, prog_bin=None):
55 self.input_file = input_file
56 if prog_bin is not None:
57 self.prog_bin = prog_bin
60 name = cis_util.get_name(input_file)
64 def transcode(self, container, a_codec=None, v_codec=None,
65 a_bitrate=None, a_samplingrate=None, a_channels=None,
66 v_bitrate=None, v_framerate=None, v_resolution=None, v_dar=None):
68 Transcodes the input file to an audio-video file.
70 @param container: possible values are listed in containers member
72 @param a_codec possible values are listed in a_codecs member as keys
73 @param v_codec possible values are listed in v_codecs member as keys
74 @param a_bitrate (numeric) audio bit rate
75 @param a_samplingrate (numeric) audio sampling rate in Hz
76 @param a_channels (numeric) number of audio channels
77 @param v_bitrate (numeric) video bit rate
78 @param v_framerate (numeric) number of frames per second for a video
79 @param v_resolution (string) video image size as <width>x<height>
80 @param v_dar video display aspect ratio as <den>x<num> or float
81 @return output file name
85 if a_codec is None and v_codec is None:
86 raise ValueError('No audio or video codec specified.')
88 if a_codec is not None and type(a_codec) not in [str, unicode]:
89 raise TypeError('Audio codec must be string.')
91 if v_codec is not None and type(v_codec) not in [str, unicode]:
92 raise TypeError('Video codec must be string.')
94 if a_samplingrate is not None and type(a_samplingrate) is not int:
95 raise TypeError('Audio sampling rate must be an integer.')
97 if a_channels is not None and type(a_channels) is not int:
98 raise TypeError('Audio channels parameter must be an integer.')
100 if v_framerate is not None and type(v_framerate) is not int:
101 raise TypeError('Video frate rate must be an integer.')
103 if v_resolution is not None \
104 and re.match('[\d]+x[\d]+', v_resolution) is None:
105 raise ValueError('Video resolution must be a string like <width>x<height>.')
107 if v_dar is not None and (type(v_dar) is not float \
108 and re.match('[\d]+:[\d]+', v_dar) is None):
109 raise ValueError('Video display aspect ratio must be a float or a string like <den>:<num>.')
111 self.output_file = os.path.join(self.dest_path, self.name)
112 if v_resolution is not None:
113 self.output_file += '_'
114 self.output_file += v_resolution[(v_resolution.rindex('x')+1):]
115 self.output_file += 'p'
116 ext = self.tr_extension(container, (v_codec is not None))
118 self.output_file += '.' + ext
120 return self._transcode(self.tr_container(container),
121 self.tr_a_codec(a_codec), self.tr_v_codec(v_codec),
122 a_bitrate, a_samplingrate, a_channels,
123 v_bitrate, v_framerate, v_resolution, v_dar)
125 def _transcode(self, container, a_codec=None, v_codec=None,
126 a_bitrate=None, a_samplingrate=None, a_channels=None,
127 v_bitrate=None, v_framerate=None, v_resolution=None, v_dar=None):
129 Called by transcode; must be overridden by a child class which
130 effectively transcodes the input file.
132 @return output file name
136 def tr_container(self, name):
137 """ Translates container API name into external program identifier."""
139 if not self.containers.has_key(name) or self.containers[name] is None:
140 raise api_exceptions.NotImplementedException("Container " + name)
142 return self.containers[name]
144 def tr_extension(self, name, video=True):
145 """ Translates container API name into file extension."""
152 if not self.extensions.has_key(name) or self.extensions[name] is None:
155 return self.extensions[name][i]
157 def tr_a_codec(self, name):
158 """ Translates audio codec API name into external program identifier."""
160 if not self.a_codecs.has_key(name) or self.a_codecs[name] is None:
161 raise api_exceptions.NotImplementedException("Audio Codec " + name)
163 return self.a_codecs[name]
165 def tr_v_codec(self, name):
166 """ Translates video codec API name into external program identifier."""
168 if not self.v_codecs.has_key(name) or self.v_codecs[name] is None:
169 raise api_exceptions.NotImplementedException("Video Codec " + name)
171 return self.v_codecs[name]
174 class BaseThumbExtractor:
176 Abstraction of the API class for the thumbnail extraction program.
178 Thumbnail extracted are in JPEG format.
186 def __init__(self, input_file, name=None, prog_bin=None):
187 self.input_file = input_file
188 if prog_bin is not None:
189 self.prog_bin = prog_bin
192 name = cis_util.get_name(input_file)
196 def extract_thumb(self, seek_pos, resolution="120x90", index=0):
198 Extracts a thumbnail from the video from a specified position
199 expressed in seconds (int/float).
201 index: an index appended to the image name in order to avoid
206 def extract_random_thumb(self, resolution="120x90", index=0):
208 Extracts a thumbnail from the video from a random position.
210 duration = self.get_video_duration()
211 seek_pos = random.random() * duration
212 self.extract_thumb(seek_pos, resolution, index)
214 def extract_summary_thumbs(self, count, resolution="120x90"):
216 Extracts a series of thumbnails from a video by taking several
219 The snapshots are taken from equally spaced positions such that
220 `count` thumbs are extracted.
222 duration = self.get_video_duration()
223 interval = duration / (count + 1)
225 n_thumbs_extracted = 0
227 for index in range (0, count):
228 thumb_extracted = True
230 self.extract_thumb(seek_pos, resolution, n_thumbs_extracted)
231 except api_exceptions.ThumbExtractionException as e:
232 thumb_extracted = False
235 n_thumbs_extracted += 1
239 return n_thumbs_extracted
241 def get_output_file_name(self, index):
242 """ Returns the name required as output file name based on index. """
243 output_file_name = os.path.join(self.dest_path, self.name) \
244 + '_t' + ("%02d" % index) + '.jpg'
245 return output_file_name
247 def get_video_duration(self):
251 class BaseFileTransferer:
253 Ensures file transfer from the Web Server to the CIS (here).
255 Several implementations can be done by extending this class for
256 file transfer protocol such as FTP, SCP, RSYNC, HTTP etc.
262 def __init__(self, local_path='', remote_path=''):
263 """ Initialize by setting local and remote paths for file transfer. """
264 self.local_path = local_path
265 self.remote_path = remote_path
270 def get(self, files):
272 Transfers files locally from the Web Server.
274 files: a list of file name strings
278 def put(self, files):
280 Transfers files from the Web Server locally.
282 files: a list of file name strings
288 This method should be called when the instance is no longer required.
290 Class's destructor calls this method.
297 def get_video_duration(input_file, formated=False):
299 Returns the number of seconds of a video (int/float) if formated is
300 False and a string for duration formated as [HH:]:mm:ss otherwise.