Lyria 3.5로 음악 생성

Lyria 3.5로 음악 생성

Lyria 3.5는 Gemini API를 통해 제공되는 Google의 음악 생성 모델 계열이에요. Lyria 3.5로 텍스트 프롬프트나 이미지에서 고품질 44.1kHz 스테레오 오디오를 생성할 수 있어요. 이 모델들은 보컬, 시간 맞춤 가사, 완전한 악기 편성을 포함한 구조적 일관성을 제공해요.

Lyria 계열에는 다음 모델이 포함돼요.

모델 모델 ID 최적 용도 길이 출력
Lyria 3 Clip lyria-3-clip-preview 짧은 클립, 루프, 미리보기 30초 MP3
Lyria 3.5 lyria-3.5 후렴, 코러스, 브리지가 있는 풀렝스 곡 몇 분(프롬프트로 제어 가능) MP3

두 모델 모두 표준 generateContent 메서드와 새로운 Interactions API로 사용할 수 있으며, 멀티모달 입력(텍스트와 이미지)을 지원하고 44.1kHz 고충실도 스테레오 오디오를 생성해요.

출처: 원문

본문

음악 클립 생성

Lyria 3 Clip 모델은 항상 30초 클립을 생성해요. 클립을 생성하려면 텍스트 프롬프트로 generateContent 메서드를 호출하세요. 응답에는 항상 생성된 가사와 곡 구조가 오디오와 함께 포함돼요.

from google import genai

client = genai.Client()

response = client.models.generate_content(
    model="lyria-3-clip-preview",
    contents="Create a 30-second cheerful acoustic folk song with "
             "guitar and harmonica.",
)

# Parse the response
for part in response.parts:
    if part.text is not None:
        print(part.text)
    elif part.inline_data is not None:
        with open("clip.mp3", "wb") as f:
            f.write(part.inline_data.data)
        print("Audio saved to clip.mp3")
import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";

const ai = new GoogleGenAI({});

async function main() {
  const response = await ai.models.generateContent({
    model: "lyria-3-clip-preview",
    contents: "Create a 30-second cheerful acoustic folk song with " +
              "guitar and harmonica.",

  });

  for (const part of response.candidates[0].content.parts) {
    if (part.text) {
      console.log(part.text);
    } else if (part.inlineData) {
      const buffer = Buffer.from(part.inlineData.data, "base64");
      fs.writeFileSync("clip.mp3", buffer);
      console.log("Audio saved to clip.mp3");
    }
  }
}

main();
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "google.golang.org/genai"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    result, err := client.Models.GenerateContent(
        ctx,
        "lyria-3-clip-preview",
        genai.Text("Create a 30-second cheerful acoustic folk song " +
                   "with guitar and harmonica."),
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }

    for _, part := range result.Candidates[0].Content.Parts {
        if part.Text != "" {
            fmt.Println(part.Text)
        } else if part.InlineData != nil {
            err := os.WriteFile("clip.mp3", part.InlineData.Data, 0644)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Println("Audio saved to clip.mp3")
        }
    }
}
import com.google.genai.Client;
import com.google.genai.types.GenerateContentResponse;
import com.google.genai.types.Part;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class GenerateMusicClip {
  public static void main(String[] args) throws IOException {

    try (Client client = new Client()) {
      GenerateContentResponse response = client.models.generateContent(
          "lyria-3-clip-preview",
          "Create a 30-second cheerful acoustic folk song with "
              + "guitar and harmonica.");

      for (Part part : response.parts()) {
        if (part.text().isPresent()) {
          System.out.println(part.text().get());
        } else if (part.inlineData().isPresent()) {
          var blob = part.inlineData().get();
          if (blob.data().isPresent()) {
            Files.write(Paths.get("clip.mp3"), blob.data().get());
            System.out.println("Audio saved to clip.mp3");
          }
        }
      }
    }
  }
}
curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/lyria-3-clip-preview:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "parts": [
        {"text": "Create a 30-second cheerful acoustic folk song with guitar and harmonica."}
      ]
    }]
  }'

풀렝스 노래 생성

lyria-3.5 모델을 사용해 몇 분 동안 지속되는 풀렝스 노래를 생성하세요. Pro 모델은 음악 구조를 이해하고 뚜렷한 후렴, 코러스, 브리지가 있는 구성을 만들 수 있어요. 프롬프트에서 지정하거나("2분 노래 만들어줘"처럼) 타임스탬프로 구조를 정의해 길이에 영향을 줄 수 있어요.

