Skip to content

Add conversation transcription samples with speaker diarization for C##3018

Open
TheMysteriousStranger90 wants to merge 1 commit into
Azure-Samples:masterfrom
TheMysteriousStranger90:TheMysteriousStranger90/detect-speakers
Open

Add conversation transcription samples with speaker diarization for C##3018
TheMysteriousStranger90 wants to merge 1 commit into
Azure-Samples:masterfrom
TheMysteriousStranger90:TheMysteriousStranger90/detect-speakers

Conversation

@TheMysteriousStranger90

Copy link
Copy Markdown

Summary

Add C# samples for real-time conversation transcription with speaker diarization using ConversationTranscriber API.

What's added

  • New file: conversation_transcription_samples.cs with 4 sample methods:
    1. Conversation transcription from microphone
    2. Conversation transcription from WAV file
    3. Conversation transcription with specified language
    4. Conversation transcription with push audio stream
  • Updated Program.cs with menu entry for the new samples
  • Updated both .csproj files to include the new source file

Motivation

The samples/csharp/ console application includes SpeechRecognizer samples (no speaker identification)
and RemoteMeetingSamples (complex async meeting API), but has no ConversationTranscriber examples.
While a basic quickstart exists in quickstart/csharp/dotnet/conversation-transcription/ (single file-input
scenario), the main samples console app lacks coverage of this API. This PR adds 4 common scenarios
(microphone, WAV file, language selection, push stream) with automatic speaker diarization (Guest-1, Guest-2, etc.)
directly into the samples console app menu.

Tested

  • All 4 methods tested with Speech SDK 1.48.1
  • Microphone methods correctly identify multiple speakers in real-time
  • File and push stream methods work with existing sample WAV files

Copilot AI review requested due to automatic review settings April 3, 2026 10:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new C# console-app samples demonstrating real-time conversation transcription with speaker diarization via the ConversationTranscriber API, and wires them into the existing sample menu.

Changes:

  • Added ConversationTranscriptionSamples with 4 conversation transcription scenarios (mic, WAV file, language selection, push stream).
  • Added a new main-menu entry and submenu in Program.cs to invoke the new samples.
  • Updated both console .csproj files to compile/link the new shared sample source.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
samples/csharp/sharedcontent/console/Program.cs Adds a new top-level menu option and submenu to run the conversation transcription samples.
samples/csharp/sharedcontent/console/conversation_transcription_samples.cs Introduces 4 new ConversationTranscriber sample methods, including microphone, file, language, and push-stream scenarios.
samples/csharp/dotnetcore/console/samples/samples.csproj Links the new shared sample source file into the .NET (net8.0) console project.
samples/csharp/dotnet-windows/console/samples/samples.csproj Links the new shared sample source file into the .NET Framework (net462) console project.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// <conversationFromMicrophone>
// Creates an instance of a speech config with specified subscription key and region.
// Replace with your own subscription key and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion");

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sample uses SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion"), but the rest of the console samples consistently use SpeechConfig.FromEndpoint(new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"), "YourSubscriptionKey") (e.g., sharedcontent/console/speech_recognition_samples.cs:28). Consider switching to FromEndpoint here as well so developers can copy/paste the same credential pattern across samples.

Suggested change
var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion");
var config = SpeechConfig.FromEndpoint(new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"), "YourSubscriptionKey");

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +96
// Creates an instance of a speech config with specified subscription key and region.
// Replace with your own subscription key and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion");

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sample uses SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion"), but the rest of the console samples consistently use SpeechConfig.FromEndpoint(new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"), "YourSubscriptionKey") (e.g., sharedcontent/console/speech_recognition_samples.cs:28). Consider switching to FromEndpoint here as well so developers can copy/paste the same credential pattern across samples.

