إنشاء محتوى باستخدام تكنولوجيا "تحويل النص إلى كلام"

يمكن لواجهة Gemini API تحويل النص المدخل إلى صوت أحادي أو متعدّد المتحدثين باستخدام إمكانات تحويل النص إلى كلام (TTS) في Gemini. يمكن التحكّم في عملية إنشاء المحتوى من نص إلى كلام، ما يعني أنّه يمكنك الجمع بين البيانات الوصفية المنظَّمة الخاصة بالانعطاف (speech_metadata) وعلامات الصوت المضمّنة لتحديد الأسلوب واللهجة والسرعة والنبرة في الصوت.

تختلف إمكانية تحويل النص إلى كلام عن إمكانية إنشاء الكلام المقدَّمة من خلال Live API، وهي مصمَّمة لتوفير تجربة تفاعلية للمحتوى الصوتي غير المنظَّم، وللمدخلات والمخرجات المتعدّدة الوسائط. في حين تتفوّق واجهة Live API في سياقات المحادثات الديناميكية، تم تصميم ميزة تحويل النص إلى كلام من خلال 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 لتحويل النص إلى كلام مدرَج في قسم النماذج المتوافقة. للحصول على أفضل النتائج، راجِع مقالة حالات استخدام كل نموذج لاختيار النموذج الأنسب لعبء العمل.

ننصحك بتجربة نماذج تحويل النص إلى كلام من Gemini في AI Studio قبل البدء في إنشاء التطبيق.

تحويل النص إلى كلام بصوت شخص واحد

لتحويل النص إلى محتوى صوتي بصوت متحدث واحد باستخدام نماذج تحويل النص إلى كلام من Gemini 3.8، مرِّر النص الحرفي في input، وأرفِق التنسيق على مستوى الجملة باستخدام التعليق التوضيحي speech_metadata، واضبط صوتك في generation_config.speech_config. يمكنك اختيار صوت من خيارات الصوت المضمّنة أو مكتبة الأصوات الموسّعة (GET /v1beta/voices) أو معرّف تصميم الصوت المخصّص (voice_...) أو معرّف نسخ الصوت (voice_... أو voicekey_... الاختياري بدون حالة).

يحفظ هذا المثال الصوت الناتج بتنسيق WAV التلقائي (audio/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" }
      ]
    }
  }'

يمكنك استرداد بيانات الصوت التي تم إنشاؤها باستخدام السمة interaction.output_audio، والتي تعرض آخر مقطع صوتي تم إنشاؤه. للحصول على تفاصيل حول سمات الراحة، يُرجى الاطّلاع على نظرة عامة على التفاعلات.

تحويل النص إلى كلام لعدة متحدثين

بالنسبة إلى الحوارات التي تضم عدة متحدثين، اضبط متحدثَين في 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 مع الحقل 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. على عكس الطلبات الأحادية (التي تعرض ملف WAV كاملاً مع عنوان RIFF)، تعرض طلبات البث أجزاء PCM خطية أولية 16 بت بدون عنوان (audio/l16، 24 كيلو هرتز، أحادي) تلقائيًا، وبالتالي يمكن تشغيل أجزاء الصوت أو ربطها بشكل مستمر بدون عناوين الحاويات.

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 تنسيقات صوتية تلقائية مختلفة حسب ما إذا كان الطلب أحاديًا أو متواصلاً:

  • طلبات أحادية (stream=False): تعرض هذه الطلبات ملف WAV (audio/wav) صوتيًا كاملاً مع عنوان RIFF عادي (24 كيلو هرتز، أحادي، 16 بت، PCM صغير الحجم). يمكنك حفظ وحدات البايت الصوتية التي تم فك ترميزها مباشرةً في ملف .wav بدون إضافة عنوان WAV يدويًا.
  • طلبات البث (stream=True): يتم عرض أجزاء Linear PCM الأولي بدون عناوين (audio/l16) (بتردد 24 كيلو هرتز، أحادي، 16 بت، PCM صغير الحجم) تلقائيًا، ما يتيح بث الأجزاء أو ربطها بشكل متواصل بدون عناوين حاوية في كل جزء.

