Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3.8
- """
- Got my inspiration from this video: https://www.youtube.com/watch?v=El4zsUZjsDc
- The pinned comment contains a list in a format of:
- hh:mm:ss Title ...
- You need pydub and ffmpeg installed.
- # pip install pydub --user # or in a venv
- Thanks to this project: http://pydub.com/
- Just needed to read the doc for 20 seconds to understand how it works
- Very nice API
- I extended it with Path support.
- Also I tried the new walrus operator
- Google for: Python Named Assignment Expression
- or: PEP 572
- + A little bit decorator magic.
- And some other stuff you would never use in production.
- """
- import sys
- import re
- from argparse import ArgumentParser
- from itertools import tee
- from pathlib import Path
- from shutil import which
- from pydub import AudioSegment
- def pathlib_compat(method):
- def inner(cls, file, format):
- if isinstance(file, Path):
- file = str(file)
- if format and format.startswith('.'):
- format = format[1:]
- return method(cls, file, format)
- return inner
- class AudioSegmentPath:
- def __init__(self, data):
- self.data = data
- @classmethod
- @pathlib_compat
- def from_file(cls, file, format):
- data = AudioSegment.from_file(file, format)
- return cls(data)
- @pathlib_compat
- def export(self, file, format):
- self.data.export(file, format)
- def __getitem__(self, miliseconds):
- return self.__class__(self.data[miliseconds])
- def parse_segment_file(file):
- regex = re.compile(r'(\d{2}):(\d{2}):(\d{2}) (.*$)')
- with file.open() as fd:
- timestamps = []
- titles = []
- for line in fd:
- if (match := regex.search(line)):
- *timestamp, title = match.groups()
- hh, mm, ss = map(int, timestamp)
- miliseconds = 1000 * (hh * 3600 + mm * 60 + ss)
- timestamps.append(miliseconds)
- titles.append(title.strip())
- timestamps.append(None)
- last, current = tee(timestamps)
- next(current)
- slices = [slice(start, stop) for start, stop in zip(last, current)]
- return zip(titles, slices)
- def split_audio(file):
- print(f'Opening {file}')
- song = AudioSegmentPath.from_file(file, file.suffix)
- print(f'File loaded, splitting now')
- for index, (title, segment) in enumerate(parse_segment_file(file.with_suffix('.segment')), start=1):
- song_segment = song[segment]
- title = f'{index} {title}'
- destination = file.with_name(title).with_suffix(file.suffix)
- song_segment.export(destination, file.suffix)
- print(f'Written {destination.name}')
- def main(file):
- file = Path(file).absolute()
- if not which('ffmpeg'):
- print(f'ffmpeg is missing or not in path', file=sys.stderr)
- return 3
- if not file.exists():
- print(f'File {file.name} does not exist', file=sys.stderr)
- return 1
- if not (segment_file := file.with_suffix('.segment')).exists():
- print(f'Segmentfile {segment_file.name} is missing')
- return 2
- split_audio(file)
- return 0
- if __name__ == '__main__':
- parser = ArgumentParser(description='Split a audio')
- parser.add_argument('file', help='Audio file to split')
- args = parser.parse_args()
- sys.exit(main(args.file))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement