Delen via


Latentie van spraaksynthese verlagen met behulp van Speech SDK

In dit artikel introduceren we de aanbevolen procedures om de latentie van tekst tot spraaksynthese te verlagen en de beste prestaties aan uw eindgebruikers te bieden.

Normaal gesproken meten we de latentie door first byte latency en finish latency, als volgt:

Latentie Beschrijving Eigenschapssleutel SpeechSynthesisResult
first byte client latency Geeft de tijdsvertraging aan tussen het starten van de synthese en het ontvangen van het eerste audiosegment bij de client, inclusief netwerklatentie. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish client latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen op de client, inclusief netwerklatentie. SpeechServiceResponse_SynthesisFinishLatencyMs
network latency De netwerklatentie tussen de client en de Azure TTS-service. SpeechServiceResponse_SynthesisNetworkLatencyMs
first byte service latency Geeft de tijdsvertraging aan tussen de ontvangen syntheseaanvraag van de Azure TTS-service en het eerste audiosegment wordt geretourneerd. SpeechServiceResponse_SynthesisServiceLatencyMs

De Speech SDK plaatst de latentieduur in de verzameling Eigenschappen van SpeechSynthesisResult. In de volgende voorbeeldcode ziet u deze waarden.

var result = await synthesizer.SpeakTextAsync(text);
Console.WriteLine($"first byte client latency: \t{result.Properties.GetProperty(PropertyId.SpeechServiceResponse_SynthesisFirstByteLatencyMs)} ms");
Console.WriteLine($"finish client latency: \t{result.Properties.GetProperty(PropertyId.SpeechServiceResponse_SynthesisFinishLatencyMs)} ms");
Console.WriteLine($"network latency: \t{result.Properties.GetProperty(PropertyId.SpeechServiceResponse_SynthesisNetworkLatencyMs)} ms");
Console.WriteLine($"first byte service latency: \t{result.Properties.GetProperty(PropertyId.SpeechServiceResponse_SynthesisServiceLatencyMs)} ms");
// you can also get the result id, and send to us when you need help for diagnosis
var resultId = result.ResultId;
Latentie Beschrijving Eigenschapssleutel SpeechSynthesisResult
first byte client latency Geeft de tijdsvertraging aan tussen het begin van de synthese en het moment waarop het eerste audiogedeelte wordt ontvangen op de client, inclusief netwerklatentie. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish client latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen op de client, inclusief netwerklatentie. SpeechServiceResponse_SynthesisFinishLatencyMs
network latency De netwerklatentie tussen de client en de Azure TTS-service. SpeechServiceResponse_SynthesisNetworkLatencyMs
first byte service latency Geeft de tijdsvertraging aan tussen de ontvangen syntheseaanvraag van de Azure TTS-service en het eerste audiosegment wordt geretourneerd. SpeechServiceResponse_SynthesisServiceLatencyMs

De Speech SDK heeft de latenties gemeten en deze in het eigenschapspakket van SpeechSynthesisResult geplaatst. Raadpleeg de volgende codes om ze op te halen.

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));
auto firstByteLatency = std::stoi(result->Properties.GetProperty(PropertyId::SpeechServiceResponse_SynthesisNetworkLatencyMs));
auto firstByteLatency = std::stoi(result->Properties.GetProperty(PropertyId::SpeechServiceResponse_SynthesisServiceLatencyMs));
// you can also get the result id, and send to us when you need help for diagnosis
auto resultId = result->ResultId;
Latentie Beschrijving Eigenschapssleutel SpeechSynthesisResult
first byte client latency Geeft de tijdsvertraging aan tussen het moment dat de synthese start en het eerste audiostuk door de client ontvangen wordt, inclusief netwerklatentie. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish client latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen op de client, inclusief netwerklatentie. SpeechServiceResponse_SynthesisFinishLatencyMs
network latency De netwerklatentie tussen de client en de Azure TTS-service. SpeechServiceResponse_SynthesisNetworkLatencyMs
first byte service latency Geeft de tijdsvertraging aan tussen de ontvangen syntheseaanvraag van de Azure TTS-service en het eerste audiosegment wordt geretourneerd. SpeechServiceResponse_SynthesisServiceLatencyMs

De Speech SDK heeft de latenties gemeten en deze in het eigenschapspakket van SpeechSynthesisResult geplaatst. Raadpleeg de volgende codes om ze op te halen.

