PL ▾

API tekstu bez cenzury dla potoków głosowych

uncensoredhttps://api.xtts.cc/v1

Demo API TTS: Przykłady żądań i odpowiedzi w czasie rzeczywistym

To demo pokazuje rzeczywiste żądania, które możesz uruchomić szybko, oraz format odpowiedzi, który jest zwracany. API jest modelem tekstowym, więc wyjściem jest tekst do odczytu, JSON i wywoływanie funkcji, które oddzielny silnik syntez mowy może następnie przeczytać na głos.

Zaktualizowano

Izometryczna ilustracja terminala emitującego tekst, dane i strumienie wywoływania funkcji

Zanim uruchomisz cokolwiek

Uczciwe ostrzeżenie dla każdego, kto oczekuje wciśnięcia play i usłyszenia głosu: to demo tts api nie produkuje dźwięku. Usługa zwraca tekst z jednego modelu, uncensored, przez POST /v1/chat/completions. Istnieje drugi endpoint, GET /v1/models, do listowania tego, co jest dostępne. Nic nie zwraca audio, obrazów ani embeddingów.

Dlaczego demo? Ponieważ wiele projektów syntezy mowy potrzebuje dokładnie tego elementu: pisarza scenariusza, czyszczenia tekstu, podziału decydującego, kto co mówi. Poniższe przykłady pokazują te zadania, a format wyjściowy to to, co Twój kod syntezy mowy będzie parsować.

Potrzebujesz klucza. Zarejestruj się na stronie klucza API z Google lub z e-mailem i hasłem, a następnie aktywuj kredyt $0.50 jednym kliknięciem. Jest ważny przez 7 dni i nie wymaga karty. Wyeksportuj klucz, aby poniższe polecenia mogły go odczytać:

export XTTS_API_KEY="paste-your-key-here"
curl -s https://api.xtts.cc/v1/models -H "Authorization: Bearer $XTTS_API_KEY" | grep uncensored

Jeśli to wywołanie zwróci listę JSON, która zawiera uncensored, klucz działa i możesz kontynuować.

Demo 1: zwykłe żądanie

Najmniejsze użyteczne wywołanie prosi o krótki akapit w stylu mówionym:

curl -s https://api.xtts.cc/v1/chat/completions \
  -H "Authorization: Bearer $XTTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "uncensored",
    "messages": [
      {"role": "system", "content": "You write short lines for a voice actor. No stage directions."},
      {"role": "user", "content": "Welcome listeners to a show about lighthouses. Two sentences."}
    ],
    "temperature": 0.7,
    "max_tokens": 120
  }'

Odpowiedź wygląda jak poniższy przykład. Tekst wewnątrz content będzie się różnić przy każdym uruchomieniu, więc traktuj go jako ilustrację struktury, a nie jako nagrane wyjście.

{
  "id": "chatcmpl-example",
  "object": "chat.completion",
  "model": "uncensored",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Welcome to the show. Tonight we climb the stairs of the world's loneliest lighthouses."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 38, "completion_tokens": 21, "total_tokens": 59}
}

Twój kod syntezy mowy odczytuje choices[0].message.content. finish_reason mówi Ci, dlaczego generowanie się zakończyło: stop dla naturalnego końca, length jeśli max_tokens skrócił go. Jeśli pominiesz max_tokens, wynik może użyć tego, co pozostanie z okna kontekstu 100 000 tokenów, które obejmuje prompt i wynik razem.

Co mówią nagłówki

Dodaj -i do polecenia curl i zobaczysz X-Request-Id, X-Balance-USD, X-RateLimit-Limit-Requests i X-RateLimit-Limit-Concurrency. Nagłówek salda jest przydatny w demo, ponieważ możesz obserwować, jak spada o niewielką kwotę po każdym wywołaniu. Dla tego żądania użycie powyżej wynosi 38 x $0.15 / 1 000 000 plus 21 x $0.50 / 1 000 000, co daje $0.0000057 plus $0.0000105, około $0.0000162.

Demo 2: strumieniowanie scenariusza

Dla audio rzadko chcesz czekać na pełny tekst. Dodaj "stream": true, a API wysyła zdarzenia wysyłane przez serwer, po małym kawałku tekstu na raz. Poniższy przykład w Node.js drukuje tekst w miarę jego przybywania, co jest momentem, w którym mógłbyś podać kolejkę zdań.

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.xtts.cc/v1",
  apiKey: process.env.XTTS_API_KEY,
});

const stream = await client.chat.completions.create({
  model: "uncensored",
  stream: true,
  messages: [
    { role: "user", content: "Read a four-line weather report for a coastal town." },
  ],
});