لطلب ترميز صوتي أو معدّل عيّنات مختلفَين، اضبط mime_type وsample_rate الاختياري داخل response_format:

التنسيق قيمة mime_type الوصف
WAV (القيمة التلقائية الأحادية) "audio/wav" ملف WAV غير مضغوط يتضمّن عنوان RIFF (‫PCM صغير الحجم وموقّع بـ 16 بت، أحادي القناة، 24 كيلوهرتز تلقائيًا) القيمة التلقائية للطلبات الأحادية
Raw PCM (L16) (الإعداد التلقائي للبث) "audio/l16" ملف صوتي بتنسيق PCM خطي غير مضغوط وبدون رأس وبترميز 16 بت مع ترتيب وحدات البايت الأصغر أولاً (24 كيلوهرتز، أحادي). الإعداد التلقائي لطلبات البث
Mu-law "audio/mulaw" صوت بترميز G.711 mu-law ذو 8 بت (شائع الاستخدام في أنظمة الاتصالات/الاستجابة الصوتية التفاعلية (IVR) في أمريكا الشمالية واليابان)
A-law "audio/alaw" صوت بترميز G.711 A-law ذو 8 بت (شائع الاستخدام في أنظمة الاتصالات الأوروبية والدولية)

يمكنك أيضًا تحديد 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" }
      ]
    }
  }'

خيارات الصوت

يتيح الإصدار 3.8 من ميزة "تحويل النص إلى كلام" في Gemini أربع طرق لاختيار الأصوات أو إنشائها:

  1. الأصوات الجاهزة في الاستوديو: 30 صوتًا منتقىً مدرَجًا في الجدول التالي.
  2. مكتبة الأصوات الموسّعة: مئات الأصوات الإضافية بمختلف اللغات واللهجات وأنواع الشخصيات، ويمكن الوصول إليها باستخدام client.voices.list() (GET /v1beta/voices).
  3. تصميم الصوت: يمكنك إنشاء شخصية صوتية مخصّصة من وصف باللغة الطبيعية في Google AI Studio أو باستخدام POST /v1beta/voices (type="prompted"، الذي يعرض معرّفًا ثابتًا voice_... ومعاينة بتنسيق WAV sample_audio في CreateVoice وGetVoice).
  4. تقليد الصوت: تقليد صوت المتحدث من خلال محتوى صوتي مرجعي ومحتوى صوتي يتضمّن موافقة في Google AI Studio أو باستخدام POST /v1beta/voices (type="replicated"، store=True ثابت تلقائيًا أو store=False اختياري بدون حالة).

حدود الصوت المخصّص وTTL

نوع الصوت وضع التخزين الحصة / الحدّ الاحتفاظ بالمعلومات (TTL)
الأصوات التي تحتفظ بحالتها (voice_...، التي يتم إنشاؤها بناءً على طلب أو نسخها) store=True ‫200 صوت لكل مشروع (يتمّ تقسيمها بين الأصوات التي تمّ إنشاؤها من خلال المطالبات والأصوات المنسوخة) سنة واحدة
مفاتيح الصوت غير الاحتفاظ بالحالة (voicekey_...، مكرّرة) store=False تتم إدارتها من قِبل العميل 7 أيام

الأصوات المُعدّة مسبقًا

