Ridurre la latenza della sintesi vocale con Speech SDK
La latenza di sintesi è fondamentale per le applicazioni. In questo articolo verranno presentate le procedure consigliate per ridurre la latenza e offrire prestazioni ottimali agli utenti finali.
In genere, la latenza viene misurata in base a first byte latency
e finish latency
, come indicato di seguito:
Latenza | Descrizione | Chiave della proprietà SpeechSynthesisResult |
---|---|---|
latenza di primo byte | Indica il ritardo di tempo tra l'inizio dell'attività di sintesi e la ricezione del primo blocco di dati audio. | SpeechServiceResponse_SynthesisFirstByteLatencyMs |
latenza di fine | Indica il ritardo di tempo tra l'inizio dell'attività di sintesi e la ricezione dell'intero dati audio sintetizzato. | SpeechServiceResponse_SynthesisFinishLatencyMs |
Speech SDK inserisce le durate di latenza nella raccolta Properties di SpeechSynthesisResult
. Il codice di esempio seguente mostra questi valori.
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;
Latenza | Descrizione | Chiave della proprietà SpeechSynthesisResult |
---|---|---|
first byte latency |
Indica il ritardo tra l'inizio della sintesi e il primo blocco audio ricevuto. | SpeechServiceResponse_SynthesisFirstByteLatencyMs |
finish latency |
Indica il ritardo di tempo tra l'inizio della sintesi e l'intero audio sintetizzato. | SpeechServiceResponse_SynthesisFinishLatencyMs |
Speech SDK ha misurato le latenze e le inserisce nel contenitore delle proprietà di SpeechSynthesisResult
. Per ottenerli, fare riferimento ai codici seguenti.
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;
Latenza | Descrizione | Chiave della proprietà SpeechSynthesisResult |
---|---|---|
first byte latency |
Indica il ritardo tra l'inizio della sintesi e il primo blocco audio ricevuto. | SpeechServiceResponse_SynthesisFirstByteLatencyMs |
finish latency |
Indica il ritardo di tempo tra l'inizio della sintesi e l'intero audio sintetizzato. | SpeechServiceResponse_SynthesisFinishLatencyMs |
Speech SDK ha misurato le latenze e le inserisce nel contenitore delle proprietà di SpeechSynthesisResult
. Per ottenerli, fare riferimento ai codici seguenti.
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();
Latenza | Descrizione | Chiave della proprietà SpeechSynthesisResult |
---|---|---|
first byte latency |
Indica il ritardo tra l'inizio della sintesi e il primo blocco audio ricevuto. | SpeechServiceResponse_SynthesisFirstByteLatencyMs |
finish latency |
Indica il ritardo di tempo tra l'inizio della sintesi e l'intero audio sintetizzato. | SpeechServiceResponse_SynthesisFinishLatencyMs |
Speech SDK ha misurato le latenze e le inserisce nel contenitore delle proprietà di SpeechSynthesisResult
. Per ottenerli, fare riferimento ai codici seguenti.
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
Latenza | Descrizione | Chiave della proprietà SPXSpeechSynthesisResult |
---|---|---|
first byte latency |
Indica il ritardo tra l'inizio della sintesi e il primo blocco audio ricevuto. | SPXSpeechServiceResponseSynthesisFirstByteLatencyMs |
finish latency |
Indica il ritardo di tempo tra l'inizio della sintesi e l'intero audio sintetizzato. | SPXSpeechServiceResponseSynthesisFinishLatencyMs |
Speech SDK ha misurato le latenze e le inserisce nel contenitore delle proprietà di SPXSpeechSynthesisResult
. Per ottenerli, fare riferimento ai codici seguenti.
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;
La prima latenza di byte è inferiore alla latenza di fine nella maggior parte dei casi. La prima latenza dei byte è indipendente dalla lunghezza del testo, mentre la latenza di fine aumenta con la lunghezza del testo.
Idealmente, si vuole ridurre al minimo la latenza vissuto dall'utente (la latenza prima che l'utente senta il suono) a un tempo di viaggio di route di rete più la prima latenza audio in blocchi del servizio di sintesi vocale.
Streaming
Lo streaming è fondamentale per ridurre la latenza. Il codice client può avviare la riproduzione quando viene ricevuto il primo blocco audio. In uno scenario di servizio, è possibile inoltrare immediatamente i blocchi audio ai client invece di attendere l'intero audio.
È possibile usare l'evento PullAudioOutputStream
, PushAudioOutputStream
, Synthesizing
e AudioDataStream
di Speech SDK per abilitare lo streaming.
Prendendo AudioDataStream
come esempio:
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.");
}
}
}
}
È possibile usare PullAudioOutputStream
, PushAudioOutputStream
, l'eventoSynthesizing
e AudioDataStream
speech SDK per abilitare lo streaming.
Prendendo AudioDataStream
come esempio:
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;
}
È possibile usare PullAudioOutputStream
, PushAudioOutputStream
, l'eventoSynthesizing
e AudioDataStream
speech SDK per abilitare lo streaming.
Prendendo AudioDataStream
come esempio:
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);
}
È possibile usare PullAudioOutputStream
, PushAudioOutputStream
, l'eventoSynthesizing
e AudioDataStream
speech SDK per abilitare lo streaming.
Prendendo AudioDataStream
come esempio:
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)
È possibile usare SPXPullAudioOutputStream
, SPXPushAudioOutputStream
, l'eventoSynthesizing
e SPXAudioDataStream
speech SDK per abilitare lo streaming.
Prendendo AudioDataStream
come esempio:
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
}
Pre-connettere e riutilizzare SpeechSynthesizer
Speech SDK usa un websocket per comunicare con il servizio.
Idealmente, la latenza di rete deve essere un tempo di viaggio di route (RTT).
Se la connessione viene appena stabilita, la latenza di rete include tempo aggiuntivo per stabilire la connessione.
La creazione di una connessione Websocket richiede l'handshake TCP, l'handshake SSL, la connessione HTTP e l'aggiornamento del protocollo, che introduce un ritardo di tempo.
Per evitare la latenza di connessione, è consigliabile pre-connettersi e riutilizzare .SpeechSynthesizer
Pre-connessione
Per effettuare la pre-connessione, stabilire una connessione al servizio Voce quando si sa che la connessione è necessaria a breve. Ad esempio, se si sta creando un bot di riconoscimento vocale nel client, è possibile pre-connettersi al servizio di sintesi vocale quando l'utente inizia a parlare e chiamare SpeakTextAsync
quando il testo di risposta del bot è pronto.
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];
Nota
Se il testo di sintesi è disponibile, è sufficiente chiamare SpeakTextAsync
per sintetizzare l'audio. L'SDK gestirà la connessione.
Riutilizzare SpeechSynthesizer
Un altro modo per ridurre la latenza di connessione consiste nel riutilizzare in SpeechSynthesizer
modo da non dover creare un nuovo SpeechSynthesizer
oggetto per ogni sintesi.
È consigliabile usare il pool di oggetti nello scenario del servizio. Vedere il codice di esempio per C# e Java.
Trasmettere audio compresso in rete
Quando la rete è instabile o con larghezza di banda limitata, anche le dimensioni del payload influiscono sulla latenza. Nel frattempo, un formato audio compresso consente di risparmiare la larghezza di banda di rete degli utenti, che è particolarmente utile per gli utenti mobili.
Sono supportati molti formati compressi, tra cui opus
, webm
mp3
, silk
e così via, vedere l'elenco completo in SpeechSynthesisOutputFormat.
Ad esempio, la velocità in bit del Riff24Khz16BitMonoPcm
formato è di 384 kbps, mentre Audio24Khz48KBitRateMonoMp3
costa solo 48 kbps.
Speech SDK userà automaticamente un formato compresso per la trasmissione quando viene impostato un pcm
formato di output.
Per Linux e Windows, GStreamer
è necessario per abilitare questa funzionalità.
Fare riferimento a questa istruzione per installare e configurare GStreamer
Speech SDK.
Per Android, iOS e macOS, non è necessaria alcuna configurazione aggiuntiva a partire dalla versione 1.20.
Altri suggerimenti
Memorizzare nella cache i file CRL
Speech SDK usa i file CRL per controllare la certificazione. La memorizzazione nella cache dei file CRL fino alla scadenza consente di evitare di scaricare i file CRL ogni volta. Per informazioni dettagliate, vedere Come configurare OpenSSL per Linux.
Usare Speech SDK più recente
Continuiamo a migliorare le prestazioni dell'SDK Voce, provare quindi a usare quello più recente nell'applicazione.
Linee guida per i test di carico
È possibile usare il test di carico per testare la capacità e la latenza del servizio di sintesi vocale. Ecco alcune linee guida:
- Il servizio di sintesi vocale ha la possibilità di ridimensionare automaticamente, ma richiede tempo per aumentare il numero di istanze. Se la concorrenza viene aumentata in breve tempo, il client potrebbe ottenere una latenza
429
o un codice di errore lungo (troppe richieste). È quindi consigliabile aumentare la concorrenza passo dopo passo nel test di carico. Per altri dettagli, vedere questo articolo , in particolare questo esempio di modelli di carico di lavoro. - È possibile usare l'esempio usando il pool di oggetti (C# e Java) per il test di carico e ottenere i numeri di latenza. È possibile modificare i turni di test e la concorrenza nell'esempio per soddisfare la concorrenza di destinazione.
- Il servizio presenta una limitazione della quota in base al traffico reale, pertanto, se si vuole eseguire test di carico con la concorrenza superiore al traffico reale, connettersi prima del test.
Passaggi successivi
- Vedere gli esempi in GitHub
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per