AI Music

How to Generate Music with the Open-Source YuE2-3B Model on Google Colab

Who owns the song you created with artificial intelligence? The question sounds simple, but the answer can change depending on the plan you pay for, the version of the terms of service and even the month in which you accepted the rules.

Picture the scene. You spend an afternoon polishing a set of lyrics, choosing a style, generate ten versions and, finally, one of them moves you. You download the file, send it to a friend and maybe use it as the soundtrack for a video from your music school. Six months later, you cancel your subscription because the budget got tight. What happens to that song? Can you still use it? Can you monetize it? And who decides?

In this post I show an alternative: generating music with an open-source model, YuE2-3B, running on Google Colab. We will first talk about copyright and terms of use, then about the hardware required and, finally, follow a step-by-step guide with code that is ready to copy and paste. Open-source means that the model files and the code to run them are published, and anyone can download and run them independently, as long as they respect the license.

Before the first note: what you sign when you use a platform

Platforms such as Suno are convenient: you write an idea, click a button and minutes later you have a complete song. But that convenience comes with a contract, and it is worth reading the clauses with the same attention we would give to a record deal.

In 2026, after its agreement with Warner Music Group, Suno rewrote parts of its terms. Language that used to say subscribers owned their songs changed to say they may receive commercial use rights. The company itself explains that, even with those rights, the user is generally not considered the owner of the work, because the output was generated by the platform. The terms also make it clear that there is no guarantee that any copyright will exist in what was generated.

There are other points. Songs created on the free plan are for non-commercial use only and cannot be monetized. Retroactive rights may be granted in limited cases, but without any guarantee. New terms took effect on September 3, 2026, and introduced download limits: 7 downloads in total on the free plan, 20 per month on Pro and 60 per month on Premier, applying even to songs created before the change. And, according to analyses of the terms, the user grants the platform a broad license to use what is submitted and what is generated to improve its models.

The company states that, if you cancel, your library stays in your account and songs downloaded as a subscriber keep their commercial rights. So, the problem is not necessarily what is written today. The problem is who writes the rules. They have changed more than once in a few months, they may change again, and you, who depend on the platform to access and download your own material, have no bargaining power at all. It is like composing in a studio that can change the contract after the recording. That is why you should always check the terms currently in force: they may have changed since I wrote this text.

What changes with an open-source model

When you run an open model, the logic is reversed. You download the model files, run them on the machine you own or rented, and the result is an audio file that is in your hands. There is no subscriber account, no download limit and no music-platform clause telling you what you may or may not do with the result. If a service shuts down tomorrow, the model you downloaded keeps working. It is the difference between subscribing to a streaming service and owning your own recording equipment.

But pay attention to a point many people forget: control is not the same as total freedom. The model has its own license. The YuE2-3B weights (the “weights” are the numbers the model learned, in other words, its knowledge stored in a file) are published under the Creative Commons CC BY-NC 4.0 license, which allows non-commercial use and requires attribution to the authors. The inference code we use to run the model is Apache 2.0, which is far more permissive, but it is the weights that define what you can do with the music.

In practice, this is great for study, teaching, demos, arrangement prototypes, soundtracks for personal projects and experiments. If your goal is to sell or monetize the music, read the license on the model’s official page and, if possible, consult a lawyer who specializes in copyright. I am not a lawyer, this text is not legal advice, and laws vary from country to country.

There is also the question of authorship. In many countries, copyright protection is tied to human creativity. The more of your own contribution a work contains, such as lyrics written by you, the structure, the arrangement choices and, afterwards, the editing and mixing, the stronger your position tends to be. Use AI as a session musician, not as a substitute for the composer.

What about the training data?

There is a question that still has no definitive answer: the music used to train these models. Lawsuits around the world are debating whether training an AI on protected works is permitted use, and deals such as the one between Suno and Warner show that the market is negotiating the rules while the game is being played. This applies to closed platforms and open models alike, and it is an area of the law that may change in the coming years. So, follow the news and keep a record of which model and which settings you used for each track. The script we will use saves the “artifacts” of each generation, which helps with that.