SpeechSynthesisResult result = synthesizer.SpeakTextAsync(text).get();
System.out.println("first byte client latency: \t" + result.getProperties().getProperty(PropertyId.SpeechServiceResponse_SynthesisFirstByteLatencyMs) + " ms.");
System.out.println("finish client latency: \t" + result.getProperties().getProperty(PropertyId.SpeechServiceResponse_SynthesisFinishLatencyMs) + " ms.");
System.out.println("network latency: \t" + result.getProperties().getProperty(PropertyId.SpeechServiceResponse_SynthesisNetworkLatencyMs) + " ms.");
System.out.println("first byte service latency: \t" + result.getProperties().getProperty(PropertyId.SpeechServiceResponse_SynthesisServiceLatencyMs) + " ms.");
// you can also get the result id, and send to us when you need help for diagnosis
String resultId = result.getResultId();
Latentie Beschrijving Eigenschapssleutel SpeechSynthesisResult
first byte client latency Geeft de tijdsvertraging aan tussen het begin van de synthese en het moment waarop het eerste audiofragment door de client wordt ontvangen, inclusief netwerklatentie. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish client latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen op de client, inclusief netwerklatentie. SpeechServiceResponse_SynthesisFinishLatencyMs
network latency De netwerklatentie tussen de client en de Azure TTS-service. SpeechServiceResponse_SynthesisNetworkLatencyMs
first byte service latency Geeft de tijdsvertraging aan tussen de ontvangen syntheseaanvraag van de Azure TTS-service en het eerste audiosegment wordt geretourneerd. SpeechServiceResponse_SynthesisServiceLatencyMs

De Speech SDK heeft de latenties gemeten en deze in de eigenschappenverzameling van SpeechSynthesisResult geplaatst. Raadpleeg de volgende codes om ze op te halen.

result = synthesizer.speak_text_async(text).get()
first_byte_client_latency = int(result.properties.get_property(speechsdk.PropertyId.SpeechServiceResponse_SynthesisFirstByteLatencyMs))
finished_client_latency = int(result.properties.get_property(speechsdk.PropertyId.SpeechServiceResponse_SynthesisFinishLatencyMs))
network_latency = int(result.properties.get_property(speechsdk.PropertyId.SpeechServiceResponse_SynthesisNetworkLatencyMs))
first_byte_service_latency = int(result.properties.get_property(speechsdk.PropertyId.SpeechServiceResponse_SynthesisServiceLatencyMs))
# you can also get the result id, and send to us when you need help for diagnosis
result_id = result.result_id
Latentie Beschrijving Eigenschapssleutel SPXSpeechSynthesisResult
first byte client latency Geeft de tijdsvertraging aan tussen de start van de synthese en het moment waarop het eerste audiosegment, inclusief netwerklatentie, wordt ontvangen op de client. SPXSpeechServiceResponseSynthesisFirstByteLatencyMs
finish client latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen op de client, inclusief netwerklatentie. SPXSpeechServiceResponseSynthesisFinishLatencyMs
network latency De netwerklatentie tussen de client en de Azure TTS-service. SPXSpeechServiceResponseSynthesisNetworkLatencyMs
first byte service latency Geeft de tijdsvertraging aan tussen de ontvangen syntheseaanvraag van de Azure TTS-service en het eerste audiosegment wordt geretourneerd. SPXSpeechServiceResponseSynthesisServiceLatencyMs

De Speech SDK heeft de latenties gemeten en plaatst deze in de eigenschapstas van SPXSpeechSynthesisResult. Raadpleeg de volgende codes om ze op te halen.

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

De eerste bytelatentie is in de meeste gevallen lager dan de voltooiingslatentie. De eerste bytelatentie is onafhankelijk van de tekstlengte, terwijl de latentie met tekstlengte toeneemt.

Idealiter willen we de door de gebruiker ervaren latentie (de latentie voordat de gebruiker het geluid hoort) minimaliseren tot één netwerkroutetijd plus de eerste audiosegmentlatentie van de spraaksyntheseservice.

Streamen

Streaming is essentieel voor het verlagen van de latentie. Clientcode kan beginnen met afspelen als eerste audiosegment wordt ontvangen. In een servicescenario kunt u de audiosegmenten direct doorsturen naar uw clients in plaats van te wachten op de hele audio.

U kunt de PullAudioOutputStream, PushAudioOutputStreamgebeurtenisSynthesizing en AudioDataStream de Speech SDK gebruiken om streaming in te schakelen.

Nemen AudioDataStream als voorbeeld:

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

U kunt de PullAudioOutputStream, PushAudioOutputStream, de Synthesizing gebeurtenis en AudioDataStream van de Speech SDK gebruiken om streaming in te schakelen.

Nemen AudioDataStream als voorbeeld:

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

U kunt de PullAudioOutputStreamgebeurtenis , PushAudioOutputStreamde Synthesizing gebeurtenis en AudioDataStream de Speech SDK gebruiken om streaming in te schakelen.

Nemen AudioDataStream als voorbeeld:

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

U kunt de PullAudioOutputStream, PushAudioOutputStream, de Synthesizing-gebeurtenis en AudioDataStream van de Speech SDK gebruiken om streaming in te schakelen.

Nemen AudioDataStream als voorbeeld:

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)

