chuja 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python-version: ["3.9", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+ cache: pip
23
+
24
+ # Lightweight install: the test suite lazy-imports / mocks the heavy ML
25
+ # stack (torch, demucs), so CI skips it entirely and stays fast.
26
+ - name: Install (no ML stack)
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install pytest typer rich click
30
+ pip install -e . --no-deps
31
+
32
+ - name: Run tests
33
+ run: pytest -q
@@ -0,0 +1,35 @@
1
+ name: Publish to PyPI
2
+
3
+ # Publishes on a GitHub Release. Uses PyPI Trusted Publishing (OIDC) — no API
4
+ # token is ever stored or entered. PyPI must have a matching pending/trusted
5
+ # publisher configured for this repo + workflow (see README "Publishing").
6
+
7
+ on:
8
+ release:
9
+ types: [published]
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-latest
14
+ environment: pypi # must match the environment set on the PyPI publisher
15
+ permissions:
16
+ id-token: write # required for OIDC trusted publishing
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.12"
23
+
24
+ - name: Build sdist + wheel
25
+ run: |
26
+ python -m pip install --upgrade pip build
27
+ python -m build
28
+
29
+ - name: Verify metadata
30
+ run: |
31
+ python -m pip install twine
32
+ python -m twine check dist/*
33
+
34
+ - name: Publish to PyPI
35
+ uses: pypa/gh-action-pypi-publish@release/v1
chuja-0.1.0/.gitignore ADDED
@@ -0,0 +1,27 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+
9
+ # Virtual environments (never commit the multi-hundred-MB ML stack)
10
+ .venv/
11
+ venv/
12
+ env/
13
+
14
+ # Tooling
15
+ .pytest_cache/
16
+ .ruff_cache/
17
+ .mypy_cache/
18
+
19
+ # chuja output
20
+ stems/
21
+ *.stems/
22
+
23
+ # OS / editor
24
+ .DS_Store
25
+ *.swp
26
+ .idea/
27
+ .vscode/
chuja-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel Nakitare
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
chuja-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,202 @@
1
+ Metadata-Version: 2.4
2
+ Name: chuja
3
+ Version: 0.1.0
4
+ Summary: Separate a song into stems (vocals/drums/bass/other) from a local file — or, opt-in, from a URL.
5
+ Project-URL: Homepage, https://github.com/dnakitare/chuja
6
+ Project-URL: Issues, https://github.com/dnakitare/chuja/issues
7
+ Author: Daniel Nakitare
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: audio,demucs,karaoke,music,source-separation,stems,vocals
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
16
+ Requires-Python: >=3.9
17
+ Requires-Dist: demucs>=4.0.0
18
+ Requires-Dist: rich>=13.0.0
19
+ Requires-Dist: soundfile>=0.12.0
20
+ Requires-Dist: typer>=0.12.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
23
+ Provides-Extra: url
24
+ Requires-Dist: yt-dlp>=2024.1.1; extra == 'url'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # chuja
28
+
29
+ [![CI](https://github.com/Dnakitare/chuja/actions/workflows/ci.yml/badge.svg)](https://github.com/Dnakitare/chuja/actions/workflows/ci.yml)
30
+
31
+ Separate a song into its stems — **vocals, drums, bass, other** — from a local
32
+ audio file, or (opt-in) from a YouTube / SoundCloud / direct URL. One command,
33
+ portable output.
34
+
35
+ ![chuja mixing console](https://raw.githubusercontent.com/Dnakitare/chuja/main/docs/03-console.png)
36
+
37
+ > *The `chuja serve` mixing console — one channel strip per stem with a live
38
+ > waveform, solo/mute, faders, and sample-accurate synced playback.*
39
+
40
+ `chuja` is a thin, friendly wrapper around two excellent open-source engines:
41
+
42
+ - **[Demucs](https://github.com/facebookresearch/demucs)** (Meta) — state-of-the-art neural source separation.
43
+ - **[yt-dlp](https://github.com/yt-dlp/yt-dlp)** — used *only* for the optional URL-fetching feature.
44
+
45
+ It does not reinvent either. What it adds is the glue: one pipeline from a
46
+ source to clean, named, downloadable stem files, with sensible defaults and a
47
+ polished CLI + Python API.
48
+
49
+ ---
50
+
51
+ ## Screenshots
52
+
53
+ **Intake** — drop a file or paste a URL, pick a model / format / split:
54
+
55
+ ![chuja intake screen](https://raw.githubusercontent.com/Dnakitare/chuja/main/docs/01-intake.png)
56
+
57
+ **Progress** — a real, per-chunk separation progress bar (not a fake spinner):
58
+
59
+ ![chuja separation progress](https://raw.githubusercontent.com/Dnakitare/chuja/main/docs/02-progress.png)
60
+
61
+ **Console** — the per-stem mixing board shown at the top of this README.
62
+
63
+ ---
64
+
65
+ ## Install
66
+
67
+ Install from source (not yet published to PyPI):
68
+
69
+ ```bash
70
+ git clone https://github.com/dnakitare/chuja
71
+ cd chuja
72
+
73
+ # Core: separate LOCAL files. Pulls in Demucs (PyTorch).
74
+ pip install .
75
+
76
+ # Optional: add URL ingestion (YouTube/SoundCloud/etc.)
77
+ pip install '.[url]'
78
+ ```
79
+
80
+ ### Install globally (run `chuja` from anywhere)
81
+
82
+ ```bash
83
+ ./install.sh
84
+ ```
85
+
86
+ If this project already has a `.venv`, the installer just symlinks its `chuja`
87
+ onto your PATH (`~/.local/bin` by default) — instant, nothing re-downloaded.
88
+ With no `.venv`, it falls back to an isolated [pipx](https://pipx.pypa.io)
89
+ install. Override the link location with `CHUJA_BIN=/usr/local/bin ./install.sh`.
90
+
91
+ Prefer to do it by hand? `pipx install '.[url]'` from the project root, or
92
+ `pip install --user '.[url]'`.
93
+
94
+ ### Requirements
95
+
96
+ Requires **Python 3.9+** and **ffmpeg** on your PATH:
97
+
98
+ | Platform | Install ffmpeg |
99
+ | --- | --- |
100
+ | macOS | `brew install ffmpeg` |
101
+ | Ubuntu/Debian | `sudo apt install ffmpeg` |
102
+ | Windows | `winget install Gyan.FFmpeg` |
103
+
104
+ > The first separation downloads the model weights (~150 MB) once and caches them.
105
+
106
+ ## Usage (CLI)
107
+
108
+ ```bash
109
+ # Local file → 4 stems as WAV under ./stems/<track>/
110
+ chuja separate song.mp3
111
+
112
+ # Pick a format and bundle into a portable zip
113
+ chuja separate song.flac --format mp3 --zip -o ~/Desktop/stems
114
+
115
+ # Karaoke / acapella split: one stem + everything else
116
+ chuja separate song.mp3 --two-stems vocals
117
+
118
+ # From a URL (requires the [url] extra)
119
+ chuja separate "https://www.youtube.com/watch?v=..." --format mp3
120
+
121
+ # Best-quality (slower) model, force a device
122
+ chuja separate song.wav --model htdemucs_ft --device cpu
123
+
124
+ # List available models
125
+ chuja models
126
+ ```
127
+
128
+ ## Usage (library)
129
+
130
+ ```python
131
+ import chuja
132
+
133
+ result = chuja.separate(
134
+ "song.mp3",
135
+ out_dir="stems",
136
+ fmt="mp3",
137
+ two_stems=None, # or "vocals" for a 2-stem split
138
+ zip_output=True,
139
+ )
140
+ print(result.track) # "song"
141
+ print(result.stems) # {"vocals": Path(...), "drums": Path(...), ...}
142
+ print(result.archive) # Path("stems/song.zip")
143
+ ```
144
+
145
+ ## Models
146
+
147
+ | Model | Stems | Notes |
148
+ | --- | --- | --- |
149
+ | `htdemucs` *(default)* | 4 | Best balance of speed and quality |
150
+ | `htdemucs_ft` | 4 | Fine-tuned — best quality, ~4× slower |
151
+ | `htdemucs_6s` | 6 | Adds piano + guitar (experimental) |
152
+ | `mdx_extra` | 4 | Alternative MDX-challenge model |
153
+
154
+ ## A note on quality
155
+
156
+ Separation quality is bounded by your **source** quality. Demucs is excellent,
157
+ but it cannot recover information that lossy compression already discarded — a
158
+ 128 kbps MP3 in means audible artifacts in the stems out. Feed it the highest-
159
+ fidelity source you have (WAV/FLAC > 320 kbps MP3 > a low-bitrate stream) for
160
+ the cleanest results. `chuja` deliberately does **not** transcode before
161
+ separation, so it never throws away quality you started with.
162
+
163
+ Performance: separation is compute-heavy. It runs on CPU everywhere, and uses
164
+ your GPU automatically when available — **CUDA** (NVIDIA) or **MPS** (Apple
165
+ Silicon). GPU is many times faster than CPU for full songs.
166
+
167
+ > **Platform note:** developed and tested on **macOS** (CPU and Apple
168
+ > Silicon/MPS). The code is written to be cross-platform — its dependencies
169
+ > (Demucs/PyTorch, soundfile, ffmpeg) all ship for Linux and Windows — but
170
+ > separation hasn't been exercised on those yet. CI runs the test suite on
171
+ > Linux. Reports from other platforms are welcome.
172
+
173
+ ## Responsible use
174
+
175
+ The optional URL feature uses `yt-dlp`. Downloading content from YouTube,
176
+ SoundCloud, and similar platforms may violate their Terms of Service, and the
177
+ audio is almost always copyrighted. **You are solely responsible** for ensuring
178
+ you have the right to download and process any audio you give to `chuja`
179
+ (e.g. your own recordings, public-domain works, or content you are licensed to
180
+ use). The core install ships *without* this capability for exactly this reason.
181
+
182
+ ## Releasing (maintainers)
183
+
184
+ Releases publish to PyPI via **Trusted Publishing** (OIDC) — no API token is
185
+ ever stored. One-time setup on PyPI
186
+ ([Publishing settings](https://pypi.org/manage/account/publishing/) → add a
187
+ *pending publisher*):
188
+
189
+ | Field | Value |
190
+ | --- | --- |
191
+ | PyPI project name | `chuja` |
192
+ | Owner | `Dnakitare` |
193
+ | Repository name | `chuja` |
194
+ | Workflow name | `release.yml` |
195
+ | Environment name | `pypi` |
196
+
197
+ Then publish a version by cutting a GitHub Release (e.g. tag `v0.1.0`). The
198
+ `release.yml` workflow builds the sdist + wheel and uploads them automatically.
199
+
200
+ ## License
201
+
202
+ MIT.
chuja-0.1.0/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # chuja
2
+
3
+ [![CI](https://github.com/Dnakitare/chuja/actions/workflows/ci.yml/badge.svg)](https://github.com/Dnakitare/chuja/actions/workflows/ci.yml)
4
+
5
+ Separate a song into its stems — **vocals, drums, bass, other** — from a local
6
+ audio file, or (opt-in) from a YouTube / SoundCloud / direct URL. One command,
7
+ portable output.
8
+
9
+ ![chuja mixing console](https://raw.githubusercontent.com/Dnakitare/chuja/main/docs/03-console.png)
10
+
11
+ > *The `chuja serve` mixing console — one channel strip per stem with a live
12
+ > waveform, solo/mute, faders, and sample-accurate synced playback.*
13
+
14
+ `chuja` is a thin, friendly wrapper around two excellent open-source engines:
15
+
16
+ - **[Demucs](https://github.com/facebookresearch/demucs)** (Meta) — state-of-the-art neural source separation.
17
+ - **[yt-dlp](https://github.com/yt-dlp/yt-dlp)** — used *only* for the optional URL-fetching feature.
18
+
19
+ It does not reinvent either. What it adds is the glue: one pipeline from a
20
+ source to clean, named, downloadable stem files, with sensible defaults and a
21
+ polished CLI + Python API.
22
+
23
+ ---
24
+
25
+ ## Screenshots
26
+
27
+ **Intake** — drop a file or paste a URL, pick a model / format / split:
28
+
29
+ ![chuja intake screen](https://raw.githubusercontent.com/Dnakitare/chuja/main/docs/01-intake.png)
30
+
31
+ **Progress** — a real, per-chunk separation progress bar (not a fake spinner):
32
+
33
+ ![chuja separation progress](https://raw.githubusercontent.com/Dnakitare/chuja/main/docs/02-progress.png)
34
+
35
+ **Console** — the per-stem mixing board shown at the top of this README.
36
+
37
+ ---
38
+
39
+ ## Install
40
+
41
+ Install from source (not yet published to PyPI):
42
+
43
+ ```bash
44
+ git clone https://github.com/dnakitare/chuja
45
+ cd chuja
46
+
47
+ # Core: separate LOCAL files. Pulls in Demucs (PyTorch).
48
+ pip install .
49
+
50
+ # Optional: add URL ingestion (YouTube/SoundCloud/etc.)
51
+ pip install '.[url]'
52
+ ```
53
+
54
+ ### Install globally (run `chuja` from anywhere)
55
+
56
+ ```bash
57
+ ./install.sh
58
+ ```
59
+
60
+ If this project already has a `.venv`, the installer just symlinks its `chuja`
61
+ onto your PATH (`~/.local/bin` by default) — instant, nothing re-downloaded.
62
+ With no `.venv`, it falls back to an isolated [pipx](https://pipx.pypa.io)
63
+ install. Override the link location with `CHUJA_BIN=/usr/local/bin ./install.sh`.
64
+
65
+ Prefer to do it by hand? `pipx install '.[url]'` from the project root, or
66
+ `pip install --user '.[url]'`.
67
+
68
+ ### Requirements
69
+
70
+ Requires **Python 3.9+** and **ffmpeg** on your PATH:
71
+
72
+ | Platform | Install ffmpeg |
73
+ | --- | --- |
74
+ | macOS | `brew install ffmpeg` |
75
+ | Ubuntu/Debian | `sudo apt install ffmpeg` |
76
+ | Windows | `winget install Gyan.FFmpeg` |
77
+
78
+ > The first separation downloads the model weights (~150 MB) once and caches them.
79
+
80
+ ## Usage (CLI)
81
+
82
+ ```bash
83
+ # Local file → 4 stems as WAV under ./stems/<track>/
84
+ chuja separate song.mp3
85
+
86
+ # Pick a format and bundle into a portable zip
87
+ chuja separate song.flac --format mp3 --zip -o ~/Desktop/stems
88
+
89
+ # Karaoke / acapella split: one stem + everything else
90
+ chuja separate song.mp3 --two-stems vocals
91
+
92
+ # From a URL (requires the [url] extra)
93
+ chuja separate "https://www.youtube.com/watch?v=..." --format mp3
94
+
95
+ # Best-quality (slower) model, force a device
96
+ chuja separate song.wav --model htdemucs_ft --device cpu
97
+
98
+ # List available models
99
+ chuja models
100
+ ```
101
+
102
+ ## Usage (library)
103
+
104
+ ```python
105
+ import chuja
106
+
107
+ result = chuja.separate(
108
+ "song.mp3",
109
+ out_dir="stems",
110
+ fmt="mp3",
111
+ two_stems=None, # or "vocals" for a 2-stem split
112
+ zip_output=True,
113
+ )
114
+ print(result.track) # "song"
115
+ print(result.stems) # {"vocals": Path(...), "drums": Path(...), ...}
116
+ print(result.archive) # Path("stems/song.zip")
117
+ ```
118
+
119
+ ## Models
120
+
121
+ | Model | Stems | Notes |
122
+ | --- | --- | --- |
123
+ | `htdemucs` *(default)* | 4 | Best balance of speed and quality |
124
+ | `htdemucs_ft` | 4 | Fine-tuned — best quality, ~4× slower |
125
+ | `htdemucs_6s` | 6 | Adds piano + guitar (experimental) |
126
+ | `mdx_extra` | 4 | Alternative MDX-challenge model |
127
+
128
+ ## A note on quality
129
+
130
+ Separation quality is bounded by your **source** quality. Demucs is excellent,
131
+ but it cannot recover information that lossy compression already discarded — a
132
+ 128 kbps MP3 in means audible artifacts in the stems out. Feed it the highest-
133
+ fidelity source you have (WAV/FLAC > 320 kbps MP3 > a low-bitrate stream) for
134
+ the cleanest results. `chuja` deliberately does **not** transcode before
135
+ separation, so it never throws away quality you started with.
136
+
137
+ Performance: separation is compute-heavy. It runs on CPU everywhere, and uses
138
+ your GPU automatically when available — **CUDA** (NVIDIA) or **MPS** (Apple
139
+ Silicon). GPU is many times faster than CPU for full songs.
140
+
141
+ > **Platform note:** developed and tested on **macOS** (CPU and Apple
142
+ > Silicon/MPS). The code is written to be cross-platform — its dependencies
143
+ > (Demucs/PyTorch, soundfile, ffmpeg) all ship for Linux and Windows — but
144
+ > separation hasn't been exercised on those yet. CI runs the test suite on
145
+ > Linux. Reports from other platforms are welcome.
146
+
147
+ ## Responsible use
148
+
149
+ The optional URL feature uses `yt-dlp`. Downloading content from YouTube,
150
+ SoundCloud, and similar platforms may violate their Terms of Service, and the
151
+ audio is almost always copyrighted. **You are solely responsible** for ensuring
152
+ you have the right to download and process any audio you give to `chuja`
153
+ (e.g. your own recordings, public-domain works, or content you are licensed to
154
+ use). The core install ships *without* this capability for exactly this reason.
155
+
156
+ ## Releasing (maintainers)
157
+
158
+ Releases publish to PyPI via **Trusted Publishing** (OIDC) — no API token is
159
+ ever stored. One-time setup on PyPI
160
+ ([Publishing settings](https://pypi.org/manage/account/publishing/) → add a
161
+ *pending publisher*):
162
+
163
+ | Field | Value |
164
+ | --- | --- |
165
+ | PyPI project name | `chuja` |
166
+ | Owner | `Dnakitare` |
167
+ | Repository name | `chuja` |
168
+ | Workflow name | `release.yml` |
169
+ | Environment name | `pypi` |
170
+
171
+ Then publish a version by cutting a GitHub Release (e.g. tag `v0.1.0`). The
172
+ `release.yml` workflow builds the sdist + wheel and uploads them automatically.
173
+
174
+ ## License
175
+
176
+ MIT.
Binary file
Binary file
Binary file
chuja-0.1.0/install.sh ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Install `chuja` globally so you can run it from any directory.
4
+ #
5
+ # Default (fast): if this project's .venv exists, symlink the `chuja` it
6
+ # already contains onto your PATH. No re-download of the ML stack.
7
+ # Fallback (clean): if there's no .venv, do an isolated install with pipx.
8
+ #
9
+ # Override the link target with: CHUJA_BIN=/usr/local/bin ./install.sh
10
+ #
11
+ set -euo pipefail
12
+
13
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
+ BIN="${CHUJA_BIN:-$HOME/.local/bin}"
15
+
16
+ if [ -x "$HERE/.venv/bin/chuja" ]; then
17
+ mkdir -p "$BIN"
18
+ ln -sf "$HERE/.venv/bin/chuja" "$BIN/chuja"
19
+ echo "✓ Linked chuja → $BIN/chuja (reuses $HERE/.venv — nothing re-downloaded)"
20
+ case ":$PATH:" in
21
+ *":$BIN:"*)
22
+ echo " Run it from anywhere: chuja"
23
+ ;;
24
+ *)
25
+ echo " ⚠ $BIN is not on your PATH yet. Add this to ~/.zshrc, then restart your shell:"
26
+ echo " export PATH=\"$BIN:\$PATH\""
27
+ ;;
28
+ esac
29
+ else
30
+ echo "No .venv here — installing in an isolated environment with pipx…"
31
+ if ! command -v pipx >/dev/null 2>&1; then
32
+ echo "✗ pipx not found. Install it first: brew install pipx (or: python3 -m pip install --user pipx)"
33
+ exit 1
34
+ fi
35
+ pipx install --force "$HERE"
36
+ pipx inject chuja yt-dlp # optional URL-ingestion support
37
+ echo "✓ Installed with pipx. Run: chuja"
38
+ fi
39
+
40
+ echo
41
+ echo "Try: chuja # interactive"
42
+ echo " chuja serve # visual console"
43
+ echo " chuja song.mp3 # separate a file"
@@ -0,0 +1,50 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "chuja"
7
+ version = "0.1.0"
8
+ description = "Separate a song into stems (vocals/drums/bass/other) from a local file — or, opt-in, from a URL."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Daniel Nakitare" }]
13
+ keywords = ["stems", "source-separation", "demucs", "audio", "music", "vocals", "karaoke"]
14
+ classifiers = [
15
+ "Environment :: Console",
16
+ "Intended Audience :: End Users/Desktop",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Topic :: Multimedia :: Sound/Audio :: Analysis",
20
+ ]
21
+
22
+ # Core stays deliberately lean and legally unambiguous: separate a LOCAL file.
23
+ dependencies = [
24
+ "demucs>=4.0.0",
25
+ "soundfile>=0.12.0",
26
+ "typer>=0.12.0",
27
+ "rich>=13.0.0",
28
+ ]
29
+
30
+ [project.optional-dependencies]
31
+ # URL ingestion (YouTube/SoundCloud/etc.) is opt-in. You are responsible for
32
+ # complying with each platform's Terms of Service and applicable copyright law.
33
+ url = ["yt-dlp>=2024.1.1"]
34
+ dev = ["pytest>=8.0.0"]
35
+
36
+ [project.scripts]
37
+ chuja = "chuja.cli:app"
38
+
39
+ [project.urls]
40
+ Homepage = "https://github.com/dnakitare/chuja"
41
+ Issues = "https://github.com/dnakitare/chuja/issues"
42
+
43
+ [tool.hatch.build.targets.wheel]
44
+ packages = ["src/chuja"]
45
+
46
+ [tool.hatch.build.targets.wheel.force-include]
47
+ "src/chuja/web/console.html" = "chuja/web/console.html"
48
+
49
+ [tool.pytest.ini_options]
50
+ testpaths = ["tests"]
@@ -0,0 +1,33 @@
1
+ """chuja — separate a song into stems from a local file or (opt-in) a URL.
2
+
3
+ >>> import chuja
4
+ >>> result = chuja.separate("song.mp3", out_dir="stems", fmt="mp3")
5
+ >>> result.stems
6
+ {'drums': PosixPath('stems/song/drums.mp3'), ...}
7
+ """
8
+
9
+ from .errors import (
10
+ ExportError,
11
+ FetchError,
12
+ MissingDependencyError,
13
+ SeparationError,
14
+ SourceError,
15
+ ChujaError,
16
+ )
17
+ from .pipeline import Result, separate
18
+ from .separator import MODELS
19
+
20
+ __version__ = "0.1.0"
21
+
22
+ __all__ = [
23
+ "separate",
24
+ "Result",
25
+ "MODELS",
26
+ "__version__",
27
+ "ChujaError",
28
+ "SourceError",
29
+ "FetchError",
30
+ "MissingDependencyError",
31
+ "SeparationError",
32
+ "ExportError",
33
+ ]