Zephyr -- ساطع Puck -- موسيقى مبهجة Charon -- مفيدة
كوريا -- شركة Fenrir -- متحمّس Leda -- شبابي
Orus -- شركة Aoede -- Breezy Callirrhoe -- مريح
Autonoe -- Bright Enceladus -- Breathy Iapetus -- Clear
Umbriel -- شخصية سهلة الجبهة -- ناعم Despina -- Smooth
Erinome -- Clear Algenib -- Gravelly Rasalgethi -- مفيدة
Laomedeia -- Upbeat Achernar -- Soft Alnilam -- الشركة
Schedar -- Even Gacrux -- ناضج Pulcherrima -- إعادة توجيه
Achird -- Friendly Zubenelgenubi -- حفلات العشاء غير الرسمية Vindemiatrix -- لطيف
Sadachbia -- مفعم بالحيوية Sadaltager -- مُلمّ سولافات -- دافئ

توسيع "مكتبة الصوت" وإضافة فلاتر إليها

بالإضافة إلى الأصوات الـ 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 أو معيار الأمم المتحدة 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"

اللغات المتاحة

ترصد نماذج تحويل النص إلى كلام لغة الإدخال تلقائيًا. يتوافق Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) مع 130 لغة، ويتوافق Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) مع 101 لغة:

اللغة Gemini 3.8 Flash TTS Gemini 3.8 Flash-Lite TTS
الأتشيهية (نص عربي) ✔️ ✔️
الأفريقانية ✔️ ✔️
الأكانية ✔️ ✔️
الأمهرية ✔️ ✔️
الأرمينية ✔️ ✔️
الأسامية ✔️ ✔️
الأوادية ✔️ ✔️
باليني ✔️ ✔️
البنغالية ✔️ ✔️
البنجرية (الخط العربي) ✔️
البنجرية (نص لاتيني) ✔️ ✔️
الباشكيرية ✔️
الباسك ✔️ ✔️
البيلاروسية ✔️ ✔️
البيمبا ✔️
البهوجبورية ✔️ ✔️
البوسنية ✔️ ✔️
بوغينيز ✔️ ✔️
البلغارية ✔️ ✔️
البورمية ✔️
الكَنْتونية ✔️ ✔️
الكتالانية ✔️ ✔️
السيبيوانية ✔️ ✔️
الكردية الوسطى ✔️ ✔️
التشاتيسغارهية ✔️ ✔️
الصينية (نص هان) ✔️ ✔️
الصينية (نص هان) ✔️ ✔️
التتارية القرمية ✔️
الكرواتية ✔️ ✔️
التشيكية ✔️ ✔️
الدانماركية ✔️ ✔️
الهولندية ✔️ ✔️
الدايلا ✔️
الدزونغا ✔️
العربية المصرية ✔️ ✔️
الإنجليزية ✔️ ✔️
الإستونية ✔️ ✔️
الفلبينية ✔️ ✔️
الفنلندية ✔️
الفرنسية ✔️ ✔️
الغليشيانية ✔️ ✔️
الجاندا ✔️ ✔️
الجورجية ✔️ ✔️
الألمانية ✔️ ✔️
اليونانية ✔️ ✔️
الجورانية ✔️
الغوجاراتية ✔️ ✔️
الكريولية الهايتية ✔️ ✔️
المنغولية الخالخية ✔️ ✔️
الهوسا ✔️ ✔️
العبرية ✔️ ✔️
الهندية ✔️ ✔️
الهنغارية ✔️ ✔️
الأيسلندية ✔️ ✔️
الإيجبو ✔️
الايلوكو ✔️ ✔️
الإندونيسية ✔️ ✔️
الفارسية الإيرانية ✔️ ✔️
الإيطالية ✔️ ✔️
اليابانية ✔️ ✔️
الجافانية ✔️ ✔️
القبائلية ✔️
الكامبا ✔️ ✔️
الكانادا ✔️ ✔️
الكشميرية (الخط العربي) ✔️ ✔️
الكشميرية (نص ديفا) ✔️ ✔️
الكازاخستانية ✔️ ✔️
الخميرية ✔️ ✔️
الكيكويو ✔️ ✔️
الكينيارواندا ✔️ ✔️
كونغو ✔️ ✔️
الكورية ✔️ ✔️
القيرغيزية ✔️ ✔️
لاو ✔️ ✔️
اللاتغالية ✔️
اللينجالا ✔️ ✔️
الليتوانية ✔️
اللكسمبورغية ✔️
المقدونية ✔️ ✔️
ماجادهي ✔️ ✔️
المايثيلية ✔️ ✔️
المالايالامية ✔️ ✔️
المالطية ✔️ ✔️
المانيبورية ✔️ ✔️
الماراثية ✔️ ✔️
المينانجكاباو (الخط العربي) ✔️ ✔️
المينانجكاباو (نص لاتيني) ✔️
ميزو ✔️ ✔️
النيبالية (لغة فردية) ✔️ ✔️
الفولانية النيجيرية ✔️ ✔️
الأذربيجانية الشمالية ✔️ ✔️
السوتو الشمالية ✔️ ✔️
الأوزبكية الشمالية ✔️ ✔️
البوكمالية النرويجية ✔️ ✔️
النرويجية الجديدة ✔️ ✔️
النيانجا ✔️ ✔️
الأوكسيتانية ✔️
الأودية (لغة فردية) ✔️ ✔️
البانغاسينية ✔️
الفارسية (أفغانستان) ✔️ ✔️
البولندية ✔️ ✔️
البرتغالية ✔️ ✔️
البنجابية ✔️ ✔️
الرومانية ✔️ ✔️
الروسية ✔️ ✔️
السنتالية ✔️ ✔️
الصربية ✔️ ✔️
السندية ✔️
السنهالية ✔️ ✔️
السلوفاكية ✔️ ✔️
السلوفينية ✔️
الصومالية ✔️
الأذربيجانية الجنوبية ✔️ ✔️
باشتو الجنوبية ✔️ ✔️
السوتو الجنوبية ✔️
الإسبانية ✔️ ✔️
العربية المعيارية (نص عربي) ✔️ ✔️
العربية الفصحى (نص لاتيني) ✔️ ✔️
اللاتفية العادية ✔️ ✔️
الملايو القياسية ✔️ ✔️
السواحيلية (لغة فردية) ✔️
السواتي ✔️
السويدية ✔️
الطاجيكية ✔️
التاميلية ✔️ ✔️
التيلوغوية ✔️ ✔️
التايلاندية ✔️
التيجرينيا ✔️
الألبانية التوسكية ✔️
الأويغورية ✔️

