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
eerste bytelatentie Geeft de tijdsvertraging aan tussen het begin van de synthesetaak en de ontvangst van het eerste segment audiogegevens. SpeechServiceResponse_SynthesisFirstByteLatencyMs
latentie voltooien Geeft de tijdsvertraging aan tussen het begin van de synthesetaak en de ontvangst van de volledige gesynthetiseerde audiogegevens. SpeechServiceResponse_SynthesisFinishLatencyMs

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 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;
Latentie Beschrijving Eigenschapssleutel SpeechSynthesisResult
first byte latency Geeft de tijdsvertraging aan tussen de synthese begint en het eerste audiosegment wordt ontvangen. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen. SpeechServiceResponse_SynthesisFinishLatencyMs

De Speech SDK heeft de latenties gemeten en deze in de eigenschappentas van SpeechSynthesisResult. 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));
// 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 latency Geeft de tijdsvertraging aan tussen de synthese begint en het eerste audiosegment wordt ontvangen. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen. SpeechServiceResponse_SynthesisFinishLatencyMs

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

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();
Latentie Beschrijving Eigenschapssleutel SpeechSynthesisResult
first byte latency Geeft de tijdsvertraging aan tussen de synthese begint en het eerste audiosegment wordt ontvangen. SpeechServiceResponse_SynthesisFirstByteLatencyMs
finish latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen. SpeechServiceResponse_SynthesisFinishLatencyMs

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

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
Latentie Beschrijving Eigenschapssleutel SPXSpeechSynthesisResult
first byte latency Geeft de tijdsvertraging aan tussen de synthese begint en het eerste audiosegment wordt ontvangen. SPXSpeechServiceResponseSynthesisFirstByteLatencyMs
finish latency Geeft de tijdsvertraging aan tussen de synthese begint en de volledige gesynthetiseerde audio wordt ontvangen. SPXSpeechServiceResponseSynthesisFinishLatencyMs

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

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;

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.

Streaming

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 PullAudioOutputStreamgebeurtenis , PushAudioOutputStreamde Synthesizing gebeurtenis en AudioDataStream 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 PullAudioOutputStreamgebeurtenis , PushAudioOutputStreamde Synthesizing gebeurtenis en AudioDataStream 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 SPXPullAudioOutputStreamgebeurtenis , SPXPushAudioOutputStreamde Synthesizing gebeurtenis en SPXAudioDataStream de Speech SDK gebruiken om streaming in te schakelen.

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 routerittijd (RTT) zijn. 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, belt SpeakTextAsync u gewoon 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 Riff24Khz16BitMonoPcm de indeling is bijvoorbeeld 384kbbits, terwijl Audio24Khz48KBitRateMonoMp3 er slechts 48kbbits kosten. 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 tekstzang, zoals het lezen van uitvoer van AI-modellen zoals GPT in realtime. 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 stap voor stap in de belastingstest 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 testdraai- en gelijktijdigheid in het voorbeeld wijzigen om te voldoen aan de gelijktijdigheid van uw doel.
  • 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