def add_stream_property(self, stream_index, prop, value=None): direct_copy = '-vcodec copy -c:a copy -map 0' output_file = util.add_postfix(self.filename, "meta") if value is None: stream_index, value = stream_index.split(':') util.run_ffmpeg('-i "{0}" {1} -metadata:s:a:{2} {3}="{4}" "{5}"'.format( \ self.filename, direct_copy, stream_index, prop, value, output_file)) return output_file
def set_tracks_property(self, prop, **props): util.logger.debug("Set tracks properties: %s-->%s", prop, str(props)) meta = VideoFile.AV_PASSTHROUGH for idx, propval in props.items(): meta += '-metadata:s:a:{0} {1}="{2}" '.format(idx, prop, propval) output_file = util.add_postfix(self.filename, prop) util.run_ffmpeg('-i "{0}" {1} "{2}"'.format(self.filename, meta.strip(), output_file)) return output_file
def slice_horizontal(self, nbr_slices, round_to = 16, slice_pattern = 'slice'): w, h = self.get_dimensions() slice_h = max(h // nbr_slices, round_to) slices = [] nbr_slices = min(nbr_slices, (h // slice_h)+1) for i in range(nbr_slices): slicefile = util.add_postfix(self.filename, "%s.%d" % (slice_pattern, i)) self.crop(w, slice_h, 0, i * slice_h, slicefile) slices.append(slicefile) return slices
def add_audio_tracks(self, *audio_files): inputs = '-i "{0}"'.format(self.filename) maps = '-map 0' i = 1 for audio_file in audio_files: inputs += ' -i "{0}"'.format(audio_file) maps += ' -map {0}'.format(i) i += 1 output_file = util.add_postfix(self.filename, "muxed") util.run_ffmpeg('{0} {1} -dn -codec copy "{2}"'.format( inputs, maps, output_file)) return output_file
def add_metadata(self, **metadatas): # ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0 -metadata year=<year> # -metadata copyright="(c) O. Korach <year>" -metadata author="Olivier Korach" # -metadata:s:a:0 language=fre -metadata:s:a:0 title="Avec musique" # -metadata:s:v:0 language=fre -disposition:a:0 default -disposition:a:1 none "%~1.meta.mp4" util.logger.debug("Add metadata: %s", str(metadatas)) opts = VideoFile.AV_PASSTHROUGH for key, value in metadatas.items(): opts += '-metadata {0}="{1}" '.format(key, value) output_file = util.add_postfix(self.filename, "meta") util.run_ffmpeg('-i "{0}" {1} "{2}"'.format(self.filename, opts.strip(), output_file)) return output_file
def set_default_track(self, track): # ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0 # -disposition:a:0 default -disposition:a:1 none out.mp4 util.logger.debug("Set default track: %s", track) disp = VideoFile.AV_PASSTHROUGH for i in range(self.__get_number_of_audio_tracks() + 1): util.logger.debug("i = %d, nb tracks = %d", i, self.__get_number_of_audio_tracks()) is_default = "default" if i == track else "none" disp += "-disposition:a:{0} {1} ".format(i, is_default) output_file = util.add_postfix(self.filename, "track") util.run_ffmpeg('-i "{0}" {1} "{2}"'.format(self.filename, disp.strip(), output_file)) return output_file
def deshake(self, width, height, out_file, **kwargs): ''' Applies deshake video filter for width x height pixels ''' media_opts = self.get_properties() media_opts.update({ opt.media.DEINTERLACE: None, opt.media.ASPECT: self.get_aspect_ratio() }) media_opts.update(util.cleanup_options(kwargs)) if out_file is None or 'nocrop' in kwargs: output_file = util.add_postfix(self.filename, "deshake_%dx%d" % (width, height)) else: output_file = out_file ffopts = opt.media2ffmpeg(media_opts) cmd = '-i "%s" %s %s "%s"' % (self.filename, \ util.dict2str(ffopts), get_deshake_filter_options(width, height), output_file) util.run_ffmpeg(cmd) if 'nocrop' not in kwargs: return output_file new_w = self.get_width() - width new_h = self.get_height() - height if out_file is None: output_file2 = util.add_postfix( self.filename, "deshake_crop_%dx%d" % (new_w, new_h)) else: output_file2 = out_file deshake_file_o = VideoFile(output_file) kwargs.update({opt.media.ASPECT: self.get_aspect_ratio()}) deshake_file_o.crop(new_w, new_h, width // 2, height // 2, output_file2, **kwargs) os.remove(output_file) return output_file2
def encode_album_art(source_file, album_art_file, **kwargs): """Encodes album art image in an audio file after optionally resizing""" # profile = 'album_art' - # For the future, we'll use the cmd line associated to the profile in the config file album_art_std_settings = '-metadata:s:v title="Album cover" -metadata:s:v comment="Cover (Front)"' target_file = util.add_postfix(source_file, 'album_art') if kwargs['scale'] is not None: w, h = re.split("x", kwargs['scale']) album_art_file = image.rescale(album_art_file, int(w), int(h)) delete_aa_file = True # ffmpeg -i %1 -i %2 -map 0:0 -map 1:0 -c copy -id3v2_version 3 -metadata:s:v title="Album cover" # -metadata:s:v comment="Cover (Front)" %1.mp3 util.run_ffmpeg('-i "%s" -i "%s" -map 0:0 -map 1:0 -c copy -id3v2_version 3 %s "%s"' % \ (source_file, album_art_file, album_art_std_settings, target_file)) shutil.copy(target_file, source_file) os.remove(target_file) if delete_aa_file: os.remove(album_art_file)
def build_target_file(source_file, profile): extension = util.get_profile_extension(profile) if extension is None: extension = util.get_file_extension(source_file) return util.add_postfix(source_file, profile, extension)