النماذج المتوافقة

الطراز متحدّث واحد مكبّر صوت متعدد تصميم الصوت تقليد الصوت
‫Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) ✔️ ✔️ ✔️ ✔️
Gemini 3.8 Flash-Lite لتحويل النص إلى كلام (gemini-3.8-flash-lite-tts) ✔️ ✔️ ✔️ ✔️
معاينة Gemini 3.1 Flash لتحويل النص إلى كلام ✔️ ✔️
إصدار تجريبي من Gemini 2.5 Pro لتحويل النص إلى كلام ✔️ ✔️

حالات استخدام كل نموذج

يتشارك كلا النموذجين Gemini 3.8 TTS مخطط واجهة برمجة التطبيقات وتنسيق الطلب نفسهما، ما يتيح لك التبديل بينهما من خلال تغيير مَعلمة واحدة:

  • استخدِم 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 بالإصدار gemini-3.1-flash-tts-preview أو إصدار أقدم إلى الإصدار 3.8 من تحويل النص إلى كلام في Gemini، اتّبِع الخطوات التالية:

  1. نقل التوجيهات على مستوى المنعطف إلى speech_metadata: يعامل نظام تحويل النص إلى كلام 3.8 في Gemini النص المدخل على أنّه نسخة طبق الأصل. انقل تعليمات الأداء المستمر (style، مثل "whispering" أو "out of breath" أو "speaking slowly") وتصنيفات المتحدثين (speaker) إلى تعليقات توضيحية منظَّمة speech_metadata بدلاً من تضمين تعليمات الأداء في نص المحضر.
  2. استخدام علامات مضمّنة بين قوسين زاويين فقط للأحداث الصوتية في نقطة زمنية معيّنة: يجب تضمين التعبيرات الصوتية غير الكلامية المؤقتة والفواصل في النص باستخدام قوسين زاويين (مثل <laugh> أو <sigh> أو <cough> أو <breath> أو <short pause>). تجنَّب علامات المؤثرات الصوتية (مثل التصفيق أو الضربات) وضَع أساليب الأداء في speech_metadata.style.
  3. تحديد speaker في كل دورة في الطلبات التي تتضمّن عدة متحدثين: يجب أن تتضمّن كل دورة في الطلبات التي تتضمّن عدة متحدثين speaker بشكل صريح داخل speech_metadata بما يتطابق مع أحد المتحدثين الذين تم ضبطهم.
  4. تصميم شخصيات مسبقًا باستخدام "تصميم الصوت": استبدِل الفقرات المتعددة "Audio Profile" أو كتل "Director's Notes" بصوت مخصّص تم إنشاؤه في تصميم الصوت، ثم استخدِم معرّف voice_... في طلبات تحويل النص إلى صوت مع سلاسل style فارغة أو قليلة.
  5. مراعاة إخراج WAV التلقائي (audio/wav) في الطلبات الأحادية: على عكس إصدارات gemini-3.1-flash-tts-preview السابقة من نماذج تحويل النص إلى كلام (التي كانت تعرض PCM الأولي بدون عنوان audio/l16 تلقائيًا)، يعرض الإصدار 3.8 من Gemini لتحويل النص إلى كلام صوت WAV (audio/wav) مع عنوان RIFF عادي تلقائيًا للطلبات الأحادية.
    • إذا كان الرمز البرمجي يضمّن سابقًا وحدات بايت PCM أولية في عنوان WAV (على سبيل المثال، باستخدام الوحدة wave أو ffmpeg في Python)، عليك إزالة تضمين العنوان اليدوي وكتابة وحدات البايت التي تم إرجاعها مباشرةً في ملف .wav.
    • إذا كان مسار التعلّم يتطلّب محتوًى صوتيًا بتنسيق PCM الأولي بدون رأس أو بتنسيق mu-law أو A-law، اضبط response_format بشكل صريح على "audio/l16" أو "audio/mulaw" أو "audio/alaw". اطّلِع على تنسيقات مصدر إخراج الصوت.