On balance, I still think it is better to generate music with an open model under your own control: you know which license applies, you choose the version, you keep your files and you do not depend on a company keeping today’s rules. It is a risk decision, not a guarantee, and each person should weigh their own situation.

The obstacle: the GPU

Music-generation models perform billions of calculations at the same time, and the part that does this heavy lifting is the GPU, the graphics processing unit. Think of the computer’s CPU as an excellent conductor who reads the score note by note, while the GPU is an entire orchestra playing in parallel. To run YuE2-3B at original quality, without compression, the recommendation is a card with about 24 GB of video memory (VRAM), which is where the model has to fit while it works. There are quantized versions, that is, compressed ones with some loss of quality, that run on smaller cards, but the experience is more limited.

GPUs with that much memory often cost well over a thousand dollars, and in many countries import taxes and exchange rates push the price even higher. For a musician or teacher who just wants to experiment, buying one is like buying a grand piano to find out whether you enjoy playing. The way out is to rent the “studio” by the hour.

Google Colab: the rehearsal studio rented by the hour

Google Colab (short for Colaboratory) is a Google service that lets you write and run Python code directly in your browser, on the company’s own computers, including machines with a GPU. It works like renting a rehearsal room: you pay for the time you use and, when you finish, you hand the room back.

The billing model that suits our case best is pay as you go. Instead of subscribing to a monthly plan, you buy compute units, which are Colab’s currency. When I last checked, the price was US$ 9.99 for 100 units, with no subscription, and the units expire 90 days after purchase, which means three months. An A100 GPU consumes roughly 10 to 15 units per hour, which works out to 7 to 10 hours of use per 100 units, or around US$ 1 to US$ 1.50 per hour. Prices are in US dollars, change over time and may vary by region, so check the Colab pricing page before you buy.

Since each song takes a few minutes to generate, 100 units yield dozens of generations for a fraction of the price of a graphics card. There are two cautions. The first is that Google does not guarantee which GPU you will get. The second is that units keep being spent while the session is open, even if you are not generating anything. Finished? End the session under Runtime > Disconnect and delete runtime.

Colab runs on Linux: how to activate the graphics card

Under the interface, Colab runs Linux (Ubuntu). This explains a few details in the code: commands that start with an exclamation mark (!) are sent to the Linux terminal, such as apt-get, which installs programs. Commands that start with %%writefile save the content of the cell to a file. A cell is each block of code in the notebook, and you run them one at a time by clicking the play button beside each one.

Before anything else, activate the graphics card. The one suggested for this model is the A100, which has plenty of memory for it:

  1. Go to colab.research.google.com and create a new notebook.
  2. In the menu, open Runtime > Change runtime type.
  3. Under Hardware accelerator, choose the A100 GPU.
  4. Save and click Connect.

If the A100 is not available at the moment, Colab may offer a different card. In that case, try again later. Our script checks for the GPU right at the start and warns you if none is found.

How the Python code works

All the code in this post is written in Python, a language widely used in artificial intelligence and known for being readable, almost like reading a recipe. You do not need to know how to program to use it: you just copy, paste and change a few texts, such as the style and the lyrics.

The flow is always the same and resembles studio work. First, we load the model onto the graphics card, like switching on the equipment. Then we define the style, which is the briefing for the band (genre, instruments, mood), and the lyrics, which also carry the structure of the song, with markers such as [Verse] and [Chorus]. Next, we tell it to generate and, finally, we save the audio and the artifacts, which are the auxiliary files of the process, including the melody and chord plan.

Two parameters deserve an explanation. The first is cot=”full”. The abbreviation comes from chain of thought. Instead of producing the audio in one go, the model first writes a symbolic plan of the song, with melody and chords in ABC notation (a simple text format for writing sheet music), and only then turns that plan into sound. It is like an arranger who sketches the score before calling in the musicians. For covers, the recommended mode is cot=”melody”. The second parameter is the seed: the number that starts the model’s internal draw. With the same seed and the same texts, you tend to get the same result, like repeating the same take. Change the seed and new variations are born.