Suggested change
// Creates an instance of a speech config with specified subscription key and region.
// Replace with your own subscription key and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion");
// Creates an instance of a speech config with the specified endpoint and subscription key.
// Replace with your own endpoint (e.g., "https://westus.api.cognitive.microsoft.com") and subscription key.
var config = SpeechConfig.FromEndpoint(new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"), "YourSubscriptionKey");

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +156
// Creates an instance of a speech config with specified subscription key and region.
// Replace with your own subscription key and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion");

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sample uses SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion"), but the rest of the console samples consistently use SpeechConfig.FromEndpoint(new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"), "YourSubscriptionKey") (e.g., sharedcontent/console/speech_recognition_samples.cs:28). Consider switching to FromEndpoint here as well so developers can copy/paste the same credential pattern across samples.

Suggested change
// Creates an instance of a speech config with specified subscription key and region.
// Replace with your own subscription key and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion");
// Creates an instance of a speech config with specified endpoint and subscription key.
// Replace with your own endpoint (e.g., "https://westus.api.cognitive.microsoft.com") and subscription key.
var config = SpeechConfig.FromEndpoint(new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"), "YourSubscriptionKey");

Copilot uses AI. Check for mistakes.
Comment on lines +218 to +220
// Creates an instance of a speech config with specified subscription key and region.
// Replace with your own subscription key and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion");

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sample uses SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion"), but the rest of the console samples consistently use SpeechConfig.FromEndpoint(new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"), "YourSubscriptionKey") (e.g., sharedcontent/console/speech_recognition_samples.cs:28). Consider switching to FromEndpoint here as well so developers can copy/paste the same credential pattern across samples.

Suggested change
// Creates an instance of a speech config with specified subscription key and region.
// Replace with your own subscription key and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion");
// Creates an instance of a speech config with specified endpoint and subscription key.
// Replace with your own endpoint and subscription key.
var config = SpeechConfig.FromEndpoint(
new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"),
"YourSubscriptionKey");

Copilot uses AI. Check for mistakes.
Comment on lines +80 to +82
// Waits for completion. Use Task.WaitAny to keep the task rooted.
Task.WaitAny(new Task[] { stopRecognition.Task, Task.Run(() => Console.ReadKey()) });

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Task.Run(() => Console.ReadKey()) is started here but never cancelled if stopRecognition.Task completes first (e.g., on cancellation/session stop). That background ReadKey can consume the next keypress intended for the menu, leading to confusing input behavior. Consider using a synchronous Console.ReadKey() stop mechanism (like other samples) or restructure with a key task that is safely drained/ignored without leaving a pending read on the console input buffer.

Suggested change
// Waits for completion. Use Task.WaitAny to keep the task rooted.
Task.WaitAny(new Task[] { stopRecognition.Task, Task.Run(() => Console.ReadKey()) });
// Waits for completion without leaving a background Console.ReadKey pending.
while (!stopRecognition.Task.IsCompleted)
{
if (Console.KeyAvailable)
{
Console.ReadKey(true);
break;
}
await Task.WhenAny(stopRecognition.Task, Task.Delay(100)).ConfigureAwait(false);
}

Copilot uses AI. Check for mistakes.
Console.WriteLine("Press any key to stop...\n");

await transcriber.StartTranscribingAsync().ConfigureAwait(false);
Task.WaitAny(new Task[] { stopRecognition.Task, Task.Run(() => Console.ReadKey()) });

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Task.Run(() => Console.ReadKey()) is started here but never cancelled if stopRecognition.Task completes first (e.g., on cancellation/session stop). That background ReadKey can consume the next keypress intended for the menu, leading to confusing input behavior. Consider using a synchronous Console.ReadKey() stop mechanism (like other samples) or restructure with a key task that is safely drained/ignored without leaving a pending read on the console input buffer.

Suggested change
Task.WaitAny(new Task[] { stopRecognition.Task, Task.Run(() => Console.ReadKey()) });
while (!stopRecognition.Task.IsCompleted)
{
if (Console.KeyAvailable)
{
Console.ReadKey(true);
break;
}
await Task.Delay(50).ConfigureAwait(false);
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants