Kortare svarstider för talsyntes med hjälp av Speech SDK

Anteckning

Den här artikeln kräver Speech SDK 1.17.0 eller senare.

Svarstiden för syntesen är viktig för dina program. I den här artikeln introducerar vi metodtips för att minska svarstiden och ge slutanvändarna bästa möjliga prestanda.

Normalt mäter vi svarstiden med first byte latency och finish latency , enligt följande:

Svarstid Beskrivning SpeechSynthesisResult-egenskapsnyckel
svarstid för första byte Anger tidsfördröjningen mellan början av syntesuppgiften och mottagandet av det första segmentet av ljuddata. SpeechServiceResponse_SynthesisFirstByteLatencyMs
avsluta svarstiden Anger tidsfördröjningen mellan början av syntesuppgiften och mottagandet av hela syntetiserade ljuddata. SpeechServiceResponse_SynthesisFinishLatencyMs

Speech SDK placerar svarstidens varaktighet i samlingen Egenskaper för SpeechSynthesisResult . Följande exempelkod visar dessa värden.

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;
Svarstid Beskrivning SpeechSynthesisResult-egenskapsnyckel
first byte latency Anger tidsfördröjningen mellan syntesen startar och det första ljud segmentet tas emot. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Anger tidsfördröjningen mellan att syntesen startar och att hela det syntetiserade ljudet tas emot. SpeechServiceResponse_SynthesisFinishLatencyMs

Speech SDK mätte svarstiderna och placerar dem i egenskapsdetalgenskapen för SpeechSynthesisResult . Se följande koder för att hämta dem.

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;
Svarstid Beskrivning SpeechSynthesisResult-egenskapsnyckel
first byte latency Anger tidsfördröjningen mellan syntesen startar och det första ljud segmentet tas emot. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Anger tidsfördröjningen mellan att syntesen startar och att hela det syntetiserade ljudet tas emot. SpeechServiceResponse_SynthesisFinishLatencyMs

Speech SDK mätte svarstiderna och placerar dem i egenskapsdetalgenskapen för SpeechSynthesisResult . Se följande koder för att hämta dem.

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();
Svarstid Beskrivning SpeechSynthesisResult-egenskapsnyckel
first byte latency Anger tidsfördröjningen mellan syntesen startar och det första ljud segmentet tas emot. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Anger tidsfördröjningen mellan att syntesen startar och att hela det syntetiserade ljudet tas emot. SpeechServiceResponse_SynthesisFinishLatencyMs

Speech SDK mätte svarstiderna och placerar dem i egenskapsdetalgenskapen för SpeechSynthesisResult . Se följande koder för att hämta dem.

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
Svarstid Beskrivning SPXSpeechSynthesisResult-egenskapsnyckel
first byte latency Anger tidsfördröjningen mellan syntesen startar och det första ljud segmentet tas emot. SPXSpeechServiceResponseSynthesisFirstByteLatencyMs
finish latency Anger tidsfördröjningen mellan att syntesen startar och att hela det syntetiserade ljudet tas emot. SPXSpeechServiceResponseSynthesisFinishLatencyMs

Speech SDK mätte svarstiderna och placerar dem i egenskapsdetalgenskapen för SPXSpeechSynthesisResult . Se följande koder för att hämta dem.

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;

Den första byte-svarstiden är mycket lägre än svarstiden för slutförande i de flesta fall. Den första bytens svarstid är oberoende av textlängden, medan svarstiden för slutförande ökar med textlängden.

Helst vill vi minimera svarstiden för användarupplevelsen (svarstiden innan användaren hör ljudet) till en nätverkstid plus den första svarstiden för ljud segment för talsyntestjänsten.

Strömning

Strömning är viktigt för att sänka svarstiden. Klientkoden kan starta uppspelningen när det första ljud segmentet tas emot. I ett tjänstscenario kan du vidarebefordra ljud segmenten direkt till dina klienter i stället för att vänta på hela ljudet.

Du kan använda PullAudioOutputStream , PushAudioOutputStream , händelse Synthesizing ochför Speech SDK för att aktivera AudioDateStream strömning.

Som AudioDateStream exempel:

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.");
            }
        }
    }
}

Du kan använda PullAudioOutputStream , PushAudioOutputStream , händelsen Synthesizing ochFör Speech SDK för att aktivera AudioDateStream strömning.