for await (const chunk of stream) {
  const piece = chunk.choices[0]?.delta?.content ?? "";
  process.stdout.write(piece);
}
process.stdout.write("\n");

Uruchom go jako moduł ES (zapisz jako demo.mjs i uruchom node demo.mjs po npm install openai). Przez sieć każde zdarzenie to linia zaczynająca się od data:, po której następuje JSON, a strumień zamyka się końcowym znacznikiem. Zużycie tokenów jest raportowane na końcu strumienia. Jedna kwestia ma znaczenie dla planowania: zapytanie strumieniowe utrzymuje swój slot współbieżności do końca strumienia, więc wolny konsument może zablokować Twoje kolejne zapytanie.

Demo 3: wywoływanie funkcji jako router mowy

Wywoływanie funkcji pozwala modelowi zwrócić uporządkowaną instrukcję zamiast prozy. W projekcie głosowym jest to czysty sposób na wybór stylu dostawy dla każdej linii. Definiujesz funkcję o nazwie say, a model wypełnia jej argumenty. Twój kod decyduje następnie, co z nimi zrobić. Model nie wykonuje niczego sam.

import json
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.xtts.cc/v1", api_key=os.environ["XTTS_API_KEY"])

tools = [{
    "type": "function",
    "function": {
        "name": "say",
        "description": "Queue one line for the voice engine.",
        "parameters": {
            "type": "object",
            "properties": {
                "text": {"type": "string"},
                "style": {"type": "string", "enum": ["calm", "urgent", "whisper"]},
            },
            "required": ["text", "style"],
        },
    },
}]

messages = [
    {"role": "system", "content": "Always answer by calling say, once per line."},
    {"role": "user", "content": "The alarm sounds. The guard tells everyone to leave."},
]

r = client.chat.completions.create(
    model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)

msg = r.choices[0].message
for call in msg.tool_calls or []:
    args = json.loads(call.function.arguments)
    print(args["style"], "->", args["text"])

Argumenty przybywają jako ciąg JSON, więc sparsuj je i zwaliduj przed użyciem. Modele mogą wyprodukować styl spoza Twojego enum lub pominąć pole, a niezweryfikowana wartość nigdy nie powinna trafić do Twojego silnika. Jeśli chcesz, aby rozmowa kontynuowała się, dołącz wiadomość asystenta i odpowiedź z role: "tool" i pasującym tool_call_id, a następnie wywołaj API ponownie.

Podczas strumieniowania wywołania narzędzi przychodzą w kawałkach. Nazwa funkcji przychodzi pierwsza, a ciąg argumentów buduje się przez fragmenty, więc zbieraj fragmenty według indeksu i sparsuj raz, gdy strumień się zakończy.

Demo 4: tryb JSON dla listy obsady

Jeśli wolisz pominąć definicje funkcji, tryb JSON daje poprawny JSON w treści wiadomości. Jest to dobre dopasowanie do zamiany surowej sceny na linie dla każdego mówcy.

curl -s https://api.xtts.cc/v1/chat/completions \
  -H "Authorization: Bearer $XTTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "uncensored",
    "response_format": {"type": "json_object"},
    "temperature": 0.2,
    "messages": [
      {"role": "system", "content": "Return JSON: {\"lines\": [{\"speaker\": string, \"text\": string}]}"},
      {"role": "user", "content": "Ana asks Ben to hold the ladder. Ben agrees reluctantly."}
    ]
  }'

Tryb JSON gwarantuje, że wyjście zostanie sparsowane, a nie że pasuje do Twojego kształtu. Opisz kształt w prompcie, jak wyżej, i sprawdź klucze w kodzie. Niska temperatura utrzymuje strukturę stabilną.

Demo 5: długi dokument w jednym żądaniu

Okno kontekstu wynosi 100 000 tokenów, dzielone przez prompt i uzupełnienie. To wystarczy, aby wysłać długą transkrypcję lub całą krótką opowieść i poprosić o wersję napisaną na uszy. Treść żądania może mieć do 8 MB, więc rozmiar rzadko jest limitem; limitem jest liczba tokenów.

Oto koszt ciężkiego wywołania. Wyślij 80 000 tokenów i otrzymaj 2 000. Dane wejściowe: 80 000 x $0,15 / 1 000 000 = $0,012. Dane wyjściowe: 2 000 x $0,50 / 1 000 000 = $0,001. Łącznie $0,013, więc kredyt próbny $0,50 pokryłby około 38 takich wywołań. Długie dane wejściowe są tanie w porównaniu z długimi danymi wyjściowymi, dlatego podsumowania i przeróbki dużych tekstów są przystępne, podczas gdy wygenerowanie całej powieści na raz nie jest.