And why do we use a venv? YuE2 requires Python 3.10, while Colab usually ships with a different version. The solution is to create a virtual environment, or venv: a folder with its own Python and its own libraries, isolated from the rest of the system. Think of a soundproof recording booth, where what happens inside does not interfere with the studio next door. That is why the scripts are run with /content/yue2_env/bin/python and not with the default Python.

Step 1: create the environment with Python 3.10

In the first cell we install Python 3.10 with apt-get, the program manager of Ubuntu, and create the virtual environment in the /content/yue2_env folder. It takes a few minutes to run.

# Cell 1: Install Python 3.10 and create the virtual environment (venv)

!sudo apt-get update -y

!sudo apt-get install -y python3.10 python3.10-dev python3.10-venv

!python3.10 -m venv /content/yue2_env

Step 2: install YuE2

The second cell updates pip (Python’s package installer), installs a specific version of the huggingface-hub library, downloads the YuE2 inference package straight from the official repository on Hugging Face and installs it inside the venv. Hugging Face is a kind of “GitHub for AI models”, where the model files are published. The weights, which take up a few gigabytes, are normally downloaded the first time the script loads the model, so the first run is the slowest.

# Cell 2: Install the inference package in the new environment

!/content/yue2_env/bin/python -m pip install –upgrade pip

!/content/yue2_env/bin/python -m pip install huggingface-hub==0.36.2

!/content/yue2_env/bin/hf download m-a-p/YuE2-3B yue2_infer-0.1.5-py3-none-any.whl –local-dir .

!/content/yue2_env/bin/python -m pip install ./yue2_infer-0.1.5-py3-none-any.whl

Step 3: a quick test with the official example

Before customizing anything, it is worth confirming that everything works by using the demo example from the repository itself. The script below downloads a ready-made request (style, lyrics and seed) and generates the song. If everything goes well, you will have a song.flac file (FLAC is a lossless audio format) next to the notebook.

# Cell 3: Create the test file with the official example

%%writefile teste_demo.py

import json

from pathlib import Path

from huggingface_hub import hf_hub_download

from yue2 import YuE2Pipeline

print(“Loading the YuE2Pipeline on the GPU…”)

pipe = YuE2Pipeline.from_pretrained(“m-a-p/YuE2-3B”, device=”cuda”)

# Download the demo example from the repository

repo = “m-a-p/YuE2-3B”

prompt_path = hf_hub_download(repo, “examples/tonight-awake.json”)

demo = json.loads(Path(prompt_path).read_text(encoding=”utf-8″))

style, lyrics = demo[“style”], demo[“lyrics”]

print(“Generating the music…”)

song = pipe(style=style, lyrics=lyrics, cot=”full”, seed=demo[“seed”])

# Save the song and the artifacts

song.save(“song.flac”)

song.save_artifacts(“outputs/song”)

print(“Generation complete! File saved as ‘song.flac’.”)

# Cell 4: Run the test with the venv’s Python 3.10

!/content/yue2_env/bin/python teste_demo.py

Step 4: the configurable generation script

This is the script for everyday use. All the options sit in the CONFIGURE HERE block at the top of the file, so that is the only part you need to touch. Here is what each one does:

  • CAPTION: the style of the song, with genre, instruments and mood. Write it in English, as in the official examples.
  • LYRICS: the lyrics, with markers such as [Verse 1] and [Chorus]. Write [Instrumental] for a track without vocals.
  • VOCAL_LANGUAGE: the language of the vocals. Use “en” for English, “pt” for Portuguese, “es” for Spanish, or “unknown” to let the model decide.
  • DURATION: the model decides the length of the track, so this value only trims the audio, with a 1.5-second fade-out, if it runs past the limit. Use -1 for no trimming.
  • BPM and KEYSCALE: tempo and key. They enter as text in the style, working as a request and not as a strict order.
  • BATCH_SIZE: how many variations to generate in sequence.
  • AUDIO_FORMAT: the final file format (wav, flac, mp3, opus, aac), converted with ffmpeg.
  • SEED: with -1, the seed is drawn at random on every generation. With a fixed number, the result tends to repeat.
  • OUTPUT_DIR: the folder where the files will be saved.

