# ISpeechDialogueSynthesizer

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/api/tracon.ispeechdialoguesynthesizer/
> Summary: ISpeechDialogueSynthesizer: A speech provider that voices a dialogue: an ordered list of turns, each spoken by its own voice, in one request and one audio result.

<div class="api-provenance">Namespace Tracon · Assembly <code>Tracon.Abstractions.dll</code></div>

A speech provider that voices a dialogue: an ordered list of turns, each spoken by its
own voice, in one request and one audio result.

```csharp
public interface ISpeechDialogueSynthesizer
```

## Remarks

A capability next to [ISpeechSynthesizer](/api/tracon.ispeechsynthesizer/), not a part of it: a provider
that speaks one voice per request implements no dialogue member. The same instance
implements both interfaces, and it is registered as an [ISpeechSynthesizer](/api/tracon.ispeechsynthesizer/)
(the unnamed default, or by name with `AddSpeechSynthesizer`). It is not
registered as [ISpeechDialogueSynthesizer](/api/tracon.ispeechdialoguesynthesizer/): a caller takes the capability
from [ISpeechProviderResolver.GetDialogueSynthesizerAsync](/api/tracon.ispeechproviderresolver/#Tracon_ISpeechProviderResolver_GetDialogueSynthesizerAsync_System_String_System_Threading_CancellationToken_), which applies
the tenant's checks first.

**Splitting is the caller's job.** A request that exceeds
[ISpeechDialogueSynthesizer.DialogueCapabilities](/api/tracon.ispeechdialoguesynthesizer/#Tracon_ISpeechDialogueSynthesizer_DialogueCapabilities) is refused before the service is called; the
implementation never splits or truncates a dialogue. The caller plans its requests from
[SpeechDialogueCapabilities.MaxVoices](/api/tracon.speechdialoguecapabilities/#Tracon_SpeechDialogueCapabilities_MaxVoices) and
[SpeechDialogueCapabilities.MaxCharactersPerRequest](/api/tracon.speechdialoguecapabilities/#Tracon_SpeechDialogueCapabilities_MaxCharactersPerRequest), and joins the audio
itself.

**DI lifetime — singleton.** The capability lives on the synthesizer
instance, which is a container singleton; it holds no per-call state.

**Tenant behavior — TENANT-INDEPENDENT implementation, tenant-gated calls.**
The instance never reads the tenant. [ISpeechProviderResolver](/api/tracon.ispeechproviderresolver/) applies the
tenant's egress policy to [ISpeechDialogueSynthesizer.ProviderName](/api/tracon.ispeechdialoguesynthesizer/#Tracon_ISpeechDialogueSynthesizer_ProviderName) and passes the tenant's own
credential in [SpeechDialogueRequest.Credential](/api/tracon.speechdialoguerequest/#Tracon_SpeechDialogueRequest_Credential), only to an
implementation whose [ISpeechDialogueSynthesizer.SupportsTenantCredentials](/api/tracon.ispeechdialoguesynthesizer/#Tracon_ISpeechDialogueSynthesizer_SupportsTenantCredentials) is [true](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool).

**Delivery:** no delivery guarantee applies. One call is one request to
the provider; it is not retried here, and a failed call produces no audio.

A workflow function node that voices two turns with the default synthesizer:

```csharp
tracon.AddWorkflowFunction<List<ChatMessage>, List<ChatMessage>>(
    "two-voices",
    provider =>
    {
        var speech = provider.GetRequiredService<ISpeechProviderResolver>();

        return async (messages, context, cancellationToken) =>
        {
            var dialogue = await speech.GetDialogueSynthesizerAsync(cancellationToken: cancellationToken);
            var result = await dialogue.SynthesizeDialogueAsync(
                new SpeechDialogueRequest
                {
                    Turns =
                    [
                        new SpeechDialogueTurn { Text = "Welcome back.", VoiceId = "host-voice" },
                        new SpeechDialogueTurn { Text = "Glad to be here.", VoiceId = "guest-voice" },
                    ],
                    IncludeTimestamps = true,
                },
                cancellationToken);

            var timing = new List<string>();

            foreach (var segment in result.Segments ?? [])
            {
                timing.Add($"turn {segment.TurnIndex}: {segment.Start} - {segment.End}");
            }

            return [new ChatMessage(ChatRole.Assistant, string.Join(", ", timing))];
        };
    });
```

## Properties

### <a id="Tracon_ISpeechDialogueSynthesizer_DialogueCapabilities"></a> DialogueCapabilities

Gets the limits of one dialogue request.

```csharp
SpeechDialogueCapabilities DialogueCapabilities { get; }
```

#### Property Value

 [SpeechDialogueCapabilities](/api/tracon.speechdialoguecapabilities/)

### <a id="Tracon_ISpeechDialogueSynthesizer_ProviderName"></a> ProviderName

The provider name. Used in cost records and in the tenant's checks.

```csharp
string ProviderName { get; }
```

#### Property Value

 [string](https://learn.microsoft.com/dotnet/api/system.string)

#### Remarks

A tenant's egress policy and provider bindings name this value, not the name the
synthesizer was registered under.

### <a id="Tracon_ISpeechDialogueSynthesizer_SupportsTenantCredentials"></a> SupportsTenantCredentials

Gets whether the implementation honours a tenant credential passed in
[SpeechDialogueRequest.Credential](/api/tracon.speechdialoguerequest/#Tracon_SpeechDialogueRequest_Credential).

```csharp
bool SupportsTenantCredentials { get; }
```

#### Property Value

 [bool](https://learn.microsoft.com/dotnet/api/system.boolean)

#### Remarks

The default is [false](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool). Tracon then refuses a dialogue for a tenant
that has its own binding for [ISpeechDialogueSynthesizer.ProviderName](/api/tracon.ispeechdialoguesynthesizer/#Tracon_ISpeechDialogueSynthesizer_ProviderName) rather than make it on the
configured credential, which would bill the wrong account. An implementation that
returns [true](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool) uses the credential for the call it came with and
never falls back to its configured one.

## Methods

### <a id="Tracon_ISpeechDialogueSynthesizer_SynthesizeDialogueAsync_Tracon_SpeechDialogueRequest_System_Threading_CancellationToken_"></a> SynthesizeDialogueAsync\(SpeechDialogueRequest, CancellationToken\)

Voices a dialogue.

```csharp
ValueTask<SpeechDialogueAudio> SynthesizeDialogueAsync(SpeechDialogueRequest request, CancellationToken cancellationToken = default)
```

#### Parameters

`request` [SpeechDialogueRequest](/api/tracon.speechdialoguerequest/)

The turns and the settings.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[SpeechDialogueAudio](/api/tracon.speechdialogueaudio/)\>

The audio of the whole dialogue and, when requested, each turn's time range.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`request` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [TraconException](/api/tracon.traconexception/)

The request breaks a limit of [ISpeechDialogueSynthesizer.DialogueCapabilities](/api/tracon.ispeechdialoguesynthesizer/#Tracon_ISpeechDialogueSynthesizer_DialogueCapabilities), a turn has no text
or no voice, a provider setting is unknown or has the wrong type, or the provider
answered with an error. The service is not called for the first three. The message
names the limit or the key, never a turn's text or a setting's value.

 [NotSupportedException](https://learn.microsoft.com/dotnet/api/system.notsupportedexception)

[SpeechDialogueRequest.Credential](/api/tracon.speechdialoguerequest/#Tracon_SpeechDialogueRequest_Credential) is set and
[ISpeechDialogueSynthesizer.SupportsTenantCredentials](/api/tracon.ispeechdialoguesynthesizer/#Tracon_ISpeechDialogueSynthesizer_SupportsTenantCredentials) is [false](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool).