الدليل الإرشادي لكتابة الطلبات

تتعامل نماذج تحويل النص إلى كلام (TTS) في Gemini 3.8 مع النص المدخل على أنّه نص مطابق تمامًا. على عكس نماذج المعاينة السابقة التي كانت تتضمّن إرشادات الأداء في نص عادي، يفصل الإصدار 3.8 من Gemini لتحويل النص إلى كلام الإرشادات المستمرة على مستوى الدور (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."
  • الكلام المتداخل: استخدِم مقاطع متعددة من الشرطة العمودية لمحاكاة الكلام المتزامن أو المتداخل بين متحدثَين (تعمل هذه الميزة بشكل أفضل مع 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_... مخصّصة ومستمرة، ثم استخدِم معرّف الصوت هذا في طلبات تحويل النص إلى كلام.
  • الاعتماد على المرجع الصوتي لتحقيق الثبات (حذف التعليمات الوصفية): تم تدريب نماذج تحويل النص إلى كلام في الإصدار 3.8 من Gemini على الاعتماد على المرجع الصوتي أولاً. لا تُدرِج تعليمات تطلب من النموذج الحفاظ على ثبات الصوت (مثل "do not switch speaker identity" أو "maintain identical timbre")، لأنّ النص الإضافي في الطلب يزيد من الانحراف. تجاهل تعليمات الأسلوب غير الضرورية والسماح للنموذج بالتنوّع بشكل طبيعي حول النقطة الثابتة التي توفّرها المرجع الصوتي.
  • لا تحاول تغيير سمات المتحدث غير القابلة للتغيير في style: تجنَّب وضع العمر أو الجنس أو الأسماء أو التغييرات الدائمة في اللهجة في speech_metadata.style. بدلاً من ذلك، اختَر صوتًا إقليميًا من "مكتبة الأصوات الموسّعة" أو أنشئ صوتًا باستخدام تصميم الصوت.
  1. إنشاء الشخصية مرة واحدة: أنشئ شخصيتك في تصميم الصوت أو اختَر صوتًا من منطقة معيّنة من "مكتبة الأصوات الموسّعة" يتطابق مع لغتك المستهدفة وشخصيتك.
  2. كتابة نصوص طبيعية تتضمّن أخطاء في الكلام: للحصول على أعلى مستوى من الطبيعية، اكتب text كنص حقيقي يتضمّن أخطاء طبيعية في الكلام وتردّدًا (على سبيل المثال، "Oh uh yeah I think... hm, so that's interesting").
  3. اختبار تحويل النص إلى كلام العادي أولاً: يمكنك تركيب النص باستخدام حقل style فارغ أولاً، إذ إنّ معظم الطلبات لا تحتاج إلى أي تعليمات style على الإطلاق.
  4. إضافة طلبات قصيرة style للتعديلات فقط: أضِف سلسلة style موجزة (مثل "casual, friendly" أو "muttering, then reassuring") فقط للردود التي تحتاج إلى تعديل محدّد في طريقة العرض، وأعِد استخدام هذه السلسلة القصيرة نفسها في الردود عندما تريد الحصول على أساس ثابت.

الوكلاء الحواريون والصوتيون في المحادثات المترابطة

عند إنشاء وكلاء صوتيين حواريين في الوقت الفعلي أو تطبيقات محادثة مترابطة، يجب مراعاة ما يلي:

  • إجراء مكالمة واحدة لتحويل النص إلى كلام في كل مرة عند وصول أجزاء النص من النموذج اللغوي الكبير
  • اسمح لـ voice الذي تم إعداده (مُنشأ مسبقًا أو مصمّم voice_... أو مكرّر voice_... / voicekey_...) بنقل هوية المتحدث خلال المحادثات، ولا تعِد إرسال شخصية طويلة في كل محادثة.
  • اترك الحقل style الخاص بكلّ دور فارغًا، أو أرسِل سلسلة ثابتة قصيرة واحدة (مثل "casual, friendly") للمحادثة بأكملها.
  • قسِّم ردود الوكيل الطويلة إلى ردود أقصر بدلاً من استخدام طلبات ذات أسلوب أقوى.

القيود

  • تقبل نماذج تحويل النص إلى كلام مدخلات نصية فقط وتنتج مخرجات صوتية فقط.
  • تتيح ميزة "إنشاء محتوى متعدد المتحدثين بطلب واحد" (multiSpeakerVoiceConfig / متعدد المتحدثين speakers) استخدام ما يصل إلى متحدثَين باستخدام أصوات مُنشأة مسبقًا. لدمج أصوات مصمَّمة خصيصًا (voice_...) أو مكرَّرة (voicekey_...) في حوار يتضمّن عدة شخصيات، يجب تركيب كل مقطع صوتي على حدة ثم ربط إطارات الصوت بتنسيق PCM بتردد 24 كيلو هرتز.
  • حدود مساحة تخزين الصوت المخصّص وTTL:
    • الأصوات التي تحتفظ بحالتها (store=True، التي يتم إنشاؤها بناءً على طلب أو نسخها): يمكن استخدام 200 صوت كحد أقصى لكل مشروع مع مدة بقاء تبلغ عامًا واحدًا.
    • مفاتيح الصوت غير المرتبطة بحالة (store=False، voicekey_...): مدة البقاء (TTL) لمدة 7 أيام
  • راجِع قسم اللغات المتاحة لمعرفة اللغات التي تغطيها هذه الميزة.

الخطوات التالية