response = client.models.generate_content(
    model="lyria-3.5",
    contents="An epic cinematic orchestral piece about a journey home. "
             "Starts with a solo piano intro, builds through sweeping "
             "strings, and climaxes with a massive wall of sound.",
)
const response = await ai.models.generateContent({
  model: "lyria-3.5",
  contents: "An epic cinematic orchestral piece about a journey home. " +
            "Starts with a solo piano intro, builds through sweeping " +
            "strings, and climaxes with a massive wall of sound.",

});
result, err := client.Models.GenerateContent(
    ctx,
    "lyria-3.5",
    genai.Text("An epic cinematic orchestral piece about a journey " +
               "home. Starts with a solo piano intro, builds through " +
               "sweeping strings, and climaxes with a massive wall of sound."),
    nil,
)
curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/lyria-3.5:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "parts": [
        {"text": "An epic cinematic orchestral piece about a journey home. Starts with a solo piano intro, builds through sweeping strings, and climaxes with a massive wall of sound."}
      ]
    }]
  }'

출력 형식 선택

기본적으로 Lyria 3.5 모델은 MP3 형식으로 오디오를 생성해요. Lyria 3.5의 경우 generationConfig의 response_format을 설정해 WAV 형식으로 출력을 요청할 수도 있어요.

from google.genai import types

response = client.models.generate_content(
    model="lyria-3.5",
    contents="An atmospheric ambient track.",
    config=types.GenerateContentConfig(
        response_modalities=["AUDIO", "TEXT"],
        response_format={"audio": {"mime_type": "audio/wav"}},
    ),
)
const response = await ai.models.generateContent({
  model: "lyria-3.5",
  contents: "An atmospheric ambient track.",
  config: {
    responseModalities: ["AUDIO", "TEXT"],
    responseFormat: { audio: { mimeType: "audio/wav" } },
  },
});
config := &genai.GenerateContentConfig{
    ResponseModalities: []string{"AUDIO", "TEXT"},
    ResponseMIMEType:   "audio/wav",
}

result, err := client.Models.GenerateContent(
    ctx,
    "lyria-3.5",
    genai.Text("An atmospheric ambient track."),
    config,
)
curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/lyria-3.5:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "parts": [
        {"text": "An atmospheric ambient track."}
      ]
    }],
    "generationConfig": {
      "responseModalities": ["AUDIO", "TEXT"],
      "responseFormat": { "audio": { "mimeType": "audio/wav" } }
    }
  }'

응답 파싱

Lyria 3.5의 응답에는 여러 파트가 포함돼요. 텍스트 파트에는 생성된 가사나 곡 구조의 JSON 설명이 포함돼요. inline_data가 있는 파트에는 오디오 바이트가 포함돼요.

lyrics = []
audio_data = None

for part in response.parts:
    if part.text is not None:
        lyrics.append(part.text)
    elif part.inline_data is not None:
        audio_data = part.inline_data.data

if lyrics:
    print("Lyrics:\n" + "\n".join(lyrics))

if audio_data:
    with open("output.mp3", "wb") as f:
        f.write(audio_data)
const lyrics = [];
let audioData = null;

for (const part of response.candidates[0].content.parts) {
  if (part.text) {
    lyrics.push(part.text);
  } else if (part.inlineData) {
    audioData = Buffer.from(part.inlineData.data, "base64");
  }
}

if (lyrics.length) {
  console.log("Lyrics:\n" + lyrics.join("\n"));
}

if (audioData) {
  fs.writeFileSync("output.mp3", audioData);
}
var lyrics []string
var audioData []byte

for _, part := range result.Candidates[0].Content.Parts {
    if part.Text != "" {
        lyrics = append(lyrics, part.Text)
    } else if part.InlineData != nil {
        audioData = part.InlineData.Data
    }
}

if len(lyrics) > 0 {
    fmt.Println("Lyrics:\n" + strings.Join(lyrics, "\n"))
}

if audioData != nil {
    err := os.WriteFile("output.mp3", audioData, 0644)
    if err != nil {
        log.Fatal(err)
    }
}
# The output from the REST API is a JSON object containing base64 encoded data.
# You can extract the text or the audio data using a tool like jq.
# To extract the audio and save it to a file:
curl ... | jq -r '.candidates[0].content.parts[] | select(.inlineData) | .inlineData.data' | base64 -d > output.mp3

이미지로 음악 생성

Lyria 3.5는 멀티모달 입력을 지원해요. 텍스트 프롬프트와 함께 최대 10개의 이미지를 제공할 수 있고, 모델은 시각 콘텐츠에서 영감을 받은 음악을 작곡해요.

from PIL import Image

image = Image.open("desert_sunset.jpg")