Som AudioDateStream exempel:

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;
}

Du kan använda PullAudioOutputStream , PushAudioOutputStream , händelsen Synthesizing ochFör Speech SDK för att aktivera AudioDateStream strömning.

Som AudioDateStream exempel:

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);
}

Du kan använda PullAudioOutputStream , PushAudioOutputStream , händelsen Synthesizing ochFör Speech SDK för att aktivera AudioDateStream strömning.

Som AudioDateStream exempel:

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)

Du kan använda SPXPullAudioOutputStream , SPXPushAudioOutputStream , händelsen Synthesizing ochFör Speech SDK för att aktivera SPXAudioDataStream strömning.

Som AudioDateStream exempel:

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
}

För-ansluta och återanvända SpeechSynthesizer

Speech SDK använder en websocket för att kommunicera med tjänsten. Helst bör nätverksfördröjningen vara en färdtid (RTT). Om anslutningen nyligen har upprättats innehåller nätverksfördröjningen extra tid för att upprätta anslutningen. Etableringen av en websocket-anslutning kräver TCP-handskakning, SSL-handskakning, HTTP-anslutning och protokolluppgradering, vilket medför tidsfördröjning. För att undvika anslutningsfördröjningen rekommenderar vi att du ansluter i förväg och återanvänder SpeechSynthesizer .

För-anslutning

För att ansluta i förväg upprättar du en anslutning till Speech-tjänsten när du vet att anslutningen kommer att behövas snart. Om du till exempel skapar en talrobot i klienten kan du ansluta till talsyntestjänsten i förväg när användaren börjar prata och anropa när robotens svarstext SpeakTextAsync är klar.

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];

Anteckning

Om den syntetiserade texten är tillgänglig anropar du SpeakTextAsync bara för att syntetisera ljudet. SDK hanterar anslutningen.

Återanvända SpeechSynthesizer

Ett annat sätt att minska anslutningsfördröjningen är att återanvända så att SpeechSynthesizer du inte behöver skapa en ny för varje SpeechSynthesizer syntes. Vi rekommenderar att du använder objektpoolen i tjänstscenariot. Se vår exempelkod för C# och Java.

Överföra komprimerat ljud över nätverket

När nätverket är instabilt eller har begränsad bandbredd påverkar nyttolastens storlek även svarstiden. Under tiden hjälper ett komprimerat ljudformat till att spara användarnas nätverksbandbredd, vilket är särskilt värdefullt för mobila användare.

Vi stöder många komprimerade format, inklusive , , , och så vidare, se den opus webm fullständiga listan i mp3 silk SpeechSynthesisOutputFormat. Formatets bithastighet är till exempel Riff24Khz16BitMonoPcm 384 kbit/s, medan Audio24Khz48KBitRateMonoMp3 bara kostar 48 kbit/s. Vårt Speech SDK använder automatiskt ett komprimerat format för överföring när ett pcm utdataformat har angetts och GStreamer är korrekt installerat. Läs den här instruktionen för att installera och GStreamer konfigurera för Speech SDK.

Andra tips

Cachelagra CRL-filer

Speech SDK använder CRL-filer för att kontrollera certifieringen. Genom att cachelagra CRL-filerna tills de har upphört att gälla undviker du att ladda ned CRL-filer varje gång. Mer information finns i Konfigurera OpenSSL för Linux.

Använda senaste Speech SDK

Vi fortsätter att förbättra Speech SDK:ns prestanda, så försök att använda den senaste Speech SDK:n i ditt program. Vi har till exempel åtgärdat TCP_NODELAY ett inställningsproblem i 1.16.0, vilket minskade extra tid för en resväg.

Riktlinjer för belastningstest

Du kan använda belastningstest för att testa talsyntestjänstens kapacitet och svarstid. Här följer några riktlinjer.

  • Talsyntestjänsten har möjlighet att skala automatiskt, men det tar tid att skala ut. Om samtidigheten ökar på kort tid kan klienten få lång svarstid eller 429 felkod (för många begäranden). Därför rekommenderar vi att du ökar samtidigheten steg för steg i belastningstestet. Mer information finns i den här artikeln.
  • Tjänsten har en kvotbegränsning baserat på den verkliga trafiken. Om du vill utföra belastningstest med samtidigheten som är mycket högre än den riktiga trafiken ansluter du därför innan testet.

Nästa steg