Snížení latence syntézy řeči s využitím sady Speech SDK

Syntéza latence je pro vaše aplikace důležitá. V tomto článku představíme osvědčené postupy pro snížení latence a dosažení nejlepšího výkonu koncovým uživatelům.

Za normálních okolností změříme latenci first byte latency následujícím finish latencyzpůsobem:

Latence Popis SpeechSynthesisResult – klíč vlastnosti
latence prvního bajtu Označuje časové zpoždění mezi začátkem souhrnného úkolu a příjmem prvního bloku zvukových dat. SpeechServiceResponse_SynthesisFirstByteLatencyMs
latence dokončení Označuje časové zpoždění mezi začátkem souhrnného úkolu a příjmem celých syntetizovaných zvukových dat. SpeechServiceResponse_SynthesisFinishLatencyMs

Sada Speech SDK umístí dobu latence do kolekce Properties kolekce SpeechSynthesisResult. Následující ukázkový kód ukazuje tyto hodnoty.

var result = await synthesizer.SpeakTextAsync(text);
Console.WriteLine($"first byte latency: \t{result.Properties.GetProperty(PropertyId.SpeechServiceResponse_SynthesisFirstByteLatencyMs)} ms");
Console.WriteLine($"finish latency: \t{result.Properties.GetProperty(PropertyId.SpeechServiceResponse_SynthesisFinishLatencyMs)} ms");
// you can also get the result id, and send to us when you need help for diagnosis
var resultId = result.ResultId;
Latence Popis SpeechSynthesisResult – klíč vlastnosti
first byte latency Označuje časové zpoždění mezi spuštěním syntézy a přijetí prvního zvukového bloku. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Označuje časové zpoždění mezi zahájením syntézy a celým syntetizovaným zvukem se přijímá. SpeechServiceResponse_SynthesisFinishLatencyMs

Sada Speech SDK změřila latence a umístí je do kontejneru SpeechSynthesisResultvlastností . Pokud je chcete získat, přečtěte si následující kódy.

auto result = synthesizer->SpeakTextAsync(text).get();
auto firstByteLatency = std::stoi(result->Properties.GetProperty(PropertyId::SpeechServiceResponse_SynthesisFirstByteLatencyMs));
auto finishedLatency = std::stoi(result->Properties.GetProperty(PropertyId::SpeechServiceResponse_SynthesisFinishLatencyMs));
// you can also get the result id, and send to us when you need help for diagnosis
auto resultId = result->ResultId;
Latence Popis SpeechSynthesisResult – klíč vlastnosti
first byte latency Označuje časové zpoždění mezi spuštěním syntézy a přijetí prvního zvukového bloku. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Označuje časové zpoždění mezi zahájením syntézy a celým syntetizovaným zvukem se přijímá. SpeechServiceResponse_SynthesisFinishLatencyMs

Sada Speech SDK změřila latence a umístí je do kontejneru SpeechSynthesisResultvlastností . Pokud je chcete získat, přečtěte si následující kódy.

SpeechSynthesisResult result = synthesizer.SpeakTextAsync(text).get();
System.out.println("first byte latency: \t" + result.getProperties().getProperty(PropertyId.SpeechServiceResponse_SynthesisFirstByteLatencyMs) + " ms.");
System.out.println("finish latency: \t" + result.getProperties().getProperty(PropertyId.SpeechServiceResponse_SynthesisFinishLatencyMs) + " ms.");
// you can also get the result id, and send to us when you need help for diagnosis
String resultId = result.getResultId();
Latence Popis SpeechSynthesisResult – klíč vlastnosti
first byte latency Označuje časové zpoždění mezi spuštěním syntézy a přijetí prvního zvukového bloku. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Označuje časové zpoždění mezi zahájením syntézy a celým syntetizovaným zvukem se přijímá. SpeechServiceResponse_SynthesisFinishLatencyMs

Sada Speech SDK změřila latence a umístí je do kontejneru SpeechSynthesisResultvlastností . Pokud je chcete získat, přečtěte si následující kódy.

result = synthesizer.speak_text_async(text).get()
first_byte_latency = int(result.properties.get_property(speechsdk.PropertyId.SpeechServiceResponse_SynthesisFirstByteLatencyMs))
finished_latency = int(result.properties.get_property(speechsdk.PropertyId.SpeechServiceResponse_SynthesisFinishLatencyMs))
# you can also get the result id, and send to us when you need help for diagnosis
result_id = result.result_id
Latence Popis SPXSpeechSynthesisResult klíč vlastnosti
first byte latency Označuje časové zpoždění mezi spuštěním syntézy a přijetí prvního zvukového bloku. SPXSpeechServiceResponseSynthesisFirstByteLatencyMs
finish latency Označuje časové zpoždění mezi zahájením syntézy a celým syntetizovaným zvukem se přijímá. SPXSpeechServiceResponseSynthesisFinishLatencyMs

