Text-to-Music Prompt Structurer
Convert a musical idea into separate, paste-ready Suno Custom/Advanced fields, not just a generic analysis of genres and instruments.
The engine is deterministic, offline, dependency-free and compatible with Python 3.10+. It is built using NLP-inspired parsing techniques and does not require a hosted LLM. It detects known musical characteristics from free-form text and preserves the original creative direction by default so unfamiliar arrangement details are not silently lost.
Project vision. This library is an effort to design a sophisticated, extensible music-prompting system that works effectively with Suno. Its author, Eduardo J. Barrios, brings advanced knowledge of artificial intelligence (AI), natural language processing (NLP), and large language models (LLMs) to the design of interpretable musical instructions, structured song sections, constraint extraction, and iterative prompt improvement. The goal is to make complex music prompting more systematic, expressive, and reusable.
Install
python -m pip install --upgrade "text-to-music-prompt-structurer>=0.3.0"
Version 0.3.0 improves prompt quality with automatic Exclude extraction, contextual language recognition and optional preflight validation. The Suno Custom/Advanced output introduced in 0.2.0 remains available.
If PyPI has not yet indexed v0.3.0, the GitHub release/tag also supports installation:
python -m pip install "git+https://github.com/edujbarrios/text-to-music-prompt-structurer.git@v0.3.0"
This Git install requires Git and uses the exact v0.3.0 tag.
Get Suno-ready fields (default CLI output)
text-to-music-prompt --title "Luz de madrugada" \
--exclude "autotune" \
--section "Intro" --cue "Intro=soft piano, no drums" \
--section "Verse 1" --cue "Verse 1=intimate, breathy lead" \
--section "Chorus" --cue "Chorus=full band, layered backing harmonies" \
--section "Bridge" --section "Final Chorus" --section "Outro" \
"neo soul with piano, nostalgic female vocals in spanish, d minor, 92 bpm"
The command prints a readable report of separate values for Suno's creation fields. The headings are not Suno metatags:
TITLE
Luz de madrugada
STYLE OF MUSIC
Neo Soul; Nostalgic mood; 92 BPM; D Minor key; Instrumentation: Piano; Vocals: Spanish-language, Female Lead; Creative direction: neo soul with piano, nostalgic female vocals in spanish, d minor, 92 bpm
LYRICS
[Intro]
[soft piano, no drums]
[Verse 1]
[intimate, breathy lead]
[Chorus]
[full band, layered backing harmonies]
[Bridge]
[Final Chorus]
[Outro]
EXCLUDE
autotune
VOCAL GENDER
Female
Copy the value under each heading into its matching Suno field.
Do not paste the combined report into the Lyrics box.
Bracketed section labels such as [Verse 1] and [Chorus] are common
guidance markers; performance cues such as [full band] are best-effort
directions, not guaranteed engine instructions.
The skeleton above intentionally contains no invented lyrics. An empty section is an editable template, not a finished song lyric. Write your own lines under the tags, supply a lyric file, or use Suno's own lyric-writing tools.
Complete custom lyrics
text-to-music-prompt \
--lyrics-file lyrics.txt \
--title "Luz de madrugada" \
--exclude "electric guitar" \
"warm neo soul, 92 bpm, female vocals in Spanish"
A UTF-8 lyrics.txt can contain existing section labels and lyrics:
[Verse 1]
La calle aún respira.
Tu nombre en el cristal.
[Chorus]
Volverá la luz.
Volverá la luz.
Its lyrics and section labels retain their exact wording (leading and trailing
blank newlines are stripped); they are not translated, summarized or rewritten. Use either --lyrics-file
or --section, not both.
Python API — complex sectional control
from text_to_music_prompt_structurer import (
MusicPromptEngine,
SunoSection,
format_for_suno,
)
engine = MusicPromptEngine()
fields = engine.process_suno(
"cinematic neo soul in d minor, 92 bpm, warm female vocals in spanish",
title="Luz de madrugada",
exclude=["autotune", "distorted guitars"],
sections=[
SunoSection("Intro", cue="solo electric piano, restrained ambience"),
SunoSection("Verse 1", "La calle aún respira.", cue="intimate breathy lead"),
SunoSection("Pre-Chorus", "Todo empieza a brillar.", cue="rising strings"),
SunoSection("Chorus", "Volverá la luz.", cue="wide harmonies, full drums"),
SunoSection("Bridge", "Una voz en la ciudad.", cue="half-time feel"),
SunoSection("Final Chorus", "Volverá la luz.", cue="maximum emotional lift"),
SunoSection("Outro", cue="piano resolves softly"),
],
)
print(fields.style_of_music) # paste into Style of Music
print(fields.lyrics) # paste into Lyrics
print(fields.exclude) # paste into Advanced > Exclude
print(fields.vocal_gender) # optional Vocal Gender UI control
print(format_for_suno(fields)) # readable combined presentation
payload = fields.to_dict() # JSON-compatible values for your own app
For instrumental tracks, use --instrumental, or describe the track
as instrumental and let process_suno() detect it. Instrumental mode
rejects nonempty lyric lines rather than generating a contradictory request.
CLI options
| Option | Purpose |
|---|---|
--format suno |
Separate Suno fields (default) |
--format json |
Machine-readable object with independent Suno fields |
--format legacy |
Preserve original STYLE/MOOD/BPM/... output |
--lyrics-file FILE |
Supply complete UTF-8 lyrics without rewriting |
--section NAME |
Add an editable structural section (repeatable) |
--cue NAME=DIRECTION |
Add a direction to the named section |
--exclude TEXT |
Fill Suno's separate Exclude control (repeatable) |
--instrumental |
Force Instrumental on |
--style-notes TEXT |
Additional freeform style/arrangement instruction |
--no-original |
Do not append the original creative description |
--no-auto-exclude |
Disable automatic negative-constraint extraction |
--check |
Display prompt-quality issues on stderr |
--max-style-chars N |
Optional caller-defined style budget (with --check) |
--max-lyrics-chars N |
Optional caller-defined lyrics budget (with --check) |
--title TITLE |
Song title |
Example JSON command:
text-to-music-prompt --format json --title "Medianoche" \
--exclude "autotune" "dreamy synthwave 110 bpm female vocals"
Prompt-quality features (v0.3.0)
Automatically extract negative musical constraints
Explicit negatives such as no drums, without autotune, avoid reverb
and sin batería populate Suno's Exclude field. The negated instrument
is removed from positive keyword detection and from the preserved creative
summary so it does not contradict the Exclude field. The extractor uses a conservative,
documented vocabulary and deliberately does not guess at open-ended negations.
from text_to_music_prompt_structurer import MusicPromptEngine
fields = MusicPromptEngine().process_suno(
"neo soul, warm piano, 92 bpm, no drums, without autotune",
preserve_description=False,
)
print(fields.exclude) # Drums, Autotune
print(fields.style_of_music) # Neo Soul; Warm mood; 92 BPM; ...
Use --no-auto-exclude to disable extraction; explicit --exclude arguments
are retained. Language detection is also context-aware: Latin trap does
not automatically mean Latin-language vocals, and Spanish guitar on its
own does not mean Spanish-language singing.
Validate without rewriting
from text_to_music_prompt_structurer import validate_suno_prompt
issues = validate_suno_prompt(
fields,
max_style_chars=1000, # your own budget, not an official Suno limit
max_lyrics_chars=3000,
)
for issue in issues:
print(issue.severity, issue.code, issue.message)
This checks missing styles, empty or skeleton-only lyrics, conflicting instrumental/vocal controls and optionally caller-defined length budgets. It never rewrites existing lyrics, and returns machine-readable issue codes.
From the CLI, use --check for diagnostics on stderr while retaining
clean prompt output on stdout (including valid JSON):
text-to-music-prompt --format json --check \
--max-style-chars 1000 "cinematic neo soul without drums"
Automated releases to GitHub and PyPI
Publishing runs through .github/workflows/release.yml whenever the package
version is updated in pyproject.toml on main. It tests, lints, builds and
checks artifacts, then publishes to PyPI through GitHub Actions OIDC Trusted
Publishing. A GitHub release with wheel and source distribution is also
created. PyPI must first have a matching Trusted Publisher under the project's
Publishing settings: owner edujbarrios, repository
text-to-music-prompt-structurer, workflow release.yml, environment
pypi. There is no need for a long-lived PyPI token.
Outputs and migration
- Suno human-readable report: default CLI mode; paste values individually into Suno.
- JSON:
--format jsonkeepsstyle_of_music,lyrics,title,exclude,instrumental,vocal_genderandlyric_briefas independent properties. - Legacy analysis:
--format legacyor Pythonformat_prompt()for existing integrations that need theSTYLE/MOOD/BPMreport.
A title is optional; exclude and instrumental are Advanced controls in Suno,
not strings to paste inside lyrics. vocal_gender is a suggested UI control when
unambiguous vocal type is detected. lyric_brief is not a Suno lyrics field.
Legacy API / compatibility
MusicPromptEngine().process(text) still returns the existing
MusicPrompt dataclass with detected genre, subgenre, mood, BPM, key,
instruments, production, language, voice type, vocal style, rhythm,
structure, era and theme. format_prompt(prompt) still generates
the previous STYLE: ...\nMOOD: ... analysis view.
Changed in 0.2: format_for_suno(prompt) now renders actual Suno
fields instead of aliasing format_prompt(). The CLI defaults to Suno
fields, but --format legacy retains its previous display.
SunoPrompt and SunoPromptEngine remain aliases of the original
MusicPrompt and MusicPromptEngine. Use SunoFields when you need
paste-ready Suno controls.
An optional lyric_brief in SunoFields is explicitly a theme brief
for a lyric-generation tool. It is not auto-inserted into Lyrics
because prose requests may be sung literally.
Supported and unsupported behavior
This package does not connect to Suno, generate audio, guarantee exact
timing, guarantee every section cue will be obeyed, or use an LLM to write
new lyrics. Some free-form details are outside its keyword vocabulary;
the original source sentence is preserved as additional musical guidance
unless --no-original is set. Manually review ambiguous instructions
or contradictory constraints before pasting into Suno.
Official source references for the field design and conventions:
- Suno: How to Make a Song — Style, Lyrics and section labels
- Suno: v6 FAQ — complex instructions and current model family
- Suno: Exclude elements — the separate Exclude control
- Suno: Vocal Gender — vocal gender in Advanced Options
- Suno: Lyrics improvements — structure labels in the editor
Development
git clone https://github.com/edujbarrios/text-to-music-prompt-structurer.git
cd text-to-music-prompt-structurer
python -m pip install -e ".[dev]"
python -m pytest
ruff check .
See CONTRIBUTING.md to extend the vocabularies.
License
Copyright © 2026 Eduardo J. Barrios.
Licensed under the Mozilla Public License 2.0. See NOTICE for attribution details.
Metadata
Release files for text-to-music-prompt-structurer 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| text_to_music_prompt_structurer-0.3.0.tar.gz | 48.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| text_to_music_prompt_structurer-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 94.5 kB
Release files / text_to_music_prompt_structurer-0.3.0.tar.gz
| Download URL | text_to_music_prompt_structurer-0.3.0.tar.gz |
|---|---|
| Size | 48.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
614e3d21482064cc6bcbccf67d00c0b4d6a984f751fc81486d38d0cd290cd8b6
|
|
BLAKE2b-256 checksum How to use checksums |
4320c563a9a8c3ee36f5104c522fd1c3f4742bd059591d1caa377847c3335326
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / text_to_music_prompt_structurer-0.3.0-py3-none-any.whl
| Download URL | text_to_music_prompt_structurer-0.3.0-py3-none-any.whl |
|---|---|
| Size | 46.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
916f2a60508cd5982a49d903f1298865eaf47abd5878616da546debe15735b22
|
|
BLAKE2b-256 checksum How to use checksums |
7767e5024bf1f42f63f33871ec8180e7b2262122525646490863de9aa4914ea0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log