# Cell 5: Create the configurable generation script

%%writefile /content/generate_music.py

import os, sys, subprocess, inspect, time, random

from pathlib import Path

# — 0. Make sure we are running inside the YuE2 virtual environment —

VENV_DIR = “/content/yue2_env”

VENV_PYTHON = f”{VENV_DIR}/bin/python”

if os.path.exists(VENV_PYTHON) and os.path.realpath(sys.prefix) != os.path.realpath(VENV_DIR):

    os.execv(VENV_PYTHON, [VENV_PYTHON] + sys.argv)

try:

    import torch

except ImportError:

    torch = None

# ===================== CONFIGURE HERE =====================

CAPTION = “blues with piano, cello, double bass, sax and soft drums”

LYRICS = “””[Verse 1]

Walking down the street today

Thinking of the words you used to say

Everything feels different now

But I will find my way somehow

[Chorus]

I keep moving on, I keep moving strong

This is where I belong

“””  # or write your own lyrics; “[Instrumental]” = no vocals

VOCAL_LANGUAGE = “en”       # “en”, “pt”, “es”, “ja”… or “unknown” (automatic)

DURATION = 30               # seconds: trims the track to this length (with fade-out); -1 = no trimming

BPM = 85                    # None = automatic

KEYSCALE = “A Major”        # e.g. “C Major”; “” = automatic

BATCH_SIZE = 1              # how many variations to generate

AUDIO_FORMAT = “wav”        # flac, mp3, opus, aac, wav, wav32

SEED = -1                   # -1 = random

USE_LM = True               # True = full melody and chord planning (cot=”full”)

PROJECT_ROOT = “/content/YuE2”   # only used if it exists: added to sys.path

OUTPUT_DIR = “/content/generated_songs”

CONFIG_OVERRIDE = None      # e.g. “m-a-p/YuE2-3B” (main model)

LM_OVERRIDE = None          # separate planning model, if the pipeline accepts one

# ==========================================================

DEFAULT_MODEL = “m-a-p/YuE2-3B”

def run(cmd):

    subprocess.run(cmd, shell=True, check=True)

# — 1. GPU —

if torch is not None:

    if not torch.cuda.is_available():

        sys.exit(“No GPU found. In Colab: Runtime > Change runtime type > GPU.”)

    props = torch.cuda.get_device_properties(0)

    print(f”GPU: {props.name} | VRAM: {props.total_memory / 1024**3:.1f} GB”)

else:

    info = subprocess.run(“nvidia-smi –query-gpu=name,memory.total –format=csv,noheader”,

                          shell=True, capture_output=True, text=True).stdout.strip()

    if not info:

        sys.exit(“No GPU found. In Colab: Runtime > Change runtime type > GPU.”)

    print(f”GPU: {info}”)

model_id = CONFIG_OVERRIDE or DEFAULT_MODEL

print(f”Python: {sys.executable}”)

print(f”Modelo: {model_id} | planning (cot): {‘on’ if USE_LM else ‘off’}”)

# — 2. Import YuE2 (installed in the venv) —

if os.path.isdir(PROJECT_ROOT):

    sys.path.insert(0, PROJECT_ROOT)

try:

    from yue2 import YuE2Pipeline

except ImportError:

    sys.exit(“The ‘yue2’ module was not found. Run cells 1 and 2 first “

             “(create the venv /content/yue2_env and install yue2_infer) and try again.”)

Path(OUTPUT_DIR).mkdir(parents=True, exist_ok=True)

# — 3. Load the model on the GPU —

print(“Loading the YuE2Pipeline on the GPU…”)

load_kwargs = {“device”: “cuda”}

if LM_OVERRIDE:

    if “lm_model” in inspect.signature(YuE2Pipeline.from_pretrained).parameters:

        load_kwargs[“lm_model”] = LM_OVERRIDE

    else:

        print(“Warning: from_pretrained does not accept ‘lm_model’; LM_OVERRIDE ignored.”)