Sada Speech SDK změřila latence a umístí je do kontejneru SPXSpeechSynthesisResultvlastností . Pokud je chcete získat, přečtěte si následující kódy.

SPXSpeechSynthesisResult *speechResult = [speechSynthesizer speakText:text];
int firstByteLatency = [intString [speechResult.properties getPropertyById:SPXSpeechServiceResponseSynthesisFirstByteLatencyMs]];
int finishedLatency = [intString [speechResult.properties getPropertyById:SPXSpeechServiceResponseSynthesisFinishLatencyMs]];
// you can also get the result id, and send to us when you need help for diagnosis
NSString *resultId = result.resultId;

První latence bajtů je ve většině případů nižší než latence dokončení. První latence bajtů je nezávislá na délce textu, zatímco latence dokončení se zvyšuje s délkou textu.

V ideálním případě chceme minimalizovat uživatelskou latenci (latenci před poslechem zvuku) na jednu dobu odezvy síťové trasy a latenci prvního zvukového bloku služby syntézy řeči.

Streamování

Streamování je důležité pro snížení latence. Klientský kód může spustit přehrávání, jakmile přijme první blok zvukových dat. Ve scénáři služby můžete bloky zvukových dat okamžitě předávat klientům, aniž byste čekali na celý zvuk.

Streamování můžete povolit pomocí sady PullAudioOutputStreamSpeech SDK , , PushAudioOutputStreamSynthesizingudálosti a AudioDataStream sady Speech SDK.

Příklad AudioDataStream :

using (var synthesizer = new SpeechSynthesizer(config, null as AudioConfig))
{
    using (var result = await synthesizer.StartSpeakingTextAsync(text))
    {
        using (var audioDataStream = AudioDataStream.FromResult(result))
        {
            byte[] buffer = new byte[16000];
            uint filledSize = 0;
            while ((filledSize = audioDataStream.ReadData(buffer)) > 0)
            {
                Console.WriteLine($"{filledSize} bytes received.");
            }
        }
    }
}

K povolení streamování můžete použít PullAudioOutputStreamsadu Speech SDK , PushAudioOutputStreamSynthesizingudálost a AudioDataStream sadu Speech SDK.

Příklad AudioDataStream :

auto synthesizer = SpeechSynthesizer::FromConfig(config, nullptr);
auto result = synthesizer->SpeakTextAsync(text).get();
auto audioDataStream = AudioDataStream::FromResult(result);
uint8_t buffer[16000];
uint32_t filledSize = 0;
while ((filledSize = audioDataStream->ReadData(buffer, sizeof(buffer))) > 0)
{
    cout << filledSize << " bytes received." << endl;
}

K povolení streamování můžete použít PullAudioOutputStreamsadu Speech SDK , PushAudioOutputStreamSynthesizingudálost a AudioDataStream sadu Speech SDK.

Příklad AudioDataStream :

SpeechSynthesizer synthesizer = new SpeechSynthesizer(config, null);
SpeechSynthesisResult result = synthesizer.StartSpeakingTextAsync(text).get();
AudioDataStream audioDataStream = AudioDataStream.fromResult(result);
byte[] buffer = new byte[16000];
long filledSize = audioDataStream.readData(buffer);
while (filledSize > 0) {
    System.out.println(filledSize + " bytes received.");
    filledSize = audioDataStream.readData(buffer);
}

K povolení streamování můžete použít PullAudioOutputStreamsadu Speech SDK , PushAudioOutputStreamSynthesizingudálost a AudioDataStream sadu Speech SDK.

Příklad AudioDataStream :

speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=None)
result = speech_synthesizer.start_speaking_text_async(text).get()
audio_data_stream = speechsdk.AudioDataStream(result)
audio_buffer = bytes(16000)
filled_size = audio_data_stream.read_data(audio_buffer)
while filled_size > 0:
    print("{} bytes received.".format(filled_size))
    filled_size = audio_data_stream.read_data(audio_buffer)

K povolení streamování můžete použít SPXPullAudioOutputStreamsadu Speech SDK , SPXPushAudioOutputStreamSynthesizingudálost a SPXAudioDataStream sadu Speech SDK.

Příklad AudioDataStream :

SPXSpeechSynthesizer *synthesizer = [[SPXSpeechSynthesizer alloc] initWithSpeechConfiguration:speechConfig audioConfiguration:nil];
SPXSpeechSynthesisResult *speechResult = [synthesizer startSpeakingText:inputText];
SPXAudioDataStream *stream = [[SPXAudioDataStream alloc] initFromSynthesisResult:speechResult];
NSMutableData* data = [[NSMutableData alloc]initWithCapacity:16000];
while ([stream readData:data length:16000] > 0) {
    // Read data here
}

Předběžné připojení a opětovné použití SpeechSynthesizer

