4 Base classes for the external programs API.
14 Abstraction of the API class for the transcoder program.
23 # Recommended formats.
32 # File extensions by container. First value is for audio files and the
33 # second one is for (audio-)video files.
35 "avi": ["avi", "avi"],
36 "flv": ["flv", "flv"],
37 "mp4": ["mp4", "mp4"],
38 "ogg": ["oga", "ogv"],
39 "webm": ["webm", "webm"],
40 "mpegts": ["mts", "mts"]
52 def __init__(self, input_file, name=None, prog_bin=None):
53 self.input_file = input_file
54 if prog_bin is not None:
55 self.prog_bin = prog_bin
58 name = cis_util.get_name(input_file)
62 def transcode(self, container, a_codec=None, v_codec=None,
63 a_bitrate=None, a_samplingrate=None, a_channels=None,
64 v_bitrate=None, v_framerate=None, v_resolution=None, v_dar=None):
66 Transcodes the input file to an audio-video file.
68 container: possible values are listed in containers member as keys
69 a_codec: possible values are listed in a_codecs member as keys
70 v_codec: possible values are listed in v_codecs member as keys
71 a_bitrate: (numeric) audio bit rate
72 a_samplingrate: (numeric) audio sampling rate in Hz
73 a_channels: (numeric) number of audio channels
74 v_bitrate: (numeric) video bit rate
75 v_framerate: (numeric) number of frames per second for a video
76 v_resolution: (string) video image size as <width>x<height>
77 v_dar: video display aspect ratio as <den>x<num> or float
81 if a_codec is None and v_codec is None:
82 raise ValueError('No audio or video codec specified.')
84 if a_codec is not None and type(a_codec) is not str:
85 raise TypeError('Audio codec must be string.')
87 if v_codec is not None and type(v_codec) is not str:
88 raise TypeError('Video codec must be string.')
90 if a_samplingrate is not None and type(a_samplingrate) is not int:
91 raise TypeError('Audio sampling rate must be an integer.')
93 if a_channels is not None and type(a_channels) is not int:
94 raise TypeError('Audio channels parameter must be an integer.')
96 if v_framerate is not None and type(v_framerate) is not int:
97 raise TypeError('Video frate rate must be an integer.')
99 if v_resolution is not None \
100 and re.match('[\d]+x[\d]+', v_resolution) is None:
101 raise ValueError('Video resolution must be a string like <width>x<height>.')
103 if v_dar is not None and (type(v_dar) is not float \
104 and re.match('[\d]+:[\d]+', v_dar) is None):
105 raise ValueError('Video display aspect ratio must be a float or a string like <den>:<num>.')
107 self.output_file = self.dest_path + self.name
108 if v_resolution is not None:
109 self.output_file += '_'
110 self.output_file += v_resolution[(v_resolution.rindex('x')+1):]
111 self.output_file += 'p'
112 ext = self.tr_extension(container, (v_codec is not None))
114 self.output_file += '.' + ext
116 self._transcode(self.tr_container(container),
117 self.tr_a_codec(a_codec), self.tr_v_codec(v_codec),
118 a_bitrate, a_samplingrate, a_channels,
119 v_bitrate, v_framerate, v_resolution, v_dar)
121 def _transcode(self, container, a_codec=None, v_codec=None,
122 a_bitrate=None, a_samplingrate=None, a_channels=None,
123 v_bitrate=None, v_framerate=None, v_resolution=None, v_dar=None):
125 Called by transcode; must be overridden by a child class which
126 effectively transcodes the input file.
130 def tr_container(self, name):
131 """ Translates container API name into external program identifier."""
133 if not self.containers.has_key(name) or self.containers[name] is None:
134 raise api_exceptions.NotImplementedException("Container " + name)
136 return self.containers[name]
138 def tr_extension(self, name, video=True):
139 """ Translates container API name into file extension."""
146 if not self.extensions.has_key(name) or self.extensions[name] is None:
149 return self.extensions[name][i]
151 def tr_a_codec(self, name):
152 """ Translates audio codec API name into external program identifier."""
154 if not self.a_codecs.has_key(name) or self.a_codecs[name] is None:
155 raise api_exceptions.NotImplementedException("Audio Codec " + name)
157 return self.a_codecs[name]
159 def tr_v_codec(self, name):
160 """ Translates video codec API name into external program identifier."""
162 if not self.v_codecs.has_key(name) or self.v_codecs[name] is None:
163 raise api_exceptions.NotImplementedException("Video Codec " + name)
165 return self.v_codecs[name]
168 class BaseThumbExtractor:
170 Abstraction of the API class for the thumbnail extraction program.
172 Thumbnail extracted are in JPEG format.
180 def __init__(self, input_file, name=None, prog_bin=None):
181 self.input_file = input_file
182 if prog_bin is not None:
183 self.prog_bin = prog_bin
186 name = cis_util.get_name(input_file)
190 def extract_thumb(self, seek_pos, resolution="120x90", index=0):
192 Extracts a thumbnail from the video from a specified position
193 expressed in seconds (int/float).
195 index: an index appended to the image name in order to avoid
200 def extract_random_thumb(self, resolution="120x90", index=0):
202 Extracts a thumbnail from the video from a random position.
204 duration = self.get_video_duration()
205 seek_pos = random.random() * duration
206 self.extract_thumb(seek_pos, resolution, index)
208 def extract_summary_thumbs(self, count, resolution="120x90"):
210 Extracts a series of thumbnails from a video by taking several
213 The snapshots are taken from equally spaced positions such that
214 `count` thumbs are extracted.
216 duration = self.get_video_duration()
217 interval = duration / (count + 1)
219 n_thumbs_extracted = 0
221 for index in range (0, count):
222 thumb_extracted = True
224 self.extract_thumb(seek_pos, resolution, index)
225 except api_exceptions.ThumbExtractionException as e:
226 thumb_extracted = False
229 n_thumbs_extracted += 1
233 return n_thumbs_extracted
235 def get_output_file_name(self, index):
236 """ Returns the name required as output file name based on index. """
237 output_file_name = self.dest_path + self.name \
238 + '_t' + ("%02d" % index) + '.jpg'
239 return output_file_name
241 def get_video_duration(self):
245 class BaseFileTransferer:
247 Ensures file transfer from the Web Server to the CIS (here).
249 Several implementations can be done by extending this class for
250 file transfer protocol such as FTP, SCP, RSYNC, HTTP etc.
256 def __init__(self, local_path='', remote_path=''):
257 """ Initialize by setting local and remote paths for file transfer. """
258 self.local_path = local_path
259 self.remote_path = remote_path
264 def get(self, files):
266 Transfers files locally from the Web Server.
268 files: a list of file name strings
272 def put(self, files):
274 Transfers files from the Web Server locally.
276 files: a list of file name strings
282 This method should be called when the instance is no longer required.
284 Class's destructor calls this method.
291 def get_video_duration(input_file):
293 Returns the number of seconds of a video (int/float).