Praktyczna wskazówka dla długich inputów: umieść instrukcje na początku i powtórz kluczową zasadę na końcu. Modele najlepiej podążają za najnowszą instrukcją, a jednowierszowe przypomnienie po 80 000 tokenach tekstu źródłowego kosztuje prawie nic.

Odczytywanie błędów w demo

Zepsuj coś celowo raz, aby później to rozpoznać. Wyślij żądanie z błędnym kluczem i otrzymasz błąd uwierzytelniania zamiast odpowiedzi. Wyślij dziesięć żądań w tym samym momencie z kluczem próbnym i niektóre zwrócą się jako HTTP 429.

429 ma trzy przyczyny, a kod błędu je rozróżnia:

  • rate_limited oznacza zbyt wiele żądań w ciągu jednej minuty: 60 na kluczu próbnym, 300 na pełnym kluczu.
  • concurrency oznacza zbyt wiele żądań w locie naraz: 2 na kluczu próbnym, 8 na pełnym kluczu.
  • 429 z nagłówkiem Retry-After: 5 oznacza, że usługa była chwilowo przeciążona. Poczekaj pięć sekund i wyślij ponownie.

Nieudane lub odrzucone żądania nie są rozliczane, więc błędy nic nie kosztują. Aby zobaczyć limity, które ma Twój klucz, przeczytaj X-RateLimit-Limit-Requests i X-RateLimit-Limit-Concurrency w dowolnej normalnej odpowiedzi. Mała pętla ponawiania, która śpi przez wartość Retry-After, lub pięć sekund, gdy brakuje, to wszystko, czego potrzebuje skrypt demo.

Co spróbować dalej

Gdy te cztery wywołania zadziałają, masz elementy potoku skryptowego. Zawiń zwykłe zapytanie w funkcję, uruchom pętlę strumieniową w kolejce i podłącz kolejkę do silnika syntezy mowy, którego wybierzesz. Silniki różnią się ceną, licencją i jakością, więc przeczytaj ich aktualne warunki. Ta usługa nie dostarcza jednego i nie mówi nic o nich.

Koszty pozostają małe, podczas gdy eksperymentujesz. Przy $0.15 za milion tokenów wejściowych i $0.50 za milion tokenów wyjściowych, typowe wywołanie demo kosztuje ułamek centa, a kredyt $0.50 pokrywa setki z nich. Zobacz stronę cenową dla doładowań od $20 do $500 z bonusami od 5% do 15%, płatne kryptowalutami. dokumentacja obejmuje pełną listę parametrów, limity zapytań (8 równoległych i 300 na minutę na pełnym kluczu) i kody błędów. Prompty nie są używane do trenowania.

Rozsądna kolejność na pierwsze popołudnie: uruchom zwykłe zapytanie, aż ton będzie odpowiedni, przełącz się na strumieniowanie i drukuj zdania po ich ukończeniu, a następnie dodaj albo wywoływanie funkcji, albo tryb JSON, w zależności od tego, jak Twój kod mowy chce otrzymywać dane. Przechowuj każdy prompt w pliku pod kontrolą wersji. Kiedy linia brzmi źle w końcowym audio, możesz ją wtedy prześledzić do dokładnej instrukcji, która ją wygenerowała, i zmienić jedną rzecz na raz.

Pytania i odpowiedzi

Czy mogę posłuchać przykładowego głosu w tym demo?

Nie. API zwraca tylko tekst, JSON i wywoływania funkcji. Dostarczasz osobny silnik syntez mowy, który zamieni tekst na audio.

Jaki identyfikator modelu wysłać?

Wyślij uncensored jako wartość modelu, z bazowym URL https://api.xtts.cc/v1 i swoim kluczem w nagłówku Authorization: Bearer.

Czy demo działają na kluczu próbnym?

Tak. Klucz próbny pozwala na 2 równoległe żądania i 60 na minutę, co wystarczy na te przykłady. Uruchamiaj je po jednym.

Dlaczego otrzymuję odpowiedź 429?

Przekroczyłeś limit zapytań na minutę (rate_limited), miałeś zbyt wiele równoległych zapytań lub usługa była chwilowo przeciążona. Poczekaj na nagłówek Retry-After, jeśli jest podany, a następnie ponów zapytanie.

Twój klucz jest o jeden krok stąd

Utwórz konto, skopiuj klucz, zmień bazowy URL. To cała konfiguracja.