2025-12-04 20:43:44 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
"""Local AI music generator using Meta's MusicGen.
|
|
|
|
|
|
|
|
|
|
Generates music from text prompts using the open-source MusicGen model.
|
|
|
|
|
First run will download the model (~3.3GB for medium, ~500MB for small).
|
|
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
python music_generator.py "upbeat electronic dance music with synths"
|
|
|
|
|
python music_generator.py --duration 15 "calm acoustic guitar melody"
|
|
|
|
|
python music_generator.py --model small "jazz piano solo"
|
|
|
|
|
python music_generator.py --interactive # Interactive mode
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import argparse
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
import importlib.util
|
|
|
|
|
import logging
|
2025-12-04 20:43:44 +01:00
|
|
|
from pathlib import Path
|
|
|
|
|
import sys
|
|
|
|
|
import warnings
|
|
|
|
|
|
2026-03-17 22:47:42 +01:00
|
|
|
from python_pkg.music_gen._music_generation import (
|
|
|
|
|
CROSSFADE_DURATION,
|
|
|
|
|
SEGMENT_DURATION,
|
|
|
|
|
VRAM_THRESHOLD_LARGE,
|
|
|
|
|
VRAM_THRESHOLD_MEDIUM,
|
|
|
|
|
_calculate_segment_duration,
|
|
|
|
|
_generate_long_audio,
|
|
|
|
|
crossfade_audio,
|
|
|
|
|
generate_music,
|
|
|
|
|
generate_segment,
|
|
|
|
|
get_device,
|
|
|
|
|
get_vram_gb,
|
|
|
|
|
load_model,
|
|
|
|
|
select_model_size,
|
|
|
|
|
)
|
|
|
|
|
from python_pkg.music_gen._music_speech import (
|
|
|
|
|
BARK_MAX_CHARS,
|
|
|
|
|
BARK_VOICES,
|
|
|
|
|
_generate_instrumental_for_song,
|
|
|
|
|
_generate_vocals_for_song,
|
|
|
|
|
_mix_audio,
|
|
|
|
|
_resample_audio,
|
|
|
|
|
_split_into_sentences,
|
|
|
|
|
generate_song,
|
|
|
|
|
generate_speech,
|
|
|
|
|
)
|
|
|
|
|
|
2025-12-04 20:43:44 +01:00
|
|
|
# Suppress warnings for cleaner output
|
|
|
|
|
warnings.filterwarnings("ignore", category=FutureWarning)
|
|
|
|
|
warnings.filterwarnings("ignore", category=UserWarning)
|
|
|
|
|
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
2026-03-17 22:47:42 +01:00
|
|
|
# Re-export all public symbols for backwards compatibility
|
|
|
|
|
__all__ = [
|
|
|
|
|
"BARK_MAX_CHARS",
|
|
|
|
|
"BARK_VOICES",
|
|
|
|
|
"CROSSFADE_DURATION",
|
|
|
|
|
"SEGMENT_DURATION",
|
|
|
|
|
"VRAM_THRESHOLD_LARGE",
|
|
|
|
|
"VRAM_THRESHOLD_MEDIUM",
|
|
|
|
|
"_calculate_segment_duration",
|
|
|
|
|
"_generate_instrumental_for_song",
|
|
|
|
|
"_generate_long_audio",
|
|
|
|
|
"_generate_vocals_for_song",
|
|
|
|
|
"_mix_audio",
|
|
|
|
|
"_resample_audio",
|
|
|
|
|
"_split_into_sentences",
|
|
|
|
|
"check_dependencies",
|
|
|
|
|
"crossfade_audio",
|
|
|
|
|
"generate_music",
|
|
|
|
|
"generate_segment",
|
|
|
|
|
"generate_song",
|
|
|
|
|
"generate_speech",
|
|
|
|
|
"get_device",
|
|
|
|
|
"get_vram_gb",
|
|
|
|
|
"interactive_mode",
|
|
|
|
|
"load_model",
|
|
|
|
|
"main",
|
|
|
|
|
"select_model_size",
|
|
|
|
|
]
|
2025-12-04 20:43:44 +01:00
|
|
|
|
2025-12-04 21:26:52 +01:00
|
|
|
|
|
|
|
|
def check_dependencies(*, include_bark: bool = False) -> bool:
|
|
|
|
|
"""Check if required packages are installed.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
include_bark: Whether to check for Bark dependencies as well.
|
|
|
|
|
"""
|
2025-12-04 20:43:44 +01:00
|
|
|
missing = []
|
|
|
|
|
|
2026-03-13 20:48:40 +01:00
|
|
|
if importlib.util.find_spec("torch") is None:
|
2025-12-04 20:43:44 +01:00
|
|
|
missing.append("torch")
|
|
|
|
|
|
2026-03-13 20:48:40 +01:00
|
|
|
if importlib.util.find_spec("transformers") is None:
|
2025-12-04 20:57:50 +01:00
|
|
|
missing.append("transformers")
|
2025-12-04 20:43:44 +01:00
|
|
|
|
2026-03-13 20:48:40 +01:00
|
|
|
if importlib.util.find_spec("scipy") is None:
|
2025-12-04 20:57:50 +01:00
|
|
|
missing.append("scipy")
|
2025-12-04 20:43:44 +01:00
|
|
|
|
2026-03-13 20:48:40 +01:00
|
|
|
if include_bark and importlib.util.find_spec("bark") is None:
|
|
|
|
|
missing.append("git+https://github.com/suno-ai/bark.git")
|
2025-12-04 21:26:52 +01:00
|
|
|
|
2025-12-04 20:43:44 +01:00
|
|
|
if missing:
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
logger.error("Missing dependencies. Install with:")
|
|
|
|
|
logger.error(" pip install %s", " ".join(missing))
|
|
|
|
|
logger.error("For CUDA support:")
|
|
|
|
|
logger.error(
|
|
|
|
|
" pip install torch --index-url https://download.pytorch.org/whl/cu121",
|
|
|
|
|
)
|
|
|
|
|
logger.error(" pip install transformers scipy")
|
2025-12-04 21:26:52 +01:00
|
|
|
if include_bark:
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
logger.error("For Bark vocals:")
|
|
|
|
|
logger.error(
|
|
|
|
|
" pip install git+https://github.com/suno-ai/bark.git",
|
|
|
|
|
)
|
2025-12-04 20:43:44 +01:00
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
EXAMPLE_PROMPTS = [
|
|
|
|
|
"upbeat electronic dance music with heavy bass",
|
|
|
|
|
"calm acoustic guitar melody with soft percussion",
|
|
|
|
|
"epic orchestral soundtrack with dramatic strings",
|
|
|
|
|
"lo-fi hip hop beats for studying",
|
|
|
|
|
"80s synthwave with retro vibes",
|
|
|
|
|
"jazz piano trio with upright bass",
|
|
|
|
|
"ambient electronic music for relaxation",
|
|
|
|
|
"rock guitar riff with drums",
|
|
|
|
|
"classical piano sonata in minor key",
|
|
|
|
|
"tropical house with steel drums",
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _show_help() -> None:
|
|
|
|
|
"""Display example prompts."""
|
|
|
|
|
logger.info("Example prompts:")
|
|
|
|
|
for i, ex in enumerate(EXAMPLE_PROMPTS, 1):
|
|
|
|
|
logger.info(" %d. %s", i, ex)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _handle_duration(raw: str) -> int | None:
|
|
|
|
|
"""Parse and return a new duration, or None on failure."""
|
|
|
|
|
try:
|
|
|
|
|
value = int(raw.strip())
|
|
|
|
|
except ValueError:
|
|
|
|
|
logger.warning(
|
|
|
|
|
"Invalid duration. Use ':d <number>' e.g., ':d 15'",
|
|
|
|
|
)
|
|
|
|
|
return None
|
|
|
|
|
else:
|
|
|
|
|
clamped = max(1, min(30, value))
|
|
|
|
|
logger.info("Duration set to %ds", clamped)
|
|
|
|
|
return clamped
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _resolve_prompt(prompt: str) -> str | None:
|
|
|
|
|
"""Resolve a numeric prompt to an example, or return as-is.
|
|
|
|
|
|
|
|
|
|
Returns None if the number is out of range.
|
|
|
|
|
"""
|
|
|
|
|
if prompt.isdigit():
|
|
|
|
|
idx = int(prompt) - 1
|
|
|
|
|
if 0 <= idx < len(EXAMPLE_PROMPTS):
|
|
|
|
|
resolved = EXAMPLE_PROMPTS[idx]
|
|
|
|
|
logger.info("Using: %s", resolved)
|
|
|
|
|
return resolved
|
|
|
|
|
logger.warning(
|
|
|
|
|
"Invalid number. Enter 1-%d",
|
|
|
|
|
len(EXAMPLE_PROMPTS),
|
|
|
|
|
)
|
|
|
|
|
return None
|
|
|
|
|
return prompt
|
|
|
|
|
|
|
|
|
|
|
2025-12-04 20:43:44 +01:00
|
|
|
def interactive_mode(model: object, processor: object) -> None:
|
|
|
|
|
"""Run interactive prompt mode."""
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
banner = "=" * 60
|
|
|
|
|
logger.info("\n%s", banner)
|
|
|
|
|
logger.info("INTERACTIVE MODE")
|
|
|
|
|
logger.info("%s", banner)
|
|
|
|
|
logger.info("Enter prompts to generate music. Commands:")
|
|
|
|
|
logger.info(" :q or :quit - Exit")
|
|
|
|
|
logger.info(" :d <seconds> - Set duration (e.g., ':d 15')")
|
|
|
|
|
logger.info(" :h or :help - Show example prompts")
|
|
|
|
|
logger.info("%s", banner)
|
2025-12-04 20:43:44 +01:00
|
|
|
|
|
|
|
|
duration = 10
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
try:
|
|
|
|
|
prompt = input(f"\n[{duration}s] Enter prompt: ").strip()
|
|
|
|
|
except (EOFError, KeyboardInterrupt):
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
logger.info("Exiting...")
|
2025-12-04 20:43:44 +01:00
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if not prompt:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if prompt.lower() in (":q", ":quit", "quit", "exit"):
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
logger.info("Exiting...")
|
2025-12-04 20:43:44 +01:00
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if prompt.lower() in (":h", ":help", "help"):
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
_show_help()
|
2025-12-04 20:43:44 +01:00
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if prompt.startswith(":d "):
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
new_dur = _handle_duration(prompt[3:])
|
|
|
|
|
if new_dur is not None:
|
|
|
|
|
duration = new_dur
|
2025-12-04 20:43:44 +01:00
|
|
|
continue
|
|
|
|
|
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
resolved = _resolve_prompt(prompt)
|
|
|
|
|
if resolved is None:
|
|
|
|
|
continue
|
2025-12-04 20:43:44 +01:00
|
|
|
|
|
|
|
|
try:
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
generate_music(
|
|
|
|
|
resolved,
|
|
|
|
|
model,
|
|
|
|
|
processor,
|
|
|
|
|
duration_seconds=duration,
|
|
|
|
|
)
|
|
|
|
|
except (RuntimeError, ValueError, OSError):
|
|
|
|
|
logger.exception("Error generating music")
|
2025-12-04 20:43:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def main() -> None:
|
|
|
|
|
"""Main entry point."""
|
|
|
|
|
parser = argparse.ArgumentParser(
|
2025-12-04 21:26:52 +01:00
|
|
|
description="Generate music or speech from text prompts",
|
2025-12-04 20:43:44 +01:00
|
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
|
|
|
epilog="""
|
|
|
|
|
Examples:
|
2025-12-04 21:26:52 +01:00
|
|
|
# Music generation (MusicGen):
|
2025-12-04 20:43:44 +01:00
|
|
|
%(prog)s "upbeat electronic dance music"
|
2025-12-04 21:26:52 +01:00
|
|
|
%(prog)s --duration 60 "calm piano melody"
|
2025-12-04 20:43:44 +01:00
|
|
|
%(prog)s --model small "jazz guitar solo"
|
|
|
|
|
%(prog)s --interactive
|
|
|
|
|
|
2025-12-04 21:26:52 +01:00
|
|
|
# Speech/vocals generation (Bark):
|
|
|
|
|
%(prog)s --speech "Hello, how are you today?"
|
|
|
|
|
%(prog)s --speech --voice v2/en_speaker_3 "Welcome!"
|
|
|
|
|
%(prog)s --speech "♪ La la la, I love to sing ♪"
|
|
|
|
|
|
|
|
|
|
# Full song with vocals over music:
|
|
|
|
|
%(prog)s --song "♪ Hello world, this is my song ♪" --music "upbeat pop"
|
|
|
|
|
|
|
|
|
|
Model sizes for MusicGen (auto-selected based on VRAM if not specified):
|
2025-12-04 20:57:50 +01:00
|
|
|
small - ~500MB, fastest, lower quality (3GB+ VRAM)
|
|
|
|
|
medium - ~3.3GB, good balance (8GB+ VRAM)
|
|
|
|
|
large - ~6.5GB, best quality (12GB+ VRAM)
|
2025-12-04 21:26:52 +01:00
|
|
|
|
|
|
|
|
Bark voices: v2/en_speaker_0 to v2/en_speaker_9
|
|
|
|
|
Bark tokens: [laughter] [laughs] [sighs] [music] [gasps] ♪ (singing)
|
2025-12-04 20:43:44 +01:00
|
|
|
""",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"prompt",
|
|
|
|
|
nargs="?",
|
2025-12-04 21:26:52 +01:00
|
|
|
help="Text description of music/speech to generate",
|
2025-12-04 20:43:44 +01:00
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"-d",
|
|
|
|
|
"--duration",
|
|
|
|
|
type=int,
|
|
|
|
|
default=10,
|
2025-12-04 21:26:52 +01:00
|
|
|
help="Duration in seconds (default: 10, any length supported)",
|
2025-12-04 20:43:44 +01:00
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"-m",
|
|
|
|
|
"--model",
|
|
|
|
|
choices=["small", "medium", "large"],
|
2025-12-04 20:57:50 +01:00
|
|
|
default=None,
|
2025-12-04 21:26:52 +01:00
|
|
|
help="MusicGen model size (auto-select based on VRAM by default)",
|
2025-12-04 20:43:44 +01:00
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"-i",
|
|
|
|
|
"--interactive",
|
|
|
|
|
action="store_true",
|
2025-12-04 21:26:52 +01:00
|
|
|
help="Run in interactive mode (MusicGen only)",
|
2025-12-04 20:43:44 +01:00
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"-o",
|
|
|
|
|
"--output",
|
|
|
|
|
type=Path,
|
|
|
|
|
help="Output directory (default: ./output)",
|
|
|
|
|
)
|
2025-12-04 21:26:52 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
"-s",
|
|
|
|
|
"--speech",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Generate speech/vocals using Bark instead of music",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"-v",
|
|
|
|
|
"--voice",
|
|
|
|
|
default="v2/en_speaker_6",
|
|
|
|
|
help="Bark voice preset (default: v2/en_speaker_6)",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--song",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Generate a full song with vocals over instrumental",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--music",
|
|
|
|
|
type=str,
|
|
|
|
|
default="upbeat pop instrumental backing track",
|
|
|
|
|
help="Music style for --song mode (default: upbeat pop)",
|
|
|
|
|
)
|
2025-12-04 20:43:44 +01:00
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
if not args.prompt and not args.interactive:
|
|
|
|
|
parser.print_help()
|
Reduce per-file-ignores by fixing lint violations across codebase
Fix ruff violations in ~15 source files and ~60+ test files to minimize
per-file-ignores in pyproject.toml. Remaining ignores are justified with
comments explaining why each suppression is necessary.
Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001
(private access), T201 (print→logging), C901 (complexity), E501 (line
length), E402 (import order).
Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in
loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108
(tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type
annotations), RUF059 (unused unpacked vars), PT019 (fixture naming).
Remaining per-file-ignores (with justifications):
- Tests: ARG, D, PLC0415, PLR2004, S101, SLF001
- music_gen sources: PLC0415 (heavy ML lazy imports)
- moviepy_showcase: PLC0415 (circular dependency)
- generate_images: PLR0913 (matplotlib helpers need many params)
- praca_magisterska_video: E501, E402 (long paths, mpl.use)
2026-03-25 18:58:05 +01:00
|
|
|
logger.error(
|
|
|
|
|
"Either provide a prompt or use --interactive mode",
|
|
|
|
|
)
|
2025-12-04 20:43:44 +01:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
# Check dependencies
|
2025-12-04 21:26:52 +01:00
|
|
|
use_bark = args.speech or args.song
|
|
|
|
|
if not check_dependencies(include_bark=use_bark):
|
2025-12-04 20:43:44 +01:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
2025-12-04 21:26:52 +01:00
|
|
|
if args.song:
|
|
|
|
|
# Full song generation mode (vocals + instrumental)
|
|
|
|
|
generate_song(
|
2025-12-04 20:43:44 +01:00
|
|
|
args.prompt,
|
2025-12-04 21:26:52 +01:00
|
|
|
args.music,
|
|
|
|
|
voice=args.voice,
|
2025-12-04 20:43:44 +01:00
|
|
|
output_dir=args.output,
|
|
|
|
|
)
|
2025-12-04 21:26:52 +01:00
|
|
|
elif args.speech:
|
|
|
|
|
# Bark speech generation mode
|
|
|
|
|
generate_speech(
|
|
|
|
|
args.prompt,
|
|
|
|
|
voice=args.voice,
|
|
|
|
|
output_dir=args.output,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
# MusicGen music generation mode
|
|
|
|
|
model_size = select_model_size(args.model)
|
|
|
|
|
model, processor = load_model(model_size)
|
|
|
|
|
|
|
|
|
|
if args.interactive:
|
|
|
|
|
interactive_mode(model, processor)
|
|
|
|
|
else:
|
|
|
|
|
generate_music(
|
|
|
|
|
args.prompt,
|
|
|
|
|
model,
|
|
|
|
|
processor,
|
|
|
|
|
duration_seconds=args.duration,
|
|
|
|
|
output_dir=args.output,
|
|
|
|
|
)
|
2025-12-04 20:43:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|