Sada Speech SDK používá ke komunikaci se službou protokol websocket. V ideálním případě by latence sítě měla být jedna doba odezvy trasy (RTT). Pokud je připojení nově navázáno, latence sítě zahrnuje další čas pro navázání připojení. Vytvoření připojení websocket vyžaduje metodu handshake protokolu TCP, handshake PROTOKOLU SSL, připojení HTTP a upgrade protokolu, což představuje časové zpoždění. Pokud se chcete vyhnout latenci připojení, doporučujeme před připojením a opětovným spuštěním SpeechSynthesizerzařízení .

Předběžné připojení

Pokud chcete provést předběžné připojení, vytvořte připojení ke službě Speech, pokud víte, že připojení je potřeba brzy. Pokud například vytváříte robota řeči v klientovi, můžete se předem připojit ke službě syntézy řeči, když uživatel začne mluvit, a zavolat SpeakTextAsync , až bude text odpovědi robota připravený.

using (var synthesizer = new SpeechSynthesizer(uspConfig, null as AudioConfig))
{
    using (var connection = Connection.FromSpeechSynthesizer(synthesizer))
    {
        connection.Open(true);
    }
    await synthesizer.SpeakTextAsync(text);
}
auto synthesizer = SpeechSynthesizer::FromConfig(config, nullptr);
auto connection = Connection::FromSpeechSynthesizer(synthesizer);
connection->Open(true);
SpeechSynthesizer synthesizer = new SpeechSynthesizer(speechConfig, (AudioConfig) null);
Connection connection = Connection.fromSpeechSynthesizer(synthesizer);
connection.openConnection(true);
synthesizer = speechsdk.SpeechSynthesizer(config, None)
connection = speechsdk.Connection.from_speech_synthesizer(synthesizer)
connection.open(True)
SPXSpeechSynthesizer* synthesizer = [[SPXSpeechSynthesizer alloc]initWithSpeechConfiguration:self.speechConfig audioConfiguration:nil];
SPXConnection* connection = [[SPXConnection alloc]initFromSpeechSynthesizer:synthesizer];
[connection open:true];

Poznámka:

Pokud je syntetizovaný text k dispozici, stačí zavolat SpeakTextAsync syntetizovat zvuk. Sada SDK zpracuje připojení.

Opakované použití SpeechSynthesizer

Dalším způsobem, jak snížit latenci připojení, je znovu použít, SpeechSynthesizer abyste nemuseli vytvářet nové SpeechSynthesizer pro každou syntézu. Doporučujeme použít fond objektů ve scénáři služby, viz náš ukázkový kód pro C# a Javu.

Přenos komprimovaného zvuku přes síť

Pokud je síť nestabilní nebo má omezenou šířku pásma, má velikost datové části vliv také na latenci. Mezitím komprimovaný zvukový formát pomáhá ušetřit šířku pásma sítě uživatelů, což je zvláště cenné pro mobilní uživatele.

Podporujeme mnoho komprimovaných formátů, včetně opus, webmmp3, silka tak dále, viz úplný seznam v SpeechSynthesisOutputFormat. Přenosová Riff24Khz16BitMonoPcm rychlost formátu je například 384 kB/s, zatímco Audio24Khz48KBitRateMonoMp3 stojí pouze 48 kB/s. Naše sada Speech SDK při nastavení výstupního pcm formátu automaticky použije komprimovaný formát pro přenos. Pro Linux a Windows GStreamer je potřeba tuto funkci povolit. Pokyny k instalaci a konfiguraci GStreamer sady Speech SDK najdete v této lekci. Pro Android, iOS a macOS není potřeba žádná další konfigurace od verze 1.20.

Další tipy

Soubory seznamu CRL mezipaměti

Sada Speech SDK používá soubory CRL ke kontrole certifikace. Ukládání do mezipaměti soubory seznamu CRL až do vypršení platnosti vám pomůže vyhnout se stahování souborů CRL pokaždé. Podrobnosti najdete v tématu věnovaném konfiguraci OpenSSL pro Linux.

Použití nejnovější sady Speech SDK

Výkon sady Speech SDK neustále zlepšujeme, takže se snažte v aplikacích používat nejnovější verzi sady Speech SDK.

Vodítko zátěžového testu

Zátěžový test můžete použít k otestování kapacity a latence služby syntézy řeči. Tady je několik pokynů:

  • Služba syntézy řeči má schopnost automatického škálování, ale horizontální navýšení kapacity trvá určitou dobu. Pokud se souběžnost zvýší za krátkou dobu, klient může získat dlouhou latenci nebo 429 kód chyby (příliš mnoho požadavků). Proto doporučujeme zvýšit úroveň souběžnosti krok za krokem v zátěžových testech. Další podrobnosti najdete v tomto článku , zejména v tomto příkladu vzorů úloh.
  • Ukázku můžete použít pomocí fondu objektů (C# a Java) pro zátěžový test a získání čísel latence. V ukázce můžete upravit otočení testu a souběžnost tak, aby splňovala vaši cílovou souběžnost.
  • Služba má omezení kvóty na základě skutečného provozu, a proto pokud chcete provést zátěžový test s vyšší souběžností než skutečný provoz, připojte se před testem.

Další kroky