# 🎵 Audio Splitter [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/) [![FFmpeg](https://img.shields.io/badge/FFmpeg-required-green.svg)](https://ffmpeg.org/) [![License: MIT](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://opensource.org/license/gpl-3.0) **Split audio files into tracks using a flexible tracklist format.** > A powerful command‑line tool that reads a tracklist (with timestamps) and splits an audio file into individual tracks. Supports multiple audio/video containers, metadata writing, and fully customisable input/output formats. --- ## ✨ Features - **Flexible tracklist parsing** – Define your own format with placeholders (`%ts`, `%tn`, `%an`, `%al`, `%date`, `%ext`) - **Timestamp support** – Handle both `start-only` (`00:00`) and `start:end` (`00:00-01:30`) timestamps - **Multiple stream support** – Preserve audio, video, and subtitle streams (or drop them selectively) - **Metadata writing** – Write `title`, `artist`, `album`, `date`, `track`, and `comment` to output files - **Custom output filenames** – Define your own naming template using placeholders (`%an-%tn.%ext`) - **Character replacement** – Replace problematic filename characters with a custom character - **Dry‑run mode** – Preview parsed tracks without splitting - **Skip existing files** – Avoid overwriting already‑extracted tracks --- ## 📦 Installation ### Prerequisites - **Python 3.8 or higher** - **FFmpeg** – required for audio processing ### Install FFmpeg | OS | Command | | -------------------- | ------------------------------------------------------------ | | **Ubuntu/Debian** | `sudo apt install ffmpeg` | | **macOS (Homebrew)** | `brew install ffmpeg` | | **Windows** | Download from [ffmpeg.org](https://ffmpeg.org/download.html) | ### Install Audio Splitter Clone the repository and install: ```bash git clone https://git.vmn.su/max/audio_splitter.git cd audio_splitter pip install . ``` Or run directly without installation: ```bash python -m audio_splitter.main input.mp3 tracklist.txt ``` --- ## Quick Start ### 1. Prepare a tracklist file Create a `tracks.txt` file with one track per line: ``` 00:00 Intro 01:30 Song One - Artist A 04:20-06:45 Another Song - Artist B 08:10 Finale - Artist C ``` - `00:00` – start‑only timestamp (track ends at next track's start or end of file) - `04:20-06:45` – explicit start and end timestamps ### 2. Run the splitter ```bash python -m audio_splitter.main my_album.mp3 tracks.txt ``` Output: ``` Found 4 tracks. Detected streams: audio=True, video=False, subs=False Audio codec: mp3 Output container: mp3 Extracting track 1: Intro (00:00:00 - 00:01:30) -> Saved to: my_album_splits/Intro.mp3 Extracting track 2: Song One (00:01:30 - 00:04:20) -> Saved to: my_album_splits/Song One - Artist A.mp3 ... Done! ``` --- ## ⚙️ Command‑Line Options ### Basic Options | Option | Description | | ---------------------- | ------------------------------------------------------------- | | `input_file` | Input audio/video file | | `tracklist_file` | Tracklist file | | `-o, --output-dir DIR` | Output directory (default: `_splits`) | | `--format FORMAT` | Output container format (mp3, m4a, mkv, mp4, ogg, opus, etc.) | | `--transcode-to CODEC` | Re‑encode audio to CODEC (e.g., libmp3lame, aac, libopus) | | `--drop-video` | Remove video streams | | `--drop-subs` | Remove subtitle streams | | `--dry-run` | Preview parsed tracklist without splitting | ### Filename Options | Option | Description | | ---------------------------- | --------------------------------------------------------------- | | `--number-tracks` | Prepend track number (`01 - `) to filenames | | `--output-template TEMPLATE` | Custom filename template (default: `%an-%tn.%ext`) | | `--replace-bad-chars` | Replace problematic characters in filenames | | `--replacement-char CHAR` | Replacement character (default: `_`) | | `--bad-chars CHARS` | Characters to replace (default includes space and single quote) | ### Metadata Options | Option | Description | | ------------------------- | ----------------------------------------------- | | `--album ALBUM` | Set album name (overrides parsed `%al`) | | `--comment COMMENT` | Set comment text | | `--no-comment` | Ignore comment entirely | | `--comment-stream INDEX` | Select comment from a specific stream (0‑based) | | `--merge-comments` | Merge all comments from all streams | | `--comment-separator SEP` | Separator for merged comments (default: `; `) | ### Tracklist Format Options | Option | Description | | --------------------------- | -------------------------------------------------- | | `--tracklist-format FORMAT` | Custom tracklist format (default: `%ts %tn - %an`) | | `--skip-existing` | Skip extraction if output file already exists | --- ## 📝 Placeholders Reference ### Tracklist Format Placeholders (`--tracklist-format`) | Placeholder | Meaning | | ----------- | --------------------------------------------------- | | `%ts` | **Timestamp** – required (`00:00` or `00:00-01:30`) | | `%tn` | Track name | | `%an` | Author/artist | | `%al` | Album | | `%date` | Date/year | | `%ext` | File extension | **Default:** `%ts %tn - %an` ### Output Template Placeholders (`--output-template`) | Placeholder | Meaning | | ----------- | -------------------------------------- | | `%tn` | Track name | | `%an` | Author/artist | | `%al` | Album | | `%date` | Date/year | | `%ext` | File extension (without leading dot) | | `%num` | Track number (zero‑padded, e.g., `01`) | **Default:** `%an-%tn.%ext` --- ## 💡 Examples ### Custom tracklist format If your tracklist uses `artist - title [time]`: ```bash python -m audio_splitter.main input.flac tracks.txt \ --tracklist-format "%an - %tn [%ts]" ``` ### Custom output filenames Name files as `01 - Artist - Song.mp3`: ```bash python -m audio_splitter.main input.flac tracks.txt \ --output-template "%num - %an - %tn.%ext" ``` ### Override album and comment ```bash python -m audio_splitter.main input.flac tracks.txt \ --album "Greatest Hits" \ --comment "Live recording" ``` ### Merge multiple comments from input file ```bash python -m audio_splitter.main input.flac tracks.txt \ --merge-comments \ --comment-separator " | " ``` ### Dry‑run to preview parsing ```bash python -m audio_splitter.main input.flac tracks.txt --dry-run ``` Output: ``` Parsed tracklist: ------------------------------------------------------------ ts | tn | an ------------------------------------------------------------ 1 | 00:00 | Intro | 2 | 01:30 | Song One | Artist A 3 | 04:20-06:45 | Another Song | Artist B ... ------------------------------------------------------------ Dry‑run complete. No files were created. ``` --- ## 📂 Project Structure ``` audio_splitter/ ├── __init__.py # Package initialisation ├── constants.py # Global constants (FORMAT_INFO, DEFAULT_BAD_CHARS) ├── utils.py # Generic helpers (timestamps, string manipulation) ├── tracklist.py # Tracklist parsing with custom formats ├── ffmpeg.py # FFmpeg/FFprobe interactions and command building ├── timestamp.py # Timestamp parsing and resolution ├── filename.py # Output filename generation ├── metadata.py # Metadata selection and building ├── formats.py # Container format decision and validation ├── core.py # Main orchestration logic └── main.py # Command‑line interface ``` --- ## 🤝 Contributing Contributions are welcome! Please follow these steps: 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request For bug reports or feature requests, please [open an issue](https://git.vmn.su/max/audio_splitter/issues). --- ## 📄 License Distributed under the GPU GPL v3 or later. See [LICENSE](LICENSE) for more information. --- ## 🙏 Acknowledgements - [FFmpeg](https://ffmpeg.org/) – the powerhouse behind audio processing - [Python](https://www.python.org/) – the language that makes it all possible --- ## 📬 Contact **Maintainer:** [Maxim Vershinin](https://git.vmn.su/max) **Project Link:** [https://git.vmn.su/max/audio_splitter](https://git.vmn.su/max/audio_splitter)