Share via


Kortare svarstid för talsyntes med hjälp av Tal-SDK

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

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

Svarstid beskrivning SpeechSynthesisResult-egenskapsnyckel
svarstid för första byte Anger tidsfördröjningen mellan starten av syntesaktiviteten och mottagandet av den första delen av ljuddata. SpeechServiceResponse_SynthesisFirstByteLatencyMs
slutför svarstid Anger tidsfördröjningen mellan starten av syntesaktiviteten och mottagandet av hela syntetiserade ljuddata. SpeechServiceResponse_SynthesisFinishLatencyMs

Speech SDK placerar svarstidsvaraktigheterna i samlingen SpeechSynthesisResultEgenskaper för . 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 ljudsegmentet 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 egenskapspåsen 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 ljudsegmentet 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 egenskapspåsen 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 ljudsegmentet 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 egenskapspåsen 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 Egenskapsnyckeln SPXSpeechSynthesisResult
first byte latency Anger tidsfördröjningen mellan syntesen startar och det första ljudsegmentet 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 egenskapspåsen 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 bytefördröjningen är i de flesta fall lägre än svarstiden för slut. Den första bytefördröjningen är oberoende av textlängd, medan svarstiden för slut ökar med textlängd.

Helst vill vi minimera svarstiden för användaranvändarna (svarstiden innan användaren hör ljudet) till en restid för nätverksvägen plus den första svarstiden för ljudsegmentet i talsyntestjänsten.

Strömning

Direktuppspelning är avgörande för att minska svarstiden. Klientkoden kan starta uppspelningen när det första ljudsegmentet tas emot. I ett tjänstscenario kan du vidarebefordra ljudsegment direkt till dina klienter, i stället för att vänta på hela ljudet.

Du kan använda PullAudioOutputStreamhändelsen , PushAudioOutputStreamSynthesizing och AudioDataStream Speech SDK för att aktivera strömning.

Ta AudioDataStream som 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 PullAudioOutputStreamhändelsen , PushAudioOutputStreamSynthesizing och AudioDataStream Speech SDK för att aktivera strömning.

Ta AudioDataStream som 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 PullAudioOutputStreamhändelsen , PushAudioOutputStreamSynthesizing och AudioDataStream Speech SDK för att aktivera strömning.

Ta AudioDataStream som 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 PullAudioOutputStreamhändelsen , PushAudioOutputStreamSynthesizing och AudioDataStream Speech SDK för att aktivera strömning.

Ta AudioDataStream som 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 SPXPullAudioOutputStreamhändelsen , SPXPushAudioOutputStreamSynthesizing och SPXAudioDataStream Speech SDK för att aktivera strömning.

Ta AudioDataStream som 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öransluta 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 restid (RTT). Om anslutningen har upprättats nyligen inkluderar 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 och återanvänder SpeechSynthesizer.

Föranslutning

För att ansluta i förväg upprättar du en anslutning till Speech-tjänsten när du vet att anslutningen behövs snart. Om du till exempel skapar en talrobot i klienten kan du föransluta till talsyntestjänsten när användaren börjar prata och anropa SpeakTextAsync när robotens svarstext ä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];

Kommentar

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

Återanvända SpeechSynthesizer

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

Överföra komprimerat ljud via nätverket

När nätverket är instabilt eller med begränsad bandbredd påverkar nyttolaststorleken också svarstiden. Samtidigt 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 opus, webm, mp3, silkoch så vidare, se den fullständiga listan i SpeechSynthesisOutputFormat. Till exempel är bithastigheten Riff24Khz16BitMonoPcm för formatet 384 kbps, medan Audio24Khz48KBitRateMonoMp3 endast kostar 48 kbps. Vårt Speech SDK använder automatiskt ett komprimerat format för överföring när ett pcm utdataformat har angetts. För Linux och Windows GStreamer krävs för att aktivera den här funktionen. Se den här instruktionen för att installera och konfigurera GStreamer för Speech SDK. För Android, iOS och macOS behövs ingen extra konfiguration från och med version 1.20.

Andra tips

Cachelagrade CRL-filer

Speech SDK använder CRL-filer för att kontrollera certifieringen. Cachelagring CRL-filerna tills de har upphört att gälla kan du undvika att ladda ned CRL-filer varje gång. Mer information finns i Så här konfigurerar du OpenSSL för Linux.

Använda senaste Speech SDK

Vi förbättrar hela tiden prestanda för Tal-SDK, så försök att använda den senaste Tal-SDK-versionen i ditt program.

Läs in testguiden

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 autoskala, 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 , särskilt det här exemplet på arbetsbelastningsmönster.
  • Du kan använda vårt exempel med hjälp av objektpoolen (C# och Java) för belastningstest och för att hämta svarstidsnumren. Du kan ändra testsvängarna och samtidigheten i exemplet för att uppfylla målets samtidighet.
  • Tjänsten har en kvotbegränsning baserat på den verkliga trafiken, och om du vill utföra belastningstest med samtidigheten högre än din verkliga trafik ansluter du före testet.

Nästa steg