pipe = YuE2Pipeline.from_pretrained(model_id, **load_kwargs)

# — 4. Build the style and lyrics —

instrumental = LYRICS.strip().lower() in (“[instrumental]”, “”)

style_parts = [CAPTION.strip()]

if instrumental:

    style_parts += [“Instrumental”, “no vocals”]

if BPM:

    style_parts.append(f”{BPM} bpm”)

if KEYSCALE:

    style_parts.append(f”{KEYSCALE} key”)

if VOCAL_LANGUAGE and VOCAL_LANGUAGE.lower() != “unknown” and not instrumental:

    style_parts.append(f”{VOCAL_LANGUAGE} vocals”)

style = “. “.join(style_parts)

lyrics = (“[Intro – instrumental]\n\n[verse – instrumental, no vocals]\n\n”

          “[chorus – instrumental, no vocals]\n\n[outro – instrumental, final chord resolution]\n”

          if instrumental else LYRICS)

print(f”Final style: {style}”)

# — 5. Post-processing (format and length) with ffmpeg —

CODECS = {  # format: (extension, ffmpeg arguments)

    “wav”:   (“wav”,  “-c:a pcm_s16le”),

    “wav32”: (“wav”,  “-c:a pcm_f32le”),

    “flac”:  (“flac”, “-c:a flac”),

    “mp3”:   (“mp3”,  “-c:a libmp3lame -q:a 2”),

    “opus”:  (“opus”, “-c:a libopus -b:a 128k”),

    “aac”:   (“aac”,  “-c:a aac -b:a 192k”),

}

fmt = AUDIO_FORMAT.lower()

if fmt not in CODECS:

    sys.exit(f”Invalid AUDIO_FORMAT: {AUDIO_FORMAT}. Use: {‘, ‘.join(CODECS)}”)

ext, codec_args = CODECS[fmt]

def audio_length(path):

    out = subprocess.run(

        f’ffprobe -v error -show_entries format=duration -of csv=p=0 “{path}”‘,

        shell=True, capture_output=True, text=True).stdout.strip()

    return float(out) if out else None

def convert(src, dst, max_seconds=None):

    “””Converts to the requested format and, if longer than the limit, trims with a fade-out.”””

    cut = “”

    length = audio_length(src)

    if max_seconds and length and length > max_seconds + 0.5:

        fade_start = max(max_seconds – 1.5, 0)

        cut = f’-t {max_seconds} -af “afade=t=out:st={fade_start}:d=1.5″‘

    run(f’ffmpeg -y -loglevel error -i “{src}” {cut} {codec_args} “{dst}”‘)

# — 6. Generate (one variation per iteration) —

stamp = time.strftime(“%Y%m%d_%H%M%S”)

saved = []

for i in range(BATCH_SIZE):

    seed = random.randint(0, 2**31 – 1) if SEED == -1 else SEED + i

    name = f”song_{stamp}_v{i + 1}_seed{seed}”

    print(f”\nGenerating variation {i + 1}/{BATCH_SIZE} (seed {seed})…”)

    t0 = time.time()

    gen_kwargs = dict(style=style, lyrics=lyrics, seed=seed)

    if USE_LM:

        gen_kwargs[“cot”] = “full”   # full melody and chord planning

    song = pipe(**gen_kwargs)

    raw = os.path.join(OUTPUT_DIR, f”{name}_raw.flac”)

    song.save(raw)

    song.save_artifacts(os.path.join(OUTPUT_DIR, f”{name}_artifacts”))

    final = os.path.join(OUTPUT_DIR, f”{name}.{ext}”)

    convert(raw, final, max_seconds=DURATION if DURATION and DURATION > 0 else None)

    if os.path.abspath(raw) != os.path.abspath(final):

        os.remove(raw)

    saved.append(final)

    print(f”Variation {i + 1} ready in {time.time() – t0:.1f}s”)

    if torch is not None:

        torch.cuda.empty_cache()

# — 7. Summary —

print(“\nGeneration complete! Audio files:”)

for f in saved:

    print(”  “, f)

