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 \
143 return self.containers[name]
145 def tr_extension(self, name, video=True):
146 """ Translates container API name into file extension."""
153 if not self.extensions.has_key(name) or self.extensions[name] is None:
156 return self.extensions[name][i]
158 def tr_a_codec(self, name):
159 """ Translates audio codec API name into external program identifier."""
161 if not self.a_codecs.has_key(name) or self.a_codecs[name] is None:
162 raise api_exceptions.NotImplementedException("Audio Codec " + name \
165 return self.a_codecs[name]
167 def tr_v_codec(self, name):
168 """ Translates video codec API name into external program identifier."""
170 if not self.v_codecs.has_key(name) or self.v_codecs[name] is None:
171 raise api_exceptions.NotImplementedException("Video Codec " + name \
174 return self.v_codecs[name]
177 class BaseThumbExtractor:
179 Abstraction of the API class for the thumbnail extraction program.
181 Thumbnail extracted are in JPEG format.
189 def __init__(self, input_file, name=None, prog_bin=None):
190 self.input_file = input_file
191 if prog_bin is not None:
192 self.prog_bin = prog_bin
195 name = cis_util.get_name(input_file)
199 def extract_thumb(self, seek_pos, resolution="120x90", index=0):
201 Extracts a thumbnail from the video from a specified position
202 expressed in seconds (int/float).
204 index: an index appended to the image name in order to avoid
209 def extract_random_thumb(self, resolution="120x90", index=0):
211 Extracts a thumbnail from the video from a random position.
213 duration = self.get_video_duration()
214 seek_pos = random.random() * duration
215 self.extract_thumb(seek_pos, resolution, index)
217 def extract_summary_thumbs(self, count, resolution="120x90"):
219 Extracts a series of thumbnails from a video by taking several
222 The snapshots are taken from equally spaced positions such that
223 `count` thumbs are extracted.
225 duration = self.get_video_duration()
226 interval = duration / (count + 1)
228 n_thumbs_extracted = 0
230 for index in range (0, count):
231 thumb_extracted = True
233 self.extract_thumb(seek_pos, resolution, n_thumbs_extracted)
234 except api_exceptions.ThumbExtractionException as e:
235 thumb_extracted = False
238 n_thumbs_extracted += 1
242 return n_thumbs_extracted
244 def get_output_file_name(self, index):
245 """ Returns the name required as output file name based on index. """
246 output_file_name = os.path.join(self.dest_path, self.name) \
247 + '_t' + ("%02d" % index) + '.jpg'
248 return output_file_name
250 def get_video_duration(self):
254 class BaseFileTransferer:
256 Ensures file transfer from the Web Server to the CIS (here).
258 Several implementations can be done by extending this class for
259 file transfer protocol such as FTP, SCP, RSYNC, HTTP etc.
265 def __init__(self, local_path='', remote_path=''):
266 """ Initialize by setting local and remote paths for file transfer. """
267 self.local_path = local_path
268 self.remote_path = remote_path
273 def get(self, files):
275 Transfers files locally from the Web Server.
277 files: a list of file name strings
281 def put(self, files):
283 Transfers files from the Web Server locally.
285 files: a list of file name strings
291 This method should be called when the instance is no longer required.
293 Class's destructor calls this method.
300 def get_video_duration(input_file, formated=False):
302 Returns the number of seconds of a video (int/float) if formated is
303 False and a string for duration formated as [HH:]:mm:ss otherwise.