response = client.models.generate_content(
    model="lyria-3.5",
    contents=[
        "An atmospheric ambient track inspired by the mood and "
        "colors in this image.",
        image,
    ],
)
const imageData = fs.readFileSync("desert_sunset.jpg");
const base64Image = imageData.toString("base64");

const response = await ai.models.generateContent({
  model: "lyria-3.5",
  contents: [
    { text: "An atmospheric ambient track inspired by the mood " +
            "and colors in this image." },
    {
      inlineData: {
        mimeType: "image/jpeg",
        data: base64Image,
      },
    },
  ],

});
curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/lyria-3.5:generateContent" \
  -H "x-goog-api-key: *** \
  -H 'Content-Type: application/json' \
  -d "{
    \"contents\": [{
      \"parts\":[
          {\"text\": \"An atmospheric ambient track inspired by the mood and colors in this image.\"},
          {
            \"inline_data\": {
              \"mime_type\":\"image/jpeg\",
              \"data\": \"<BASE64_IMAGE_DATA>\"
            }
          }
      ]
    }]
  }"

커스텀 가사 제공

자신의 가사를 작성해 프롬프트에 포함할 수 있어요. 곡 구조를 모델이 이해하도록 [Verse], [Chorus], [Bridge] 같은 섹션 태그를 사용하세요.

prompt = """
Create a dreamy indie pop song with the following lyrics:

[Verse 1]
Walking through the neon glow,
city lights reflect below,
every shadow tells a story,
every corner, fading glory.

[Chorus]
We are the echoes in the night,
burning brighter than the light,
hold on tight, don't let me go,
we are the echoes down below.

[Verse 2]
Footsteps lost on empty streets,
rhythms sync to heartbeats,
whispers carried by the breeze,
dancing through the autumn leaves.
"""

response = client.models.generate_content(
    model="lyria-3.5",
    contents=prompt,
)
prompt := `
Create a dreamy indie pop song with the following lyrics:

[Verse 1]
Walking through the neon glow,
city lights reflect below,
every shadow tells a story,
every corner, fading glory.

[Chorus]
We are the echoes in the night,
burning brighter than the light,
hold on tight, don't let me go,
we are the echoes down below.

[Verse 2]
Footsteps lost on empty streets,
rhythms sync to heartbeats,
whispers carried by the breeze,
dancing through the autumn leaves.
`

result, err := client.Models.GenerateContent(
    ctx,
    "lyria-3.5",
    genai.Text(prompt),
    nil,
)
curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/lyria-3.5:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "parts": [
        {"text": "Create a dreamy indie pop song with the following lyrics: ..."}
      ]
    }]
  }'

타이밍과 구조 제어

타임스탬프를 사용해 곡의 특정 순간에 정확히 무엇이 일어나는지 지정할 수 있어요. 이는 악기가 언제 들어오는지, 가사가 언제 전달되는지, 곡이 어떻게 진행되는지 제어하는 데 유용해요.

prompt = """
[0:00 - 0:10] Intro: Begin with a soft lo-fi beat and muffled
              vinyl crackle.
[0:10 - 0:30] Verse 1: Add a warm Fender Rhodes piano melody
              and gentle vocals singing about a rainy morning.
[0:30 - 0:50] Chorus: Full band with upbeat drums and soaring
              synth leads. The lyrics are hopeful and uplifting.
[0:50 - 1:00] Outro: Fade out with the piano melody alone.
"""

response = client.models.generate_content(
    model="lyria-3.5",
    contents=prompt,
)
curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/lyria-3.5:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "parts": [
        {"text": "[0:00 - 0:10] Intro: ..."}
      ]
    }]
  }'

연주 트랙 생성

배경 음악, 게임 사운드트랙, 보컬이 필요하지 않은 모든 사용 사례의 경우 모델에 연주 전용 트랙을 생성하도록 프롬프트할 수 있어요.

response = client.models.generate_content(
    model="lyria-3-clip-preview",
    contents="A bright chiptune melody in C Major, retro 8-bit "
             "video game style. Instrumental only, no vocals.",
)
curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/lyria-3-clip-preview:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "parts": [
        {"text": "A bright chiptune melody in C Major, retro 8-bit video game style. Instrumental only, no vocals."}
      ]
    }]
  }'

다른 언어로 음악 생성

Lyria 3.5는 프롬프트의 언어로 가사를 생성해요. 프랑스어 가사로 노래를 생성하려면 프롬프트를 프랑스어로 작성하세요. 모델은 보컬 스타일과 발음을 언어에 맞게 조정해요.

