From 5b0bb2517733b235ba0565e63b5f15a557e2eefd Mon Sep 17 00:00:00 2001 From: Maxim Vershinin Date: Wed, 29 Jul 2026 20:05:17 +0500 Subject: [PATCH 1/4] Test docker image, basic functionality --- .dockerignore | 40 ++++++++++++++++++++++++++++++++++ Dockerfile | 51 ++++++++++++++++++++++++++++++++++++++++++++ docker-entrypoint.sh | 17 +++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100755 docker-entrypoint.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e095cb7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,40 @@ +# Git +.git/ +.gitignore + +# Python cache +*.pyc +__pycache__/ +*.pyo +*.pyd + +# Build artifacts +build/ +dist/ +*.egg-info/ +.eggs/ + +# Virtual environments +.venv +venv/ +env/ +ENV/ + +# IDE +.vscode/ +.idea/ +*.swp + +# License (not needed for installation) +LICENSE + +# Docker files (not needed in build context) +Dockerfile +.dockerignore + +# Local test files +*.mp3 +*.flac +*.wav +*.txt +*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0a369c5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,51 @@ +FROM python:3.13-slim + +# Install FFmpeg and dependencies (gosu will be downloaded separately) +RUN apt-get update && \ + apt-get install -y --no-install-recommends ffmpeg ca-certificates wget gpg && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Install gosu (lightweight tool for dropping privileges) +RUN set -eux; \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.17/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.17/gosu-$dpkgArch.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version + +# Set Python environment variables +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +# Set working directory +WORKDIR /app + +# Copy package metadata and source code +COPY setup.py pyproject.toml README.md ./ +COPY audio_splitter/ ./audio_splitter/ + +# Install the package +RUN pip install --no-cache-dir . + +# Create a non-root user with UID 1000 +RUN addgroup --system --gid 1000 appgroup && \ + adduser --system --uid 1000 --ingroup appgroup appuser + +# Change ownership of /app to the container user (so it can write there if needed) +RUN chown -R appuser:appgroup /app + +# Copy the entrypoint script +COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +# Set the entrypoint +ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] + +# Default command (shows help if no arguments) +CMD ["audio_splitter", "--help"] diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 0000000..34edfa6 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +# Check if we are running as root (default) +if [ "$(id -u)" = "0" ]; then + # If /data is a directory, change its ownership to the container user + if [ -d "/data" ]; then + echo "Setting ownership of /data to appuser:appgroup" + chown -R appuser:appgroup /data + fi + + # Drop privileges and run the command using gosu + exec gosu appuser "$@" +else + # If not root, just run the command directly + exec "$@" +fi From 9d30844a1e6ebc7c7f35ca2a193067611c90c554 Mon Sep 17 00:00:00 2001 From: Maxim Vershinin Date: Thu, 30 Jul 2026 09:46:31 +0000 Subject: [PATCH 2/4] Docker image hardened, seems to be working stable --- .gitignore | 1 + Dockerfile | 14 ++++++++++---- docker-entrypoint.sh | 11 ++++++----- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 2e12554..3b06537 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build/ dist/ *.egg-info/ *.pyc +test_data/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 0a369c5..40cb482 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,14 @@ FROM python:3.13-slim -# Install FFmpeg and dependencies (gosu will be downloaded separately) +# Install FFmpeg and dependencies required for gosu installation RUN apt-get update && \ - apt-get install -y --no-install-recommends ffmpeg ca-certificates wget gpg && \ + apt-get install -y --no-install-recommends \ + ffmpeg \ + ca-certificates \ + wget \ + gnupg \ + dirmngr \ + gnupg-agent && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -47,5 +53,5 @@ RUN chmod +x /usr/local/bin/docker-entrypoint.sh # Set the entrypoint ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] -# Default command (shows help if no arguments) -CMD ["audio_splitter", "--help"] +# Default command (shows help if no arguments provided) +CMD ["--help"] \ No newline at end of file diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 34edfa6..178ffb6 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -9,9 +9,10 @@ if [ "$(id -u)" = "0" ]; then chown -R appuser:appgroup /data fi - # Drop privileges and run the command using gosu - exec gosu appuser "$@" + # Drop privileges and run audio_splitter with the provided arguments + exec gosu appuser audio_splitter "$@" else - # If not root, just run the command directly - exec "$@" -fi + # If not root, just run audio_splitter directly + # It's not supposed to be called + exec audio_splitter "$@" +fi \ No newline at end of file From 6c72834933f8399c9cb8bbda0a566432b68bd852 Mon Sep 17 00:00:00 2001 From: Maxim Vershinin Date: Thu, 30 Jul 2026 09:57:59 +0000 Subject: [PATCH 3/4] test_data added to .dockerignore --- .dockerignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.dockerignore b/.dockerignore index e095cb7..8252870 100644 --- a/.dockerignore +++ b/.dockerignore @@ -33,6 +33,7 @@ Dockerfile .dockerignore # Local test files +test_data/ *.mp3 *.flac *.wav From bb4adb18860c778468d7a04721ddcb6ac0f5a0e1 Mon Sep 17 00:00:00 2001 From: Maxim Vershinin Date: Thu, 30 Jul 2026 10:22:01 +0000 Subject: [PATCH 4/4] README.md includes information about docker setup --- README.md | 119 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 11c6676..ba4de61 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ [![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) +[![License: GPLv3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![Docker](https://img.shields.io/badge/Docker-ready-blue.svg)](https://www.docker.com/) **Split audio files into tracks using a flexible tracklist format.** @@ -20,6 +21,8 @@ - **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 +- **Delete original** – Optionally remove the input file after successful splitting +- **Docker image** – Run without installing dependencies; simple one‑line commands --- @@ -43,8 +46,8 @@ Clone the repository and install: ```bash -git clone https://github.com/yourusername/audio-splitter.git -cd audio-splitter +git clone https://git.vmn.su/max/audio_splitter.git +cd audio_splitter pip install . ``` @@ -54,15 +57,11 @@ Now the `audio_splitter` command is available globally: audio_splitter input.mp3 tracks.txt ``` -Or run directly without installation: - -```bash -python -m audio_splitter.main input.mp3 tracklist.txt -``` +> **Tip:** For development, install in editable mode: `pip install -e .` --- -## Quick Start +## 🚀 Quick Start ### 1. Prepare a tracklist file @@ -81,9 +80,6 @@ Create a `tracks.txt` file with one track per line: ### 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 ``` @@ -147,6 +143,12 @@ Done! | `--tracklist-format FORMAT` | Custom tracklist format (default: `%ts %tn - %an`) | | `--skip-existing` | Skip extraction if output file already exists | +### Other Options + +| Option | Description | +| ------------------- | --------------------------------------------------------- | +| `--delete-original` | Delete the original input file after successful splitting | + --- ## 📝 Placeholders Reference @@ -186,7 +188,7 @@ Done! If your tracklist uses `artist - title [time]`: ```bash -python -m audio_splitter.main input.flac tracks.txt \ +audio_splitter input.flac tracks.txt \ --tracklist-format "%an - %tn [%ts]" ``` @@ -195,14 +197,14 @@ python -m audio_splitter.main input.flac tracks.txt \ Name files as `01 - Artist - Song.mp3`: ```bash -python -m audio_splitter.main input.flac tracks.txt \ +audio_splitter input.flac tracks.txt \ --output-template "%num - %an - %tn.%ext" ``` ### Override album and comment ```bash -python -m audio_splitter.main input.flac tracks.txt \ +audio_splitter input.flac tracks.txt \ --album "Greatest Hits" \ --comment "Live recording" ``` @@ -210,15 +212,21 @@ python -m audio_splitter.main input.flac tracks.txt \ ### Merge multiple comments from input file ```bash -python -m audio_splitter.main input.flac tracks.txt \ +audio_splitter input.flac tracks.txt \ --merge-comments \ --comment-separator " | " ``` +### Delete original file after splitting + +```bash +audio_splitter input.flac tracks.txt --delete-original +``` + ### Dry‑run to preview parsing ```bash -python -m audio_splitter.main input.flac tracks.txt --dry-run +audio_splitter input.flac tracks.txt --dry-run ``` Output: @@ -238,6 +246,69 @@ Dry‑run complete. No files were created. --- +## 🐳 Docker + +You can run `audio_splitter` in a Docker container without installing Python or FFmpeg on your host. + +### Pull the Image (Optional) + +```bash +docker pull yourusername/audio_splitter:latest +``` + +### Build the Image Locally + +```bash +docker build -t audio_splitter . +``` + +### Usage + +**You must mount your working directory to `/data` inside the container.** +The container will automatically adjust permissions so that you can read input files and write output files. + +Simply provide the arguments as you would to the `audio_splitter` command: + +```bash +docker run --rm -v $(pwd):/data audio_splitter /data/input.mp3 /data/tracks.txt [OPTIONS] +``` + +#### Examples + +**Basic split:** + +```bash +docker run --rm -v $(pwd):/data audio_splitter /data/input.mp3 /data/tracks.txt +``` + +**With custom options:** + +```bash +docker run --rm -v $(pwd):/data audio_splitter /data/input.mp3 /data/tracks.txt --album "Greatest Hits" --format mp3 --number-tracks +``` + +**Dry‑run:** + +```bash +docker run --rm -v $(pwd):/data audio_splitter /data/input.mp3 /data/tracks.txt --dry-run +``` + +**Help:** + +```bash +docker run --rm audio_splitter --help +``` + +### Output + +All output files are written to the mounted directory on your host (under the default `input_splits/` subdirectory, or any custom `--output-dir` you specify). + +### Permission Handling + +The container automatically adjusts ownership of the mounted `/data` directory so that the container user can read and write files there. No `--user` or `:z` flags are required. + +--- + ## 📂 Project Structure ``` @@ -252,7 +323,10 @@ audio_splitter/ ├── metadata.py # Metadata selection and building ├── formats.py # Container format decision and validation ├── core.py # Main orchestration logic -└── main.py # Command‑line interface +├── main.py # Command‑line interface +├── docker-entrypoint.sh # Docker entrypoint script +├── Dockerfile # Docker image definition +└── README.md # This file ``` --- @@ -267,13 +341,13 @@ Contributions are welcome! Please follow these steps: 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). +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. +Distributed under the GNU General Public License v3 (or later). See the [LICENSE](LICENSE) file for more details. --- @@ -281,10 +355,11 @@ Distributed under the GPU GPL v3 or later. See [LICENSE](LICENSE) for more infor - [FFmpeg](https://ffmpeg.org/) – the powerhouse behind audio processing - [Python](https://www.python.org/) – the language that makes it all possible +- [gosu](https://github.com/tianon/gosu) – privilege dropping for Docker --- ## 📬 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) +**Maintainer:** Maxim Vershinin +**Project Link:** [https://git.vmn.su/max/audio_splitter](https://git.vmn.su/max/audio_splitter)