def generate_clip(self, song: Song, start: int, end: int) -> Path: """Create one clip from an existing MP3 file.""" assert song.filepath is not None album: Optional[str] = song.album if album is None: album = song.filepath.parent.name assert album is not None album = Song.clean(album) dest_dir = self.options.clip_destination_dir(album) filename = song.filename if filename is None or filename == '': filename = song.filepath.name assert filename is not None assert filename != '' if not dest_dir.exists(): dest_dir.mkdir(parents=True) dest_path = dest_dir / filename metadata = Metadata(artist=Song.clean(song.artist), title=Song.clean(song.title), album=album) with self.mp3.create(dest_path, metadata=metadata) as output: src = self.mp3.use(song).clip(start, end) src = src.normalize(0) output.append(src) output.generate() return dest_path
def _sort_level(self, parent: str, column: str, reverse: bool) -> None: """ Sort specified directory level and then any children of that level. """ # create tuple of the value of selected column + its ID for # each item at this level of the tree has_children = False pairs: List[Tuple[str, str]] = [] for ref_id in self.tree.get_children(parent): value = Song.clean(self.tree.set(ref_id, column)).lower() pairs.append(( value, ref_id, )) children = self.tree.get_children(ref_id) if children: self._sort_level(ref_id, column, reverse) has_children = True if has_children and column != 'filename': return pairs.sort(reverse=reverse) # rearrange items into sorted positions for index, (_, ref_id) in enumerate(pairs): self.tree.move(ref_id, parent, index)
def generate_clip(self, song: Song, start: int, end: int) -> Path: """Create one clip from an existing MP3 file.""" album: Optional[str] = song.album if album is None: album = song.fullpath.parent.name assert album is not None album = Song.clean(album) dest_dir = self.options.clip_destination_dir(album) filename = song.filename assert filename is not None assert filename != '' if not dest_dir.exists(): dest_dir.mkdir(parents=True) dest_path = dest_dir / filename metadata = song.as_dict(exclude={'filename', 'ref_id'}) metadata['album'] = album if start > int(song.duration): raise ValueError( f'{start} is beyond the duration of song "{song.title}"') with self.mp3.create(dest_path, metadata=Metadata(**metadata)) as output: src = self.mp3.use(song).clip(start, end) output.append(src) output.generate() return dest_path
def _generate(self, destination: MP3FileWriter, progress: Progress) -> None: """generate output file, combining all input files""" output: Optional[AudioSegment] = None num_files = float(len(destination._files)) for index, mp3file in enumerate(destination._files, 1): progress.pct = 50.0 * index / num_files progress.text = f'Adding {mp3file.filename.name}' if progress.abort: return seg = AudioSegment.from_mp3(str(mp3file.filename)) if mp3file.start is not None: if mp3file.end is not None: seg = seg[mp3file.start:mp3file.end] else: seg = seg[mp3file.start:] elif mp3file.end is not None: seg = seg[:mp3file.end] if mp3file.headroom is not None: seg = seg.normalize(mp3file.headroom) if output is None: output = seg else: output += seg tags = None if destination._metadata is not None: tags = { "artist": Song.clean(destination._metadata.artist), "title": Song.clean(destination._metadata.title) } if destination._metadata.album: tags["album"] = Song.clean(destination._metadata.album) assert output is not None progress.text = f'Encoding MP3 file "{destination.filename.name}"' progress.pct = 50.0 if progress.abort: return dest_dir = destination.filename.parent if not dest_dir.exists(): dest_dir.mkdir(parents=True) output.export(str(destination.filename), format="mp3", bitrate=destination.bitrate, tags=tags) progress.pct = 100.0
def generate(self, songs: List[Song]) -> List[Path]: """ Generate all clips for all selected Songs Returns list of filenames of new clips """ total_songs = len(songs) clips: List[Path] = [] start = int(Duration(self.options.clip_start)) end = start + 1000 * self.options.clip_duration for index, song in enumerate(songs): self.progress.text = '{} ({:d}/{:d})'.format( Song.clean(song.title), index, total_songs) self.progress.pct = 100.0 * float(index) / float(total_songs) #pylint: disable=broad-except try: clips.append(self.generate_clip(song, start, end)) except InvalidMP3Exception as err: traceback.print_exc() print(r'Error generating clip: {0} - {1}'.format( Song.clean(song.title), str(err))) self.progress.pct = 100.0 self.progress.text = 'Finished generating clips' return clips