response = client.models.generate_content(
    model="lyria-3.5",
    contents="Crée une chanson pop romantique en français sur un "
             "coucher de soleil à Paris. Utilise du piano et de "
             "la guitare acoustique.",
)
curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/lyria-3.5:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "parts": [
        {"text": "Crée une chanson pop romantique en français sur un coucher de soleil à Paris. Utilise du piano et de la guitare acoustique."}
      ]
    }]
  }'

모델 지능

Lyria 3.5는 프롬프트를 분석하며, 모델이 프롬프트에 따라 음악 구조(인트로, 후렴, 코러스, 브리지 등)를 통해 추론하는 과정을 거쳐요. 이는 오디오가 생성되기 전에 발생하며 구조적 일관성과 음악성을 보장해요.

Interactions API

Interactions API — Gemini 모델 및 에이전트와 상호작용하기 위한 통합 인터페이스 — 로 Lyria 3.5 모델을 사용할 수 있어요. 복잡한 멀티모달 사용 사례를 위한 상태 관리와 장기 실행 작업을 간소화해요.

import base64
from google import genai

client = genai.Client()

interaction = client.interactions.create(
    model="lyria-3.5",
    input="A melancholic jazz fusion track in D minor, " +
          "featuring a smooth saxophone melody, walking bass line, " +
          "and complex drum rhythms.",
)

generated_audio = interaction.output_audio
if generated_audio:
    with open("interaction_output.mp3", "wb") as f:
        f.write(base64.b64decode(generated_audio.data))
    print("Audio saved to interaction_output.mp3")

lyrics = interaction.output_text
if lyrics:
    print(f"Lyrics:\n{lyrics}")
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';

const client = new GoogleGenAI({});

const interaction = await client.interactions.create({
  model: 'lyria-3.5',
  input: 'A melancholic jazz fusion track in D minor, ' +
         'featuring a smooth saxophone melody, walking bass line, ' +
         'and complex drum rhythms.',
});

const generatedAudio = interaction.output_audio;
if (generatedAudio) {
  fs.writeFileSync('interaction_output.mp3', Buffer.from(generatedAudio.data, 'base64'));
  console.log('Audio saved to interaction_output.mp3');
}

const lyrics = interaction.output_text;
if (lyrics) {
  console.log(`Lyrics:\n${lyrics}`);
}
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: *** \
-d '{
    "model": "lyria-3.5",
    "input": "A melancholic jazz fusion track in D minor, featuring a smooth saxophone melody, walking bass line, and complex drum rhythms."
}'

프롬프팅 가이드

음악 장르, 악기, 곡 구조, 커스텀 가사, 보컬 전달 스타일을 위한 효과적인 프롬프트 작성법을 알아보려면 Lyria 프롬프트 가이드를 참조하세요.

모범 사례

  • 먼저 Clip으로 반복하세요. 풀렝스 생성에 lyria-3.5로 확정하기 전에 더 빠른 lyria-3-clip-preview 모델로 프롬프트를 실험하세요.
  • 구체적으로 작성하세요. 모호한 프롬프트는 일반적인 결과를 만들어요. 최상의 출력을 위해 악기, BPM, 키, 분위기, 구조를 언급하세요.
  • 언어를 맞추세요. 가사를 원하는 언어로 프롬프트하세요.
  • 섹션 태그를 사용하세요. [Verse], [Chorus], [Bridge] 태그는 모델이 따라야 할 명확한 구조를 제공해요.
  • 가사와 지침을 분리하세요. 커스텀 가사를 제공할 때 음악 방향 지침과 명확히 분리하세요.

제한 사항

  • 안전: 모든 프롬프트는 안전 필터로 검사돼요. 필터를 트리거하는 프롬프트는 차단돼요. 특정 아티스트 목소리를 요청하거나 저작권 가사 생성 같은 프롬프트가 포함돼요.
  • 워터마킹: 모든 생성 오디오에는 식별을 위한 SynthID 오디오 워터마크가 포함돼요. 이 워터마크는 인간 귀에는 인지할 수 없으며 청취 경험에 영향을 주지 않아요.
  • 다중 턴 편집: 음악 생성은 단일 턴 프로세스예요. 여러 프롬프트를 통한 반복 편집이나 생성된 클립 다듬기는 현재 Lyria 3.5 버전에서 지원되지 않아요.
  • 길이: Clip 모델은 항상 30초 클립을 생성해요. Pro 모델은 몇 분 지속되는 노래를 생성하고, 정확한 길이는 프롬프트로 영향 줄 수 있어요.
  • 결정성: 같은 프롬프트라도 호출 간에 결과가 달라질 수 있어요.

다음 단계

더 알아보기 (Learn more)