Add conversation transcription samples with speaker diarization for C##3018
Conversation
There was a problem hiding this comment.
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
ConversationTranscriptionSampleswith 4 conversation transcription scenarios (mic, WAV file, language selection, push stream). - Added a new main-menu entry and submenu in
Program.csto invoke the new samples. - Updated both console
.csprojfiles 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"); |
There was a problem hiding this comment.
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.
| var config = SpeechConfig.FromSubscription("YourSubscriptionKey", "YourServiceRegion"); | |
| var config = SpeechConfig.FromEndpoint(new Uri("https://YourServiceRegion.api.cognitive.microsoft.com"), "YourSubscriptionKey"); |
| // 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"); |
There was a problem hiding this comment.
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.
| // 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"); |
| // 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"); |
There was a problem hiding this comment.
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.
| // 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"); |
| // 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"); |
There was a problem hiding this comment.
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.
| // 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"); |
| // Waits for completion. Use Task.WaitAny to keep the task rooted. | ||
| Task.WaitAny(new Task[] { stopRecognition.Task, Task.Run(() => Console.ReadKey()) }); | ||
|
|
There was a problem hiding this comment.
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.
| // 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); | |
| } |
| Console.WriteLine("Press any key to stop...\n"); | ||
|
|
||
| await transcriber.StartTranscribingAsync().ConfigureAwait(false); | ||
| Task.WaitAny(new Task[] { stopRecognition.Task, Task.Run(() => Console.ReadKey()) }); |
There was a problem hiding this comment.
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.
| 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); | |
| } |
Summary
Add C# samples for real-time conversation transcription with speaker diarization using
ConversationTranscriberAPI.What's added
conversation_transcription_samples.cswith 4 sample methods:Program.cswith menu entry for the new samples.csprojfiles to include the new source fileMotivation
The
samples/csharp/console application includesSpeechRecognizersamples (no speaker identification)and
RemoteMeetingSamples(complex async meeting API), but has noConversationTranscriberexamples.While a basic quickstart exists in
quickstart/csharp/dotnet/conversation-transcription/(single file-inputscenario), 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