U kunt de SPXPullAudioOutputStream, SPXPushAudioOutputStream, de Synthesizing gebeurtenis en SPXAudioDataStream van de Speech SDK gebruiken om streaming mogelijk te maken.

Nemen AudioDataStream als voorbeeld:

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
}

Spraaksyntheseizer vooraf verbinden en opnieuw gebruiken

De Speech SDK maakt gebruik van een websocket om te communiceren met de service. In het ideale geval moet de netwerklatentie één rondreistijd (RTT) bedragen. Als de verbinding nieuw tot stand is gebracht, bevat de netwerklatentie extra tijd om de verbinding tot stand te brengen. De inrichting van een websocket-verbinding vereist de TCP-handshake, SSL-handshake, http-verbinding en protocolupgrade, waardoor vertraging wordt geïntroduceerd. Om de latentie van de verbinding te voorkomen, raden we u aan vooraf verbinding te maken en opnieuw te SpeechSynthesizergebruiken.

Vooraf verbinding maken

Als u vooraf verbinding wilt maken, maakt u een verbinding met de Speech-service wanneer u weet dat de verbinding binnenkort nodig is. Als u bijvoorbeeld een spraakbot in de client bouwt, kunt u vooraf verbinding maken met de spraaksyntheseservice wanneer de gebruiker begint te praten en bellen SpeakTextAsync wanneer de antwoordtekst van de bot gereed is.

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

Notitie

Als de tekst beschikbaar is, gebruik SpeakTextAsync om de audio te synthetiseren. De SDK verwerkt de verbinding.

SpeechSynthesizer opnieuw gebruiken

Een andere manier om de verbindingslatentie te verminderen, is door het SpeechSynthesizer opnieuw te gebruiken, zodat u geen nieuwe SpeechSynthesizer hoeft te maken voor elke synthese. U wordt aangeraden een objectgroep te gebruiken in het servicescenario. Bekijk onze voorbeeldcode voor C# en Java.

Gecomprimeerde audio verzenden via het netwerk

Wanneer het netwerk instabiel of met beperkte bandbreedte is, is de nettolading ook van invloed op de latentie. Ondertussen helpt een gecomprimeerde audio-indeling om de netwerkbandbreedte van de gebruikers te besparen, wat vooral waardevol is voor mobiele gebruikers.

We ondersteunen veel gecomprimeerde indelingen, waaronder opus, webm, mp3, silkenzovoort, bekijk de volledige lijst in SpeechSynthesisOutputFormat. De bitrate van het formaat Riff24Khz16BitMonoPcm is bijvoorbeeld 384 kbps, terwijl Audio24Khz48KBitRateMonoMp3 slechts 48 kbps is. De Speech SDK gebruikt automatisch een gecomprimeerde indeling voor verzending wanneer een pcm uitvoerindeling is ingesteld. Voor Linux en Windows GStreamer is vereist om deze functie in te schakelen. Raadpleeg deze instructie voor het installeren en configureren GStreamer van de Speech SDK. Voor Android, iOS en macOS is geen extra configuratie nodig vanaf versie 1.20.

Invoertekst streamen

Tekststreaming maakt realtime tekstverwerking mogelijk voor snelle audiogeneratie. Het is perfect voor dynamische tekstvocalisatie, zoals het voorlezen van uitvoerresultaten van AI-modellen zoals GPT in real time. Deze functie minimaliseert de latentie en verbetert de vloeiendheid en reactiesnelheid van audio-uitvoer, waardoor deze ideaal is voor interactieve toepassingen, livegebeurtenissen en responsieve AI-gestuurde dialogen.

Tekststreaming gebruiken

Tekststreaming wordt ondersteund in C#, C++ en Python met Speech SDK.

Als u de functie voor tekststreaming wilt gebruiken, maakt u verbinding met het websocket V2-eindpunt: wss://{region}.tts.speech.microsoft.com/cognitiveservices/websocket/v2

Zie de voorbeeldcode voor het instellen van het eindpunt:

// IMPORTANT: MUST use the websocket v2 endpoint
var ttsEndpoint = $"wss://{Environment.GetEnvironmentVariable("AZURE_TTS_REGION")}.tts.speech.microsoft.com/cognitiveservices/websocket/v2";
var speechConfig = SpeechConfig.FromEndpoint(
    new Uri(ttsEndpoint),
    Environment.GetEnvironmentVariable("AZURE_TTS_API_KEY"));