print(f”Artifacts (per variation) in: {OUTPUT_DIR}/*_artifacts”)

The rest of the script handles the behind-the-scenes work: it checks that the GPU is active, makes sure it is running inside the venv, builds the style text (adding BPM, key and language), loads the model, generates each variation, converts the audio and prints a summary with the path of the files. Each variation also gets an artifacts folder with the melody and chord plan.

Step 5: generate and listen

Run the cell below. The first run downloads the model and may take a while, and later runs are faster. Watch for the message “Generating variation 1/1” and wait a few minutes.

# Cell 6: Run the generation

!/content/yue2_env/bin/python /content/generate_music.py

When it finishes, the next cell plays the latest generated songs right there in the notebook, with no need to download anything.

# Cell 7: Listen to the latest generated songs

import glob, os

from IPython.display import Audio, display

exts = (“.wav”, “.flac”, “.mp3”, “.opus”, “.aac”)

files = [f for f in glob.glob(“/content/generated_songs/*”) if f.lower().endswith(exts)]

for f in sorted(files, key=os.path.getmtime)[-4:]:

    print(f)

    display(Audio(f))

If you see a message saying that no GPU was found, go back to the Runtime menu and confirm the accelerator you chose. If the warning says the yue2 module was not found, run cells 1 and 2 again, because the virtual environment disappears when the session is restarted. And remember: every generation spends computing units, so test first with BATCH_SIZE = 1 and a short DURATION, and only then generate in larger quantities.

How to write the style and the lyrics

The code is only half of the work. The other half is writing good requests. A few principles that work well:

  • Short, specific style: genre, instruments, mood and tempo. For example: “blues with piano, cello, double bass, sax and soft drums”.
  • Clear structure: use sections such as [Intro], [Verse], [Chorus] and [Outro], with short lines and one idea per line, thinking about how they would be sung.
  • Instrumental: with LYRICS = “[Instrumental]”, the script already adds “no vocals” to the style and builds the structure by itself.
  • Variations: generate several versions with different seeds and pick the best one, the way you would choose among takes.

To control the dynamics of an instrumental track, you can describe what happens inside each section. Try pasting the block below in place of CAPTION, LYRICS and VOCAL_LANGUAGE in the script. Changing the language to “unknown” prevents the script from adding “en vocals” to the style of a piece that has no voice.

CAPTION = “Orchestral instrumental in cinematic movie style, complete orchestra, strictly instrumental, clear production”

LYRICS = “””[Intro – instrumental]

[instrumental – verse 1]

dynamics increasing until climax, starting with woodwind until full orchestra, strictly instrumental, no vocals

[instrumental – chorus]

strings, brass and timpani, with energy, strictly instrumental, no vocals

[instrumental – verse 2]

dynamics decreasing in volume, cello solo, strictly instrumental, no vocals

[instrumental – ending]

full orchestra, strictly instrumental, no vocals

“””

VOCAL_LANGUAGE = “unknown”

Save your songs before ending the session

Everything in the /content folder disappears when the session ends. Before disconnecting, download your files from the file panel (the folder icon on the left side; click the three dots next to the file and choose Download). Another option is to mount Google Drive with the cell below, run before the generation, and point OUTPUT_DIR to a folder inside /content/drive/MyDrive/. Drive will ask for authorization from your Google account.

# Optional: mount Google Drive to keep your songs (remove the # from the two lines)

from google.colab import drive

drive.mount(‘/content/drive’)

Conclusion

Generating music with an open model takes a little more work than clicking a button, but it gives back something valuable: clarity about the rules of the game. You know which license applies, where your files are and how much you are paying per hour of studio time. Just remember that the YuE2-3B weights are for non-commercial use and that the debate over training data is still open.

YuE2 can also create covers from a melody in ABC notation, apply LoRA adapters for instrumental music and run everything in a graphical interface in ComfyUI. Those are topics for upcoming posts. And you, what do you plan to create first: a song with your own lyrics or an instrumental soundtrack? Tell us in the comments.

Further reading

Leave a Reply

Making Music 4 Ever
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.