291 lines
9.9 KiB
Markdown
291 lines
9.9 KiB
Markdown
# 🎵 Audio Splitter
|
||
|
||
[](https://www.python.org/downloads/)
|
||
[](https://ffmpeg.org/)
|
||
[](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://github.com/yourusername/audio-splitter.git
|
||
cd audio-splitter
|
||
pip install .
|
||
```
|
||
|
||
Now the `audio_splitter` command is available globally:
|
||
|
||
```bash
|
||
audio_splitter input.mp3 tracks.txt
|
||
```
|
||
|
||
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
|
||
# If not installed
|
||
python -m audio_splitter.main my_album.mp3 tracks.txt
|
||
# If installed
|
||
audio_splitter 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: `<input>_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://github.com/yourusername/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)
|