Belangrijke stappen

  1. Een aanvraag voor een tekststroom maken: gebruiken SpeechSynthesisRequestInputType.TextStream om een tekststroom te initiëren.

  2. Globale eigenschappen instellen: Pas instellingen zoals uitvoerindeling en spraaknaam rechtstreeks aan, omdat de functie gedeeltelijke tekstinvoer verwerkt en SSML niet ondersteunt. Raadpleeg de volgende voorbeeldcode voor instructies over het instellen ervan. OpenAI-tekst naar spraakstemmen wordt niet ondersteund door de functie voor tekststreaming. Zie deze taaltabel voor volledige taalondersteuning.

    // Set output format
    speechConfig.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm);
    
    // Set a voice name
    SpeechConfig.SetProperty(PropertyId.SpeechServiceConnection_SynthVoice, "en-US-AvaMultilingualNeural");
    
  3. Stream uw tekst: voor elk tekstsegment dat is gegenereerd op basis van een GPT-model, gebruikt request.InputStream.Write(text); u deze om de tekst naar de stream te verzenden.

  4. Sluit de stroom: nadat het GPT-model de uitvoer heeft voltooid, sluit u de stream met behulp van request.InputStream.Close();.

Zie de voorbeeldcode op GitHub voor gedetailleerde implementatie

Als u de functie voor tekststreaming wilt gebruiken, maakt u verbinding met het websocket V2-eindpunt: wss://{region}.tts.speech.microsoft.com/cognitiveservices/websocket/v2

Zie de voorbeeldcode voor het instellen van het eindpunt:

# IMPORTANT: MUST use the websocket v2 endpoint
speech_config = speechsdk.SpeechConfig(endpoint=f"wss://{os.getenv('AZURE_TTS_REGION')}.tts.speech.microsoft.com/cognitiveservices/websocket/v2",
                                       subscription=os.getenv("AZURE_TTS_API_KEY"))

Belangrijke stappen

  1. Een aanvraag voor een tekststroom maken: gebruiken speechsdk.SpeechSynthesisRequestInputType.TextStream om een tekststroom te initiëren.

  2. Globale eigenschappen instellen: Pas instellingen zoals uitvoerindeling en spraaknaam rechtstreeks aan, omdat de functie gedeeltelijke tekstinvoer verwerkt en SSML niet ondersteunt. Raadpleeg de volgende voorbeeldcode voor instructies over het instellen ervan. OpenAI-tekst naar spraakstemmen wordt niet ondersteund door de functie voor tekststreaming. Zie deze taaltabel voor volledige taalondersteuning.

    # set a voice name
    speech_config.speech_synthesis_voice_name = "en-US-AvaMultilingualNeural"
    
  3. Stream uw tekst: voor elk tekstsegment dat is gegenereerd op basis van een GPT-model, gebruikt request.input_stream.write(text) u deze om de tekst naar de stream te verzenden.

  4. Sluit de stroom: nadat het GPT-model de uitvoer heeft voltooid, sluit u de stream met behulp van request.input_stream.close().

Zie de voorbeeldcode op GitHub voor gedetailleerde implementatie.

De C++-voorbeeldcode is nu niet beschikbaar. Zie voor de voorbeeldcode die laat zien hoe u tekststreaming gebruikt:

Zie voor de voorbeeldcode die laat zien hoe u tekststreaming gebruikt:

Zie voor de voorbeeldcode die laat zien hoe u tekststreaming gebruikt:

Andere tips

CRL-bestanden in cache

De Speech SDK gebruikt CRL-bestanden om de certificering te controleren. Als u de CRL-bestanden in de cache opslaat totdat deze zijn verlopen, kunt u voorkomen dat CRL-bestanden telkens worden gedownload. Zie OpenSSL voor Linux configureren voor meer informatie.

De nieuwste Speech SDK gebruiken

We blijven de prestaties van de Speech SDK verbeteren, dus probeer de nieuwste Speech SDK in uw toepassing te gebruiken.

Richtlijn voor belastingstests

U kunt belastingstest gebruiken om de capaciteit en latentie van de spraaksyntheseservice te testen. Hier volgen enkele richtlijnen:

  • De spraaksyntheseservice heeft de mogelijkheid om automatisch te schalen, maar het duurt even om uit te schalen. Als de gelijktijdigheid in korte tijd wordt verhoogd, krijgt de client mogelijk lange latentie of 429 foutcode (te veel aanvragen). Daarom raden we u aan om uw gelijktijdigheid stapsgewijs tijdens het uitvoeren van de loadtest te verhogen. Zie dit artikel voor meer informatie, met name dit voorbeeld van workloadpatronen.
  • U kunt ons voorbeeld gebruiken met behulp van een objectgroep (C# en Java) voor belastingstests en het ophalen van de latentienummers. U kunt de testuitvoeringen en concurrentie in de voorbeeldconfiguratie wijzigen om te voldoen aan uw doel voor gelijktijdigheid.
  • De service heeft een quotumbeperking op basis van het werkelijke verkeer, dus als u een belastingstest wilt uitvoeren met de gelijktijdigheid die hoger is dan uw werkelijke verkeer, maakt u verbinding voordat u de test uitvoert.

Volgende stappen