Gemini API יכול להפוך קלט טקסט לאודיו עם דובר אחד או כמה דוברים באמצעות יכולות יצירת הטקסט לדיבור (TTS) של Gemini.
הפקת טקסט לדיבור היא ניתנת לשליטה, כלומר אפשר לשלב מטא-נתונים מובְנים של תור (speech_metadata) ותגי קול מוטבעים כדי להגדיר את הסגנון, המבטא, הקצב והטון של האודיו.
יכולת ה-TTS שונה מיצירת דיבור שמתבצעת באמצעות Live API, שנועד לאודיו אינטראקטיבי ולא מובנה, ולתשומות ולתפוקות מולטי-מודאליות. Live API מצטיין בהקשרים דינמיים של שיחות, אבל TTS דרך Gemini API מותאם לתרחישים שבהם נדרש דיבור מדויק של טקסט עם שליטה מפורטת בסגנון ובצליל, כמו יצירת פודקאסטים או ספרי אודיו.
במדריך הזה מוסבר איך ליצור אודיו עם דובר אחד או עם כמה דוברים מטקסט באמצעות Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) ו-Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts).
לפני שמתחילים
חשוב לוודא שאתם משתמשים במודל Gemini TTS שמופיע בקטע מודלים נתמכים. כדי לקבל את התוצאות הטובות ביותר, כדאי לעיין במאמר מתי כדאי להשתמש באיזה מודל כדי לבחור את המודל המתאים ביותר לעומס העבודה שלכם.
מומלץ לבדוק את מודלי ה-TTS של Gemini ב-AI Studio לפני שמתחילים לפתח.
TTS עם דובר יחיד
כדי להמיר טקסט לאודיו של דובר יחיד באמצעות מודלים של Gemini 3.8 TTS, מעבירים את התמליל המילולי ב-input, מצרפים סגנון ברמת התור באמצעות הערה speech_metadata ומגדירים את הקול ב-generation_config.speech_config. אפשר לבחור קול מתוך אפשרויות הקול המובנות, מתוך ספריית הקולות המורחבת (GET /v1beta/voices), מתוך מזהה של עיצוב קול בהתאמה אישית (voice_...), או מתוך מזהה של רפליקציה של קולות (voice_..., או voicekey_... אם רוצים להשתמש באפשרות בלי שמירת מצב).
בדוגמה הזו, פלט האודיו (audio/wav) בפורמט WAV שמוגדר כברירת מחדל מהמודל נשמר ישירות בקובץ:
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-3.8-flash-tts",
input=[{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly",
}],
}],
}],
response_format={"type": "audio"},
generation_config={
"speech_config": [
{"voice": "Kore"},
]
},
)
with open("out.wav", "wb") as f:
f.write(base64.b64decode(interaction.output_audio.data))
JavaScript
import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';
async function main() {
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
model: 'gemini-3.8-flash-tts',
input: [{
type: 'user_input',
content: [{
type: 'text',
text: 'Have a wonderful day!',
annotations: [{
type: 'speech_metadata',
style: 'cheerful and friendly',
}],
}],
}],
response_format: { type: 'audio' },
generation_config: {
speech_config: [
{ voice: 'Kore' },
],
},
});
const audioBuffer = Buffer.from(interaction.output_audio.data, 'base64');
fs.writeFileSync('out.wav', audioBuffer);
}
await main();
Go
package main
import (
"context"
"encoding/base64"
"encoding/binary"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func saveWaveFile(filename string, pcmData []byte) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
sampleRate := uint32(24000)
numChannels := uint16(1)
bitsPerSample := uint16(16)
byteRate := sampleRate * uint32(numChannels) * uint32(bitsPerSample/8)
blockAlign := numChannels * (bitsPerSample / 8)
dataSize := uint32(len(pcmData))
f.WriteString("RIFF")
binary.Write(f, binary.LittleEndian, uint32(36+dataSize))
f.WriteString("WAVEfmt ")
binary.Write(f, binary.LittleEndian, uint32(16))
binary.Write(f, binary.LittleEndian, uint16(1))
binary.Write(f, binary.LittleEndian, numChannels)
binary.Write(f, binary.LittleEndian, sampleRate)
binary.Write(f, binary.LittleEndian, byteRate)
binary.Write(f, binary.LittleEndian, blockAlign)
binary.Write(f, binary.LittleEndian, bitsPerSample)
f.WriteString("data")
binary.Write(f, binary.LittleEndian, dataSize)
_, err = f.Write(pcmData)
return err
}
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
generationConfig := &interactions.GenerationConfig{
SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
{Voice: genai.Ptr("Kore")},
})),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.1-flash-tts-preview"),
Input: interactions.NewInteractionsInput("Say cheerfully: Have a wonderful day!"),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
)),
GenerationConfig: generationConfig,
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputAudio != nil && res.Interaction.OutputAudio.Data != nil {
pcmBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputAudio.Data)
if err != nil {
log.Fatal(err)
}
if err := saveWaveFile("out.wav", pcmBytes); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.8-flash-tts",
"input": [{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly"
}]
}]
}],
"response_format": {
"type": "audio"
},
"generation_config": {
"speech_config": [
{ "voice": "Kore" }
]
}
}' | jq -r '[.steps[] | select(.type=="model_output") | .content[] | select(.type=="audio")] | last | .data' | base64 --decode > out.wav
ב-SDK של Python ו-JavaScript, אפשר לאחזר נתוני אודיו שנוצרו באמצעות מאפיין הנוחות interaction.output_audio, שמחזיר את בלוק האודיו האחרון שנוצר (בתגובות JSON של REST גולמיות, האודיו בקידוד base64 מאוחסן ב-steps[].content[].data). פרטים על מאפייני נוחות זמינים בסקירה הכללית על אינטראקציות.
המרת טקסט לדיבור (TTS) עם כמה דוברים
בדיאלוג עם כמה דוברים, מגדירים שני דוברים ב-speech_config.speakers
ומעבירים כל תור כפריט טקסט נפרד עם הערה speech_metadata שמציינת את speaker ואת style האופציונלי ברמת התור. שימוש ב-"mode": "conversational" לקצב טבעי של חילופי תורות:
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-3.8-flash-tts",
input=[{
"type": "user_input",
"content": [
{
"type": "text",
"text": "How's it going today Jane?",
"annotations": [{
"type": "speech_metadata",
"speaker": "Joe",
"style": "cheerful and friendly",
}],
},
{
"type": "text",
"text": "Not too bad, how about you? Ready to test these new voices?",
"annotations": [{
"type": "speech_metadata",
"speaker": "Jane",
"style": "calm and relaxed",
}],
},
],
}],
response_format={"type": "audio"},
generation_config={
"speech_config": {
"mode": "conversational",
"speakers": [
{"speaker": "Joe", "voice": "Puck"},
{"speaker": "Jane", "voice": "Kore"},
],
}
},
)
with open("out.wav", "wb") as f:
f.write(base64.b64decode(interaction.output_audio.data))
JavaScript
import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';
async function main() {
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
model: 'gemini-3.8-flash-tts',
input: [{
type: 'user_input',
content: [
{
type: 'text',
text: "How's it going today Jane?",
annotations: [{
type: 'speech_metadata',
speaker: 'Joe',
style: 'cheerful and friendly',
}],
},
{
type: 'text',
text: 'Not too bad, how about you? Ready to test these new voices?',
annotations: [{
type: 'speech_metadata',
speaker: 'Jane',
style: 'calm and relaxed',
}],
},
],
}],
response_format: { type: 'audio' },
generation_config: {
speech_config: {
mode: 'conversational',
speakers: [
{ speaker: 'Joe', voice: 'Puck' },
{ speaker: 'Jane', voice: 'Kore' },
],
},
},
});
const audioBuffer = Buffer.from(interaction.output_audio.data, 'base64');
fs.writeFileSync('out.wav', audioBuffer);
}
await main();
Go
package main
import (
"context"
"encoding/base64"
"encoding/binary"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func saveWaveFile(filename string, pcmData []byte) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
sampleRate := uint32(24000)
numChannels := uint16(1)
bitsPerSample := uint16(16)
byteRate := sampleRate * uint32(numChannels) * uint32(bitsPerSample/8)
blockAlign := numChannels * (bitsPerSample / 8)
dataSize := uint32(len(pcmData))
f.WriteString("RIFF")
binary.Write(f, binary.LittleEndian, uint32(36+dataSize))
f.WriteString("WAVEfmt ")
binary.Write(f, binary.LittleEndian, uint32(16))
binary.Write(f, binary.LittleEndian, uint16(1))
binary.Write(f, binary.LittleEndian, numChannels)
binary.Write(f, binary.LittleEndian, sampleRate)
binary.Write(f, binary.LittleEndian, byteRate)
binary.Write(f, binary.LittleEndian, blockAlign)
binary.Write(f, binary.LittleEndian, bitsPerSample)
f.WriteString("data")
binary.Write(f, binary.LittleEndian, dataSize)
_, err = f.Write(pcmData)
return err
}
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
prompt := "TTS the following conversation between Joe and Jane:\n" +
"Joe: How's it going today Jane?\n" +
"Jane: Not too bad, how about you?"
generationConfig := &interactions.GenerationConfig{
SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
{Speaker: genai.Ptr("Joe"), Voice: genai.Ptr("Kore")},
{Speaker: genai.Ptr("Jane"), Voice: genai.Ptr("Puck")},
})),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.1-flash-tts-preview"),
Input: interactions.NewInteractionsInput(prompt),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
)),
GenerationConfig: generationConfig,
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputAudio != nil && res.Interaction.OutputAudio.Data != nil {
pcmBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputAudio.Data)
if err != nil {
log.Fatal(err)
}
if err := saveWaveFile("out.wav", pcmBytes); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.8-flash-tts",
"input": [{
"type": "user_input",
"content": [
{
"type": "text",
"text": "How'\''s it going today Jane?",
"annotations": [{
"type": "speech_metadata",
"speaker": "Joe",
"style": "cheerful and friendly"
}]
},
{
"type": "text",
"text": "Not too bad, how about you? Ready to test these new voices?",
"annotations": [{
"type": "speech_metadata",
"speaker": "Jane",
"style": "calm and relaxed"
}]
}
]
}],
"response_format": {
"type": "audio"
},
"generation_config": {
"speech_config": {
"mode": "conversational",
"speakers": [
{ "speaker": "Joe", "voice": "Puck" },
{ "speaker": "Jane", "voice": "Kore" }
]
}
}
}'
שליטה בסגנון הדיבור באמצעות מטא-נתונים ותגים
Gemini 3.8 TTS מתייחס לשדה text כאל תמליל מילה במילה. כדי לשלוט בהעברה בלי שההוראות לבימוי יוקראו בקול רם, צריך לפצל את ההוראות לפי היקף:
- הגייה רציפה ברמת הפנייה (
speech_metadata.style): כדי להגדיר רגשות, סגנון הגייה, פרוזודיה, קצב ועוצמת קול שרלוונטיים לכל הפנייה, צריך להזין אותם בשדהstyle(לדוגמה,"style": "whispered urgently","style": "out of breath"או"style": "warm and enthusiastic"). - אירועים בנקודת זמן מסוימת (תגים מוטבעים): מציבים פרצי קול רגעיים שאינם דיבור או הפסקות ישירות בתוך התמליל באמצעות סוגריים זוויתיים (לדוגמה,
"Wait... <short pause> did you hear that? <sigh>"או"Excuse me <cough> as I was saying...").
במדריך לכתיבת הנחיות מפורטות שיטות מומלצות.
Go
package main
import (
"context"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
transcriptRes, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput(
"Generate a short transcript around 100 words that reads " +
"like it was clipped from a podcast by excited herpetologists. " +
"The hosts names are Dr. Anya and Liam.",
),
}),
})
if err != nil {
log.Fatal(err)
}
var transcript string
if transcriptRes.Interaction.OutputText != nil {
transcript = *transcriptRes.Interaction.OutputText
}
generationConfig := &interactions.GenerationConfig{
SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
{Speaker: genai.Ptr("Dr. Anya"), Voice: genai.Ptr("Kore")},
{Speaker: genai.Ptr("Liam"), Voice: genai.Ptr("Puck")},
})),
}
ttsRes, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.1-flash-tts-preview"),
Input: interactions.NewInteractionsInput(transcript),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
)),
GenerationConfig: generationConfig,
}),
})
if err != nil {
log.Fatal(err)
}
_ = ttsRes
}
יצירת דיבור בסטרימינג
כדי להזרים את האודיו שנוצר בזמן הסינתזה, צריך להגדיר את הערך stream: true. בשונה מבקשות unary (שמחזירות קובץ WAV מלא עם כותרת RIFF), בקשות סטרימינג מחזירות נתחי PCM לינאריים גולמיים של 16 ביט בפורמט little-endian (audio/l16, 24 kHz, מונו) ללא כותרת כברירת מחדל, כך שאפשר להפעיל או לחבר ברצף נתחי אודיו ללא כותרות של קונטיינר.
Python
import base64
from google import genai
client = genai.Client()
stream = client.interactions.create(
model="gemini-3.8-flash-tts",
input=[{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly",
}],
}],
}],
response_format={"type": "audio"},
generation_config={
"speech_config": [
{"voice": "Kore"},
]
},
stream=True,
)
for event in stream:
if event.event_type == "step.delta":
if event.delta.type == "audio":
audio_data = base64.b64decode(event.delta.data)
# Process the audio chunk (e.g. play it or write to a file)
JavaScript
import {GoogleGenAI} from '@google/genai';
async function main() {
const client = new GoogleGenAI({});
const stream = await client.interactions.create({
model: 'gemini-3.8-flash-tts',
input: [{
type: 'user_input',
content: [{
type: 'text',
text: 'Have a wonderful day!',
annotations: [{
type: 'speech_metadata',
style: 'cheerful and friendly',
}],
}],
}],
response_format: { type: 'audio' },
generation_config: {
speech_config: [
{ voice: 'Kore' },
],
},
stream: true,
});
for await (const event of stream) {
if (event.event_type === 'step.delta') {
if (event.delta.type === 'audio') {
const audioBuffer = Buffer.from(event.delta.data, 'base64');
// Process the audio buffer
}
}
}
}
await main();
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
--no-buffer \
-d '{
"model": "gemini-3.8-flash-tts",
"input": [{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly"
}]
}]
}],
"response_format": {
"type": "audio"
},
"generation_config": {
"speech_config": [
{ "voice": "Kore" }
]
},
"stream": true
}'
פורמטים של פלט אודיו
מודלים של Gemini 3.8 TTS משתמשים בפורמטים שונים של אודיו כברירת מחדל, בהתאם לסוג הבקשה: unary או streaming:
- בקשות unary (
stream=False): החזרת אודיו מלא בפורמט WAV (audio/wav) עם כותרת RIFF רגילה (24 kHz, מונו, 16-bit signed little-endian PCM). אפשר לשמור את בייטים של האודיו המפוענח ישירות בקובץ.wavבלי להוסיף ידנית כותרת של WAV. - בקשות סטרימינג (
stream=True): החזרת נתחים של Linear PCM גולמי ללא כותרת (audio/l16) (24 kHz, מונו, 16-bit signed little-endian PCM) כברירת מחדל, כדי שאפשר יהיה להזרים או לשרשר נתחים ברציפות ללא כותרות של קונטיינר בכל נתח.
כדי לבקש קידוד אודיו או קצב דגימה שונים, מגדירים את mime_type ואת sample_rate האופציונליים בתוך response_format:
| פורמט | ערך של mime_type |
תיאור |
|---|---|---|
| WAV (ברירת מחדל אונרית) | "audio/wav" |
קובץ WAV לא דחוס עם כותרת RIFF (PCM עם סימן של 16 ביט, little-endian, מונו, ברירת מחדל של 24 kHz). ברירת המחדל לבקשות unary. |
| Raw PCM (L16) (ברירת מחדל לסטרימינג) | "audio/l16" |
אודיו PCM ליניארי לא דחוס, ללא כותרת, 16 ביט, חתום, little-endian (24 kHz, מונו). ברירת המחדל לבקשות סטרימינג. |
| Mu-law | "audio/mulaw" |
אודיו מקודד ב-8 ביט G.711 mu-law (בשימוש נפוץ במערכות טלפוניה/תגובה קולית אינטראקטיבית בצפון אמריקה וביפן). |
| A-law | "audio/alaw" |
אודיו מוצפן ב-8 ביט G.711 A-law (בשימוש נפוץ במערכות טלפוניה אירופאיות ובינלאומיות). |
אפשר גם לציין את sample_rate בהרץ (לדוגמה, 24000, 16000 או 8000).
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-3.8-flash-tts",
input=[{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly",
}],
}],
}],
response_format={
"type": "audio",
"mime_type": "audio/l16", # "audio/wav" (default), "audio/l16", "audio/mulaw", or "audio/alaw"
"sample_rate": 24000,
},
generation_config={
"speech_config": [
{"voice": "Kore"},
]
},
)
with open("out.pcm", "wb") as f:
f.write(base64.b64decode(interaction.output_audio.data))
JavaScript
import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';
async function main() {
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
model: 'gemini-3.8-flash-tts',
input: [{
type: 'user_input',
content: [{
type: 'text',
text: 'Have a wonderful day!',
annotations: [{
type: 'speech_metadata',
style: 'cheerful and friendly',
}],
}],
}],
response_format: {
type: 'audio',
mime_type: 'audio/l16', // 'audio/wav' (default), 'audio/l16', 'audio/mulaw', or 'audio/alaw'
sample_rate: 24000,
},
generation_config: {
speech_config: [
{ voice: 'Kore' },
],
},
});
const audioBuffer = Buffer.from(interaction.output_audio.data, 'base64');
fs.writeFileSync('out.pcm', audioBuffer);
}
await main();
Go
package main
import (
"context"
"encoding/base64"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
generationConfig := &interactions.GenerationConfig{
SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
{Voice: genai.Ptr("Kore")},
})),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.1-flash-tts-preview"),
Input: interactions.NewInteractionsInput("Say cheerfully: Have a wonderful day!"),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
)),
GenerationConfig: generationConfig,
Stream: genai.Ptr(true),
}),
})
if err != nil {
log.Fatal(err)
}
stream := res.InteractionSSEStreamEvent
defer stream.Close()
for stream.Next() {
event := stream.Value()
if stepDelta := event.GetDataStepDelta(); stepDelta != nil {
if audioDelta := stepDelta.GetDeltaAudio(); audioDelta != nil && audioDelta.Data != nil {
audioData, err := base64.StdEncoding.DecodeString(*audioDelta.Data)
if err != nil {
log.Fatal(err)
}
// Process the audio chunk (e.g. play it or write to a file)
_ = audioData
}
}
}
if err := stream.Err(); err != nil {
log.Fatal(err)
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.8-flash-tts",
"input": [{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly"
}]
}]
}],
"response_format": {
"type": "audio",
"mime_type": "audio/l16",
"sample_rate": 24000
},
"generation_config": {
"speech_config": [
{ "voice": "Kore" }
]
}
}'
אפשרויות קול
Gemini 3.8 TTS תומך בארבע דרכים לבחור או ליצור קולות:
- קולות מוכנים מראש: 30 קולות שנבחרו בקפידה ומפורטים בטבלה הבאה.
- ספריית קולות מורחבת: מאות קולות נוספים בשפות, במבטאים ובארכיטיפים של דמויות שניתן לגשת אליהם באמצעות
client.voices.list()(GET /v1beta/voices). - עיצוב קול: יצירת דמות קולית מותאמת אישית מתיאור בשפה טבעית ב-Google AI Studio או באמצעות
POST /v1beta/voices(type="prompted", שמחזירה מזהה קבועvoice_...ותצוגה מקדימה שלsample_audioWAV ב-CreateVoiceוב-GetVoice). - רפליקציה של קולות: שכפול של קול הדובר מאודיו של הפניה והסכמה ב-Google AI Studio או באמצעות
POST /v1beta/voices(type="replicated",store=Trueמתמשך כברירת מחדל אוstore=Falseאופציונלי בלי שמירת מצב).
מגבלות וערכי TTL של קולות מותאמים אישית
| הכתבה | מצב אחסון | מכסה / מגבלה | שמירה (TTL) |
|---|---|---|---|
קולות עם מצב (voice_..., בהנחיה או בשכפול) |
store=True |
200 קולות לכל פרויקט (משותפים בין קולות שנוצרו מהנחיות וקולות ששוכפלו) | שנה אחת |
מפתחות קוליים ללא מצב (voicekey_..., משוכפלים) |
store=False |
בניהול של לקוח | 7 ימים |
קולות שנוצרו מראש
| Zephyr -- Bright | Puck -- Upbeat | Charon -- אינפורמטיבי |
| Kore -- Firm | Fenrir – מתלהב | Leda -- Youthful |
| Orus -- Firm | Aoede – Breezy | Callirrhoe – נינוח |
| Autonoe -- Bright | Enceladus -- Breathy | Iapetus -- Clear |
| Umbriel -- Easy-going | Algieba – Smooth | Despina -- Smooth |
| Erinome -- Clear | Algenib -- מחוספס | Rasalgethi -- Informative |
| Laomedeia -- Upbeat | Achernar -- Soft | Alnilam -- Firm |
| Schedar – Even | Gacrux -- Mature | Pulcherrima -- Forward |
| Achird -- Friendly | Zubenelgenubi – רגוע | Vindemiatrix – עדין |
| Sadachbia -- Lively | Sadaltager -- Knowledgeable | Sulafat – חמה |
ספריית קולות מורחבת וסינון
בנוסף ל-30 הקולות המוצגים בטבלה שלמעלה, ספריית הקולות המורחבת כוללת מאות קולות נוספים בשפות שונות, עם מבטאים אזוריים, דמויות וסגנונות שונים. אתם יכולים לעיין בספריית הקולות המלאה, לסנן אותה ולשמוע דוגמאות שלה באופן אינטראקטיבי ב-Google AI Studio, או לשלוח אליה שאילתות באופן פרוגרמטי באמצעות client.voices.list() (GET /v1beta/voices, באמצעות google-genai גרסה 2.25.0 ואילך / @google/genai גרסה 2.24.0 ואילך).
ListVoices מחזירה את הקולות המותאמים אישית ששמרתם (בסדר מהחדש לישן), ואחריהם את הקולות המוכנים מראש שמתאימים לקריטריונים של המסנן. כשמעבירים כמה ערכים למסנן רשימה, המערכת מחזירה את הקולות שתואמים לכל ערך במסנן הזה (OR), ואילו פרמטרים נפרדים של מסנן משולבים עם AND:
| פרמטר | סוג | תיאור |
|---|---|---|
language_code |
list[str] |
תגי שפה בתקן BCP-47 (לדוגמה, ["en-US", "en-GB"]). התאמה מדויקת לא תלוית-רישיות. |
region_code |
list[str] |
קודים אזוריים לפי תקן ISO 3166-1 alpha-2 או UN M.49 (לדוגמה, ["US", "GB"]). |
accent |
list[str] |
תיאור(ים) של מבטא אזורי (לדוגמה, ["American", "British"]). |
gender |
list[str] |
הצגת המגדר הנתפס ("female", "male" או "neutral"). |
pitch |
list[str] |
סיווג גובה הקול ("low", "medium" או "high"). |
persona |
list[str] |
פרסונה קולית או ארכיטיפ של דמות (לדוגמה, ["Warm, Friendly"], ["Narrator"]). |
contexts (context ב-REST) |
list[str] |
דומיין לשימוש אופטימלי (לדוגמה, ["Audiobook", "Conversational", "News"]). |
type (type_ ב-Python) |
list[str] |
סינון לפי מקור הקול: "prebuilt", "prompted" (עיצוב קול) או "replicated" (רפליקציה של קולות). |
search |
str |
חיפוש מחרוזת משנה בטקסט חופשי התאים ל-display_name ול-description ללא הבחנה בין אותיות רישיות לאותיות קטנות. |
page_size |
int |
המספר המקסימלי של קולות שמוחזרים לכל דף (ברירת מחדל 50, מקסימום 1000). |
page_token |
str |
טוקן מ-response.next_page_token לאחזור של דף התוצאות הבא. |
Python
from google import genai
client = genai.Client()
# Filter the Voice Library by language, gender, pitch, domain context, and keyword
response = client.voices.list(
language_code=["en-US", "en-GB"],
gender=["female"],
pitch=["medium", "low"],
contexts=["Audiobook", "Conversational"],
type_=["prebuilt"],
search="warm",
page_size=50,
)
for voice in response.voices or []:
print(
f"{voice.id} | {voice.display_name} ({voice.language_code},"
f" {voice.accent}, {voice.gender}, pitch={voice.pitch}):"
f" {voice.description}"
)
JavaScript
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI();
// Filter the Voice Library by language, gender, pitch, domain context, and keyword
const response = await ai.voices.list({
language_code: ["en-US", "en-GB"],
gender: ["female"],
pitch: ["medium", "low"],
contexts: ["Audiobook", "Conversational"],
type: ["prebuilt"],
search: "warm",
page_size: 50,
});
for (const voice of response.voices ?? []) {
console.log(
`${voice.id} | ${voice.display_name} (${voice.language_code}, ${voice.accent}, ${voice.gender}, pitch=${voice.pitch}): ${voice.description}`
);
}
REST
curl -G "https://generativelanguage.googleapis.com/v1beta/voices" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
--data-urlencode "language_code=en-US" \
--data-urlencode "language_code=en-GB" \
--data-urlencode "gender=female" \
--data-urlencode "pitch=medium" \
--data-urlencode "context=Audiobook" \
--data-urlencode "type=prebuilt" \
--data-urlencode "search=warm" \
--data-urlencode "page_size=50"
שפות נתמכות
מודלי ה-TTS מזהים את שפת הקלט באופן אוטומטי.
Gemini 3.8 Flash TTS
(gemini-3.8-flash-tts) תומך ביותר מ-130 שפות, ו-Gemini 3.8 Flash-Lite TTS
(gemini-3.8-flash-lite-tts) תומך ביותר מ-100 שפות:
| שפה | Gemini 3.8 Flash TTS | Gemini 3.8 Flash-Lite TTS |
|---|---|---|
| אצ'ה (כתב ערבי) | ✔️ | ✔️ |
| אפריקאנס | ✔️ | ✔️ |
| אקאן | ✔️ | ✔️ |
| אמהרית | ✔️ | ✔️ |
| ארמנית | ✔️ | ✔️ |
| אסאמית | ✔️ | ✔️ |
| עוואדי | ✔️ | ✔️ |
| באלינזית | ✔️ | ✔️ |
| בנגלית | ✔️ | ✔️ |
| בנג'אר (כתב ערבי) | ✔️ | — |
| בנג'אר (כתב לטיני) | ✔️ | ✔️ |
| בשקירית | ✔️ | — |
| בסקית | ✔️ | ✔️ |
| בלארוסית | ✔️ | ✔️ |
| במבה | ✔️ | — |
| בוג'פורי | ✔️ | ✔️ |
| בוסנית | ✔️ | ✔️ |
| בוגינזית | ✔️ | ✔️ |
| בולגרית | ✔️ | ✔️ |
| בורמזית | ✔️ | — |
| קנטונזית | ✔️ | ✔️ |
| קטלאנית | ✔️ | ✔️ |
| סבואנו | ✔️ | ✔️ |
| כורדית מרכזית | ✔️ | ✔️ |
| צ'אטיסגארי | ✔️ | ✔️ |
| סינית (כתב האן) | ✔️ | ✔️ |
| סינית (כתב האנט) | ✔️ | ✔️ |
| טטארית של חצי האי קרים | ✔️ | — |
| קרואטית | ✔️ | ✔️ |
| צ'כית | ✔️ | ✔️ |
| דנית | ✔️ | ✔️ |
| הולנדית | ✔️ | ✔️ |
| דיולה | ✔️ | — |
| דזונקה | ✔️ | — |
| ערבית מצרית | ✔️ | ✔️ |
| אנגלית | ✔️ | ✔️ |
| אסטונית | ✔️ | ✔️ |
| פיליפינית | ✔️ | ✔️ |
| פינית | ✔️ | — |
| צרפתית | ✔️ | ✔️ |
| גליציאנית | ✔️ | ✔️ |
| גאנדה | ✔️ | ✔️ |
| גאורגית | ✔️ | ✔️ |
| גרמנית | ✔️ | ✔️ |
| יוונית | ✔️ | ✔️ |
| גוארני | ✔️ | — |
| גוג'ראטי | ✔️ | ✔️ |
| קריאולית האיטית | ✔️ | ✔️ |
| מונגולית חלחה | ✔️ | ✔️ |
| האוסה | ✔️ | ✔️ |
| עברית | ✔️ | ✔️ |
| הינדי | ✔️ | ✔️ |
| הונגרית | ✔️ | ✔️ |
| איסלנדית | ✔️ | ✔️ |
| איגבו | ✔️ | — |
| אילוקו | ✔️ | ✔️ |
| אינדונזית | ✔️ | ✔️ |
| פרסית איראנית | ✔️ | ✔️ |
| איטלקית | ✔️ | ✔️ |
| יפנית | ✔️ | ✔️ |
| ג'אווה | ✔️ | ✔️ |
| קביל | ✔️ | — |
| קאמבה | ✔️ | ✔️ |
| קנאדה | ✔️ | ✔️ |
| קשמירית (כתב ערבי) | ✔️ | ✔️ |
| קשמירית (כתב דוונאגרי) | ✔️ | ✔️ |
| קזחית | ✔️ | ✔️ |
| חמרית | ✔️ | ✔️ |
| קיקויו | ✔️ | ✔️ |
| קינירואנדה | ✔️ | ✔️ |
| קונגו | ✔️ | ✔️ |
| קוריאנית | ✔️ | ✔️ |
| קירגיזית | ✔️ | ✔️ |
| לאו | ✔️ | ✔️ |
| לטגאלית | ✔️ | — |
| לינגלה | ✔️ | ✔️ |
| ליטאית | ✔️ | — |
| לוקסמבורגית | ✔️ | — |
| מקדונית | ✔️ | ✔️ |
| מגאהי | ✔️ | ✔️ |
| מאיטילית | ✔️ | ✔️ |
| מליאלאם | ✔️ | ✔️ |
| מלטית | ✔️ | ✔️ |
| מניפורית | ✔️ | ✔️ |
| מראטהית | ✔️ | ✔️ |
| מיננגקבאו (כתב ערבי) | ✔️ | ✔️ |
| מיננגקבאו (כתב לטיני) | ✔️ | — |
| מיזו | ✔️ | ✔️ |
| נפאלית (שפה ספציפית) | ✔️ | ✔️ |
| פולפולדה ניגרית | ✔️ | ✔️ |
| צפון אזרית | ✔️ | ✔️ |
| סוטו צפונית | ✔️ | ✔️ |
| אוזבקית צפונית | ✔️ | ✔️ |
| נורבגית ספרותית | ✔️ | ✔️ |
| נורווגית (Nynorsk) | ✔️ | ✔️ |
| ניאנג'ה | ✔️ | ✔️ |
| אוקסיטנית | ✔️ | — |
| אורייה (שפה נפרדת) | ✔️ | ✔️ |
| פנגסינאן | ✔️ | — |
| פרסית (אפגניסטן) | ✔️ | ✔️ |
| פולנית | ✔️ | ✔️ |
| פורטוגזית | ✔️ | ✔️ |
| פנג'אבי | ✔️ | ✔️ |
| רומנית | ✔️ | ✔️ |
| רוסית | ✔️ | ✔️ |
| סנטלי | ✔️ | ✔️ |
| סרבית | ✔️ | ✔️ |
| סינדהית | ✔️ | — |
| סינהאלה | ✔️ | ✔️ |
| סלובקית | ✔️ | ✔️ |
| סלובנית | ✔️ | — |
| סומלית | ✔️ | — |
| אזרית דרומית | ✔️ | ✔️ |
| פאשטו דרומית | ✔️ | ✔️ |
| ססוטו | ✔️ | — |
| ספרדית | ✔️ | ✔️ |
| ערבית רגילה (כתב ערבי) | ✔️ | ✔️ |
| ערבית רגילה (תסריט Latn) | ✔️ | ✔️ |
| לטבית רגילה | ✔️ | ✔️ |
| מלאית תקנית | ✔️ | ✔️ |
| סוואהילי (שפה נפרדת) | ✔️ | — |
| סוואטי | ✔️ | — |
| שוודית | ✔️ | — |
| טג'יקית | ✔️ | — |
| טמילית | ✔️ | ✔️ |
| טלוגו | ✔️ | ✔️ |
| תאית | ✔️ | — |
| תיגרינית | ✔️ | — |
| אלבנית טוסק | ✔️ | — |
| טורקית | ✔️ | ✔️ |
| אויגור | ✔️ | — |
| וייטנאמית | ✔️ | ✔️ |
מודלים נתמכים
| מודל | דובר יחיד | מערכת רמקולים | עיצוב קולי | רפליקציה של קולות |
|---|---|---|---|---|
Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) |
✔️ | ✔️ | ✔️ | ✔️ |
Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) |
✔️ | ✔️ | ✔️ | ✔️ |
| תצוגה מקדימה של Gemini 3.1 Flash TTS | ✔️ | ✔️ | — | — |
| Gemini 2.5 Pro Preview TTS | ✔️ | ✔️ | — | — |
מתי כדאי להשתמש בכל מודל
שני מודלי ה-TTS של Gemini 3.8 חולקים את אותה סכימת API ואת אותו פורמט הנחיות, כך שאפשר לעבור ביניהם באמצעות שינוי של פרמטר אחד:
- משתמשים ב-Gemini 3.8 Flash TTS
(
gemini-3.8-flash-tts) כשחשובים לכם במיוחד איכות אקוסטית מקסימלית, משחק ניואנסי ושליטה בהבעה. הוא אידיאלי לעבודות יצירתיות ברמה של אולפן, לדיאלוגים מורכבים עם כמה דוברים, לתגי קול חזקים, להגייה מסובכת, לניבים אזוריים או של מיעוטים ולקריינות ארוכות שדורשות יציבות מושלמת של הקול ושל טון החדר. - שימוש ב-Gemini 3.8 Flash-Lite TTS
(
gemini-3.8-flash-lite-tts) כפתרון מהיר וחסכוני במקוםgemini-3.1-flash-tts-preview. הוא מותאם להפקה בכמות גדולה, לשיחות עם נציגים קוליים, לתכונות של קריאה בקול רם, לרפליקציה של קולות מהימנה ולדיבור יומיומי בשפה אחת בשפות מרכזיות.
מדריך להעברת נתונים (מיגרציה)
אם אתם מבצעים מיגרציה מגרסה gemini-3.1-flash-tts-preview או מגרסאות קודמות של מודלים של Gemini TTS אל Gemini 3.8 TTS:
- העברת הוראות ברמת הפנייה אל
speech_metadata: ב-Gemini 3.8 TTS, טקסט הקלט נחשב לתמליל מילולי בלבד. העברת הוראות לגבי אופן המסירה (style—כמו"whispering","out of breath"או"speaking slowly") ותוויות לזיהוי דוברים (speaker) להערותspeech_metadataמובנות, במקום להטמיע הוראות במהלכים בטקסט התמליל. - משתמשים בתגי שורה עם סוגריים זוויתיים רק לאירועים קוליים שמתרחשים בנקודת זמן מסוימת: משתמשים בסוגריים זוויתיים (כמו
<laugh>,<sigh>,<cough>,<breath>או<short pause>) כדי לציין בתוך התמליל קולות רגעיים שאינם דיבור והפסקות. לא משתמשים בתגי אפקטים קוליים (כמו מחיאות כפיים או חבטות) ומציינים סגנונות דיבור בתוךspeech_metadata.style. - צריך לציין
speakerבכל תור בבקשות עם כמה דוברים: בכל תור בבקשה עם כמה דוברים צריך לציין במפורש אתspeakerבתוךspeech_metadataשמתאים לאחד מהדוברים שהוגדרו. - עיצוב פרסונות מראש באמצעות עיצוב קול: מחליפים בלוקים של
"Audio Profile"או"Director's Notes"עם כמה פסקאות בקול מותאם אישית שנוצר בעיצוב קול, ואז מעבירים את מזההvoice_...הזה דרך בקשות ה-TTS עם מחרוזותstyleמינימליות או ריקות. - הסבר על פלט WAV (
audio/wav) שמוגדר כברירת מחדל בבקשות unary: בניגוד למודלים של TTS מגרסהgemini-3.1-flash-tts-previewומגרסאות קודמות (שבהם הוחזר PCM גולמיaudio/l16ללא כותרת כברירת מחדל), במודל Gemini 3.8 TTS מוחזר אודיו בפורמט WAV (audio/wav) עם כותרת RIFF רגילה כברירת מחדל לבקשות unary.- אם הקוד שלכם עטף בעבר בייטים של PCM גולמיים בכותרת WAV (לדוגמה, באמצעות מודול
waveשל Python אוffmpeg), צריך להסיר את העטיפה הידנית של הכותרת ולכתוב את הבייטים שהוחזרו ישירות לקובץ.wav. - אם צינור עיבוד הנתונים דורש אודיו PCM, mu-law או A-law גולמי ללא כותרת, צריך להגדיר את
response_formatל-"audio/l16","audio/mulaw"או"audio/alaw". פורמטים של פלט אודיו
- אם הקוד שלכם עטף בעבר בייטים של PCM גולמיים בכותרת WAV (לדוגמה, באמצעות מודול
מדריך לכתיבת פרומפטים
מודלים של Gemini 3.8 TTS מתייחסים לטקסט הקלט אך ורק כתמליל מילולי.
בניגוד למודלים קודמים של תצוגה מקדימה שבהם הוראות הבמה היו מוטמעות בטקסט פשוט, ב-Gemini 3.8 TTS ההוראות ברמת התור (speech_metadata) מופרדות מתגי קול מוטבעים בנקודת זמן מסוימת.
שדה סגנון לעומת תגים מוטבעים
כדאי לפצל את הוראות הביצוע לפי היקף:
- העברה ברמת הפנייה (
speech_metadata.style): מכניסים מאפייני העברה מתמשכת – כמו רגש, פרוזודיה, קצב כללי או סגנון העברה (למשל"whispering","out of breath","muttering"או"sarcastic") – לשדהstyleשלspeech_metadata. כדי ליצור דמות יציבה וביצועים עקביים לאורך התורות, צריך לעצב את האישיות מראש בעיצוב הקול ולהשתמש ב-styleרק לשינויים אופציונליים ברמת התור. - אירועים בנקודת זמן מסוימת (תגים מוטבעים): כדי להוסיף לטקסט תמלול פרצי קול רגעיים שאינם דיבור, נשימות או הפסקות, משתמשים בסוגריים זוויתיים (
<cough>,<breath>,<sigh>,<short pause>). כדי לקבל את איכות האודיו הכי גבוהה, משתמשים בסוגריים זוויתיים (<...>) ומוסיפים רק קולות אנושיים ולא אפקטים קוליים שאינם קולות.
| היקף | איפה למקם | דוגמאות |
|---|---|---|
| ברמת הפנייה (נמשך לאורך הפנייה) | speech_metadata.style |
"angry tone", "speaking rapidly", "out of breath", "whispers", "sarcastic" |
| נקודת זמן (מתרחש במילה ספציפית) | בתוך הטקסט ב-text (<...>) |
"<cough> Thank you all for coming tonight! <throat-clearing> As I was saying..." |
קצב ופסק זמן
אתם יכולים לשלוט בקצב ובשקט בשלוש רמות של פירוט:
- סימני פיסוק ושלוש נקודות: השתמשו בפסיקים, במקפים (
--) ובשלוש נקודות (...) כדי ליצור היסוס טבעי בשיחה. - תגי השהיה בתוך השורה: מוסיפים את התגים
<short pause>או<long pause>בנקודות המדויקות בתסריט שבהן הדובר צריך להשהות את הדיבור:text Hold on, let me think... <short pause> Alright, I've got it. - קצב ברמת התור: מגדירים את הערך
"style": "speaking rapidly"או"style": "speaking slowly"ב-speech_metadataכדי לשלוט בקצב הדיבור לאורך כל התור.
פרוזודיה וגובה הצליל
משתמשים בתג speech_metadata.style כדי לשלוט בהטעמה, בגובה הטון ובאינטונציה לאורך תור (לדוגמה, "style": "high pitch, cheerful and excited inflection" או "style": "monotone and flat"). אם יש שינוי ברגש או בהטעמה באמצע הדיאלוג, צריך לפצל את התסריט לתורות נפרדות עם ערכי style שונים לכל תור.
הדגשה
כדי להדגיש מילות מפתח ספציפיות בטקסט התמליל, אפשר להשתמש באותיות רישיות בשילוב עם סימני פיסוק ותגי דיבור מוטבעים:
This is a VERY important point!
It was a VERY long day <sigh> ... nobody listens anymore.
פרצי קול וצלילים שאינם דיבור
מציבים קולות אנושיים שהם לא דיבור בתוך סוגריים זוויתיים (<...>) בנקודה המדויקת שבה צריך להשמיע את הצליל. תגי קול מומלצים:
<argh> |
<breath> |
<heavy breath> |
<exhales> |
<cackle> |
<cheer> |
<chuckle> / <chuckles> |
<cough> |
<cry> |
<gasp> |
<giggle> |
<groan> |
<growl> |
<grunt> |
<grr> |
<hiss> |
<laugh> / <laughter> |
<moan> |
<pant> |
<pff> / <phew> |
<scream> |
<shout> |
<shriek> |
<sigh> / <sighs> |
<sneeze> |
<snicker> |
<snort> |
<sob> |
<throat-clearing> |
<tsk> |
<whimper> |
<whispers> / <whispering> |
<yawn> |
<short pause> |
<long pause> |
ערוצים אחוריים ודיבור חופף
בדיאלוג עם כמה דוברים, כדי ליצור ערוצים משניים טבעיים או דיבור חופף בלי ליצור תור נפרד לכל תגובה, אפשר להוסיף את התגובות של המאזין בין תווי צינור (|reaction|) בתוך תור הדיבור של הדובר.
- החלפת מסרים קצרה בערוץ האחורי: תגובות קצרות של המאזינים (
|oh hmm|,|oh really?|,|absolutely|) במהלך התור של הדובר הפעיל:- תור 1 (דובר א'):
"So the launch is Thursday |oh hmm| Are we actually ready?" - תור 2 (דובר ב'):
"Ready enough |oh really?| The last blocker cleared this morning." - תור 3 (דובר א'):
"Then let's ship it |absolutely| and watch the dashboards."
- תור 1 (דובר א'):
- חפיפה ודיבור לסירוגין: כדי לדמות דיבור בו-זמני או לסירוגין בין שני דוברים, משתמשים בכמה מקטעים עם קו אנכי (האפשרות הזו מתאימה במיוחד ל-
gemini-3.8-flash-tts):- ספירה לאחור/פזמון בו-זמנית:
"Let's surprise him on three |ok| ready?"ואחריו"one. two. three. |happy| happy |birthday| birthday!" - חפיפה מלאה בין הדוברים:
"Hello |oh| there |my| it |goodness| must |gracious| be |would| almost |you| time |look| for |at that| dinner"
- ספירה לאחור/פזמון בו-זמנית:
עקביות בין יצירות ומה כדאי להימנע ממנו
כדי לשמור על יציבות הזהות הקולית לאורך השיחה, חשוב להקפיד על ההנחיות הבאות:
- כדאי לעצב את פרסונות הקול מראש בעיצוב הקול במקום להשתמש בבלוקים ארוכים של סגנון:
פסקה ארוכה
"Audio Profile"ורשימה עם כמה תבליטים"Director's Notes"שהועברו ממודלים קודמים הם הגורם הכי נפוץ לשינוי בקול. אפשר להשתמש באותה אינטואיציה יצירתית מראש בעיצוב קול כדי ליצור דמותvoice_...מותאמת אישית קבועה, ואז להשתמש במזהה הקול הזה בקריאות ל-TTS. - הסתמכות על נקודת הייחוס הקולית ליציבות (השמטת מטא-הוראות):
מודלים של Gemini 3.8 TTS מאומנים להסתמך קודם על נקודת הייחוס הקולית.
אל תכללו הוראות שאומרות למודל לשמור על יציבות הקול (כמו
"do not switch speaker identity"או"maintain identical timbre") – טקסט נוסף בהנחיה מגדיל את הסחף. כדאי להשמיט הוראות סגנון מיותרות ולאפשר למודל להשתנות באופן טבעי סביב הנקודה היציבה שמופיעה ברפרנס הקולי. - אל תנסו לשנות מאפיינים קבועים של הדובר ב-
style: אל תציינו ב-speech_metadata.styleשינויים בגיל, במגדר, בשמות או במבטא קבוע. במקום זאת, אפשר לבחור קול אזורי מתוך ספריית הקולות המורחבת או ליצור קול באמצעות עיצוב קול.
תהליך עבודה מומלץ
- יוצרים את הדמות פעם אחת: יוצרים את הדמות בעיצוב קול או בוחרים קול אזורי מתוך ספריית הקולות המורחבת שתואם לשפת היעד ולדמות.
- כתיבת תמלילים של דיבור טבעי עם שיבושי דיבור: כדי שהתמליל יישמע טבעי ככל האפשר, כדאי לכתוב את
textכמו תמליל של דיבור אמיתי – כולל שיבושי דיבור והיסוסים שקורים בשיחה (לדוגמה,"Oh uh yeah I think... hm, so that's interesting"). - קודם בודקים TTS רגיל: מסנתזים את התמליל עם שדה
styleריק – ברוב הבקשות לא צריך לתת הוראותstyleבכלל. - הוספת הנחיות קצרות
styleרק לשינויים קלים: מוסיפים מחרוזתstyleקצרה (למשל"casual, friendly"או"muttering, then reassuring") רק לתפניות שבהן צריך לבצע התאמה ספציפית של התוצאה, ומשתמשים באותה מחרוזת קצרה בדיוק בתפניות שונות כשרוצים לקבל תוצאה עקבית.
סוכנים קוליים ודיאלוגים רב-שלביים
כשמפתחים סוכני קול לשיחות בזמן אמת או אפליקציות רב-שלביות:
- להתקשר שיחת TTS אחת בכל תור כשהנתונים מגיעים בחלקים ממודל שפה גדול (LLM).
- מאפשרים ל-
voiceשהוגדר (מוכן מראש, מתוכנןvoice_...או משוכפלvoice_.../voicekey_...) לשמור את זהות הדובר לאורך כל התורות – לא לשלוח מחדש תיאור ארוך של דמות בכל תור. - משאירים את השדה
styleלכל תור ריק, או שולחים מחרוזת קצרה וקבועה (למשל"casual, friendly") לכל השיחה. - לפצל תשובות ארוכות של נציגים לתשובות קצרות יותר, במקום להשתמש בהנחיות סגנון חזקות יותר.
מגבלות
- מודלים של TTS מקבלים קלט של טקסט בלבד ומפיקים פלט של אודיו בלבד.
- יצירה של כמה דוברים בבקשה אחת (
speech_config.speakers) תומכת בעד 2 דוברים באמצעות קולות מוכנים מראש. כדי לשלב קולות מותאמים אישית (voice_...) או קולות משוכפלים (voice_.../voicekey_...) בדיאלוג של כמה דמויות, צריך לבצע סינתזה של כל תור דיבור בנפרד. בגלל שבקשות unary מחזירותaudio/wavעם כותרת RIFF של 44 בייט כברירת מחדל, צריך לבקש PCM גולמי ({"type": "audio", "mime_type": "audio/l16"}) או להסיר את כותרת ה-WAV מכל תור לפני שמשלבים את פריימי האודיו של PCM ב-24kHz. - מכסות אחסון וערכי TTL של קולות בהתאמה אישית:
- קולות עם מצב (
store=True, בהנחיה או בשכפול): עד 200 קולות לכל פרויקט עם אורך חיים של שנה. - מפתחות קוליים ללא שמירת מצב (
store=False,voicekey_...): אורך חיים (TTL) של 7 ימים (time-to-live).
- קולות עם מצב (
- בקטע שפות נתמכות מפורטות השפות הנתמכות.
המאמרים הבאים
- בעזרת עיצוב קול, אתם יכולים ליצור דמויות קוליות בהתאמה אישית משפה טבעית.
- לשכפל קול של דובר קיים ברפליקציה של קולות.
- אפשר להשוות בין המפרטים של המודלים בדפים של Gemini 3.8 Flash TTS ושל Gemini 3.8 Flash-Lite TTS.
- אתם יכולים לנסות את Live API כדי ליהנות מאודיו אינטראקטיבי דו-כיווני.