你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

快速入门:创建实时分割聚类

参考文档 | 包 (NuGet) | GitHub 上的其他示例

在本快速入门中,你将运行一个应用程序,以便通过实时分割聚类进行语音转文本听录。 分割聚类用于区分参与对话的不同说话人。 语音服务提供有关哪个说话人正在说出转录语音的特定部分的信息。

说话人信息包含在说话人 ID 字段的结果中。 说话人 ID 是服务在从所提供的音频内容中识别不同说话人时分配给每个会话参与者的通用标识符。

提示

可以在 Speech Studio 中试用实时语音转文本,且无需注册或编写任何代码。 但是,Speech Studio 尚不支持分割聚类。

先决条件

设置环境

语音 SDK 以 NuGet 包的形式提供并实现了 .NET Standard 2.0。 本指南的后面部分会安装语音 SDK,但先请查看 SDK 安装指南以了解更多要求。

设置环境变量。

需要对应用程序进行身份验证才能访问 Azure AI 服务。 本文介绍如何使用环境变量来存储凭据。 然后,你可以从代码访问环境变量来验证应用程序。 对于生产环境,请使用更安全的方式来存储和访问凭据。

重要

我们建议使用 Azure 资源的托管标识进行 Microsoft Entra ID 身份验证,以避免将凭据随云中运行的应用程序一起存储。

如果使用 API 密钥,请将其安全地存储在其他某个位置,例如 Azure 密钥保管库中。 请不要直接在代码中包含 API 密钥,并且切勿公开发布该密钥。

有关 Azure AI 服务安全性的详细信息,请参阅对 Azure AI 服务的请求进行身份验证

若要为语音资源密钥和区域设置环境变量,请打开控制台窗口,并按照操作系统和开发环境的说明进行操作。

  • 要设置 SPEECH_KEY 环境变量,请将“your-key”替换为你的资源的某一个密钥。
  • 要设置 SPEECH_REGION 环境变量,请将 “your-region”替换为你的资源的某一个地区。
setx SPEECH_KEY your-key
setx SPEECH_REGION your-region

注意

如果你只需要访问当前控制台中的环境变量,可使用 set(而不是 setx)来设置环境变量。

添加环境变量后,你可能需要重启任何需要读取环境变量的程序(包括控制台窗口)。 例如,如果使用 Visual Studio 作为编辑器,请在运行示例之前重启 Visual Studio。

使用对话听录对文件实施分割聚类

按照以下步骤创建控制台应用程序并安装语音 SDK。

  1. 在需要新项目的文件夹中打开命令提示符窗口。 运行以下命令,使用 .NET CLI 创建控制台应用程序。

    dotnet new console
    

    该命令会在你的项目目录中创建 Program.cs 文件。

  2. 使用 .NET CLI 在新项目中安装语音 SDK。

    dotnet add package Microsoft.CognitiveServices.Speech
    
  3. Program.cs 的内容替换为以下代码。

    using Microsoft.CognitiveServices.Speech;
    using Microsoft.CognitiveServices.Speech.Audio;
    using Microsoft.CognitiveServices.Speech.Transcription;
    
    class Program 
    {
        // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
        static string speechKey = Environment.GetEnvironmentVariable("SPEECH_KEY");
        static string speechRegion = Environment.GetEnvironmentVariable("SPEECH_REGION");
    
        async static Task Main(string[] args)
        {
            var filepath = "katiesteve.wav";
            var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);        
            speechConfig.SpeechRecognitionLanguage = "en-US";
            speechConfig.SetProperty(PropertyId.SpeechServiceResponse_DiarizeIntermediateResults, "true"); 
    
            var stopRecognition = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
    
            // Create an audio stream from a wav file or from the default microphone
            using (var audioConfig = AudioConfig.FromWavFileInput(filepath))
            {
                // Create a conversation transcriber using audio stream input
                using (var conversationTranscriber = new ConversationTranscriber(speechConfig, audioConfig))
                {
                    conversationTranscriber.Transcribing += (s, e) =>
                    {
                        Console.WriteLine($"TRANSCRIBING: Text={e.Result.Text} Speaker ID={e.Result.SpeakerId}");
                    };
    
                    conversationTranscriber.Transcribed += (s, e) =>
                    {
                        if (e.Result.Reason == ResultReason.RecognizedSpeech)
                        {
                            Console.WriteLine();
                            Console.WriteLine($"TRANSCRIBED: Text={e.Result.Text} Speaker ID={e.Result.SpeakerId}");
                            Console.WriteLine();
                        }
                        else if (e.Result.Reason == ResultReason.NoMatch)
                        {
                            Console.WriteLine($"NOMATCH: Speech could not be transcribed.");
                        }
                    };
    
                    conversationTranscriber.Canceled += (s, e) =>
                    {
                        Console.WriteLine($"CANCELED: Reason={e.Reason}");
    
                        if (e.Reason == CancellationReason.Error)
                        {
                            Console.WriteLine($"CANCELED: ErrorCode={e.ErrorCode}");
                            Console.WriteLine($"CANCELED: ErrorDetails={e.ErrorDetails}");
                            Console.WriteLine($"CANCELED: Did you set the speech resource key and region values?");
                            stopRecognition.TrySetResult(0);
                        }
    
                        stopRecognition.TrySetResult(0);
                    };
    
                    conversationTranscriber.SessionStopped += (s, e) =>
                    {
                        Console.WriteLine("\n    Session stopped event.");
                        stopRecognition.TrySetResult(0);
                    };
    
                    await conversationTranscriber.StartTranscribingAsync();
    
                    // Waits for completion. Use Task.WaitAny to keep the task rooted.
                    Task.WaitAny(new[] { stopRecognition.Task });
    
                    await conversationTranscriber.StopTranscribingAsync();
                }
            }
        }
    }
    
  4. 获取示例音频文件或使用自己的 .wav 文件。 将 katiesteve.wav 替换为 .wav 文件的路径和名称。

    应用程序识别对话中多个参与者的语音。 你的音频文件应包含多个说话人。

  5. 若要更改语音识别语言,请将 en-US 替换为其他支持的语言。 例如,es-ES 代表西班牙语(西班牙)。 如果未指定语言,则默认语言为 en-US。 若要详细了解如何从多种使用的语言中进行识别,请参阅语言识别

  6. 运行控制台应用程序以开始对话听录:

    dotnet run
    

重要

请确保设置 SPEECH_KEYSPEECH_REGION 环境变量。 如果未设置这些变量,示例会失败并显示错误消息。

转录的对话应以文本格式输出:

TRANSCRIBING: Text=good morning steve Speaker ID=Unknown
TRANSCRIBING: Text=good morning steve how are Speaker ID=Guest-1
TRANSCRIBING: Text=good morning steve how are you doing today Speaker ID=Guest-1

TRANSCRIBED: Text=Good morning, Steve. How are you doing today? Speaker ID=Guest-1

TRANSCRIBING: Text=good morning katie Speaker ID=Unknown
TRANSCRIBING: Text=good morning katie i hope Speaker ID=Guest-2
TRANSCRIBING: Text=good morning katie i hope you're having a great Speaker ID=Guest-2
TRANSCRIBING: Text=good morning katie i hope you're having a great start to Speaker ID=Guest-2
TRANSCRIBING: Text=good morning katie i hope you're having a great start to your day Speaker ID=Guest-2

TRANSCRIBED: Text=Good morning, Katie. I hope you're having a great start to your day. Speaker ID=Guest-2

TRANSCRIBING: Text=have you tried Speaker ID=Unknown
TRANSCRIBING: Text=have you tried the latest Speaker ID=Unknown
TRANSCRIBING: Text=have you tried the latest real time Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what in Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what in real time Speaker ID=Guest-1

TRANSCRIBED: Text=Have you tried the latest real time diarization in Microsoft Speech Service which can tell you who said what in real time? Speaker ID=Guest-1

TRANSCRIBING: Text=not yet Speaker ID=Unknown
TRANSCRIBING: Text=not yet i Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch trans Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization Speaker ID=Guest-2  
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization function Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produc Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces di Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature Speaker ID=Guest-2  
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to di Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize in real Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize in real time Speaker ID=Guest-2

TRANSCRIBED: Text=Not yet. I've been using the batch transcription with diarization functionality, but it produces diarization results after the whole audio is processed. Is the new feature able to diarize in real time? Speaker ID=Guest-2

TRANSCRIBING: Text=absolutely Speaker ID=Unknown
TRANSCRIBING: Text=absolutely i Speaker ID=Unknown
TRANSCRIBING: Text=absolutely i recom Speaker ID=Guest-1
TRANSCRIBING: Text=absolutely i recommend Speaker ID=Guest-1
TRANSCRIBING: Text=absolutely i recommend you give it a try Speaker ID=Guest-1

TRANSCRIBED: Text=Absolutely, I recommend you give it a try. Speaker ID=Guest-1

TRANSCRIBING: Text=that's exc Speaker ID=Unknown
TRANSCRIBING: Text=that's exciting Speaker ID=Unknown
TRANSCRIBING: Text=that's exciting let me try Speaker ID=Guest-2
TRANSCRIBING: Text=that's exciting let me try it right now Speaker ID=Guest-2

TRANSCRIBED: Text=That's exciting. Let me try it right now. Speaker ID=Guest-2

说话人被标识为 Guest-1、Guest-2 等,具体取决于对话中的说话人数量。

注意

当尚未识别说话人时,你可能会在一些早期中间结果中看到 Speaker ID=Unknown。 如果没有中间分割结果(如果未将 PropertyId.SpeechServiceResponse_DiarizeIntermediateResults 属性设置为“true”),则说话人 ID 始终为“未知”。

清理资源

可以使用 Azure 门户Azure 命令行接口 (CLI) 删除创建的语音资源。

参考文档 | 包 (NuGet) | GitHub 上的其他示例

在本快速入门中,你将运行一个应用程序,以便通过实时分割聚类进行语音转文本听录。 分割聚类用于区分参与对话的不同说话人。 语音服务提供有关哪个说话人正在说出转录语音的特定部分的信息。

说话人信息包含在说话人 ID 字段的结果中。 说话人 ID 是服务在从所提供的音频内容中识别不同说话人时分配给每个会话参与者的通用标识符。

提示

可以在 Speech Studio 中试用实时语音转文本,且无需注册或编写任何代码。 但是,Speech Studio 尚不支持分割聚类。

先决条件

设置环境

语音 SDK 以 NuGet 包的形式提供并实现了 .NET Standard 2.0。 本指南的后面部分会安装语音 SDK,但先请查看 SDK 安装指南以了解更多要求。

设置环境变量。

需要对应用程序进行身份验证才能访问 Azure AI 服务。 本文介绍如何使用环境变量来存储凭据。 然后,你可以从代码访问环境变量来验证应用程序。 对于生产环境,请使用更安全的方式来存储和访问凭据。

重要

我们建议使用 Azure 资源的托管标识进行 Microsoft Entra ID 身份验证,以避免将凭据随云中运行的应用程序一起存储。

如果使用 API 密钥,请将其安全地存储在其他某个位置,例如 Azure 密钥保管库中。 请不要直接在代码中包含 API 密钥,并且切勿公开发布该密钥。

有关 Azure AI 服务安全性的详细信息,请参阅对 Azure AI 服务的请求进行身份验证

若要为语音资源密钥和区域设置环境变量,请打开控制台窗口,并按照操作系统和开发环境的说明进行操作。

  • 要设置 SPEECH_KEY 环境变量,请将“your-key”替换为你的资源的某一个密钥。
  • 要设置 SPEECH_REGION 环境变量,请将 “your-region”替换为你的资源的某一个地区。
setx SPEECH_KEY your-key
setx SPEECH_REGION your-region

注意

如果你只需要访问当前控制台中的环境变量,可使用 set(而不是 setx)来设置环境变量。

添加环境变量后,你可能需要重启任何需要读取环境变量的程序(包括控制台窗口)。 例如,如果使用 Visual Studio 作为编辑器,请在运行示例之前重启 Visual Studio。

使用对话听录对文件实施分割聚类

按照以下步骤创建控制台应用程序并安装语音 SDK。

  1. Visual Studio Community 2022 中新建一个名为 ConversationTranscription 的 C++ 控制台项目。

  2. 选择“工具”>“NuGet 包管理器”>“包管理器控制台”。 在包管理器控制台中,运行此命令:

    Install-Package Microsoft.CognitiveServices.Speech
    
  3. ConversationTranscription.cpp 的内容替换为以下代码。

    #include <iostream> 
    #include <stdlib.h>
    #include <speechapi_cxx.h>
    #include <future>
    
    using namespace Microsoft::CognitiveServices::Speech;
    using namespace Microsoft::CognitiveServices::Speech::Audio;
    using namespace Microsoft::CognitiveServices::Speech::Transcription;
    
    std::string GetEnvironmentVariable(const char* name);
    
    int main()
    {
        // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
        auto speechKey = GetEnvironmentVariable("SPEECH_KEY");
        auto speechRegion = GetEnvironmentVariable("SPEECH_REGION");
    
        if ((size(speechKey) == 0) || (size(speechRegion) == 0)) {
            std::cout << "Please set both SPEECH_KEY and SPEECH_REGION environment variables." << std::endl;
            return -1;
        }
    
        auto speechConfig = SpeechConfig::FromSubscription(speechKey, speechRegion);
        speechConfig->SetProperty(PropertyId::SpeechServiceResponse_DiarizeIntermediateResults, "true"); 
    
        speechConfig->SetSpeechRecognitionLanguage("en-US");
    
        auto audioConfig = AudioConfig::FromWavFileInput("katiesteve.wav");
        auto conversationTranscriber = ConversationTranscriber::FromConfig(speechConfig, audioConfig);
    
        // promise for synchronization of recognition end.
        std::promise<void> recognitionEnd;
    
        // Subscribes to events.
        conversationTranscriber->Transcribing.Connect([](const ConversationTranscriptionEventArgs& e)
            {
                std::cout << "TRANSCRIBING:" << e.Result->Text << std::endl;
                std::cout << "Speaker ID=" << e.Result->SpeakerId << std::endl;
            });
    
        conversationTranscriber->Transcribed.Connect([](const ConversationTranscriptionEventArgs& e)
            {
                if (e.Result->Reason == ResultReason::RecognizedSpeech)
                {
                    std::cout << "\n" << "TRANSCRIBED: Text=" << e.Result->Text << std::endl;
                    std::cout << "Speaker ID=" << e.Result->SpeakerId << "\n" << std::endl;
                }
                else if (e.Result->Reason == ResultReason::NoMatch)
                {
                    std::cout << "NOMATCH: Speech could not be transcribed." << std::endl;
                }
            });
    
        conversationTranscriber->Canceled.Connect([&recognitionEnd](const ConversationTranscriptionCanceledEventArgs& e)
            {
                auto cancellation = CancellationDetails::FromResult(e.Result);
                std::cout << "CANCELED: Reason=" << (int)cancellation->Reason << std::endl;
    
                if (cancellation->Reason == CancellationReason::Error)
                {
                    std::cout << "CANCELED: ErrorCode=" << (int)cancellation->ErrorCode << std::endl;
                    std::cout << "CANCELED: ErrorDetails=" << cancellation->ErrorDetails << std::endl;
                    std::cout << "CANCELED: Did you set the speech resource key and region values?" << std::endl;
                }
                else if (cancellation->Reason == CancellationReason::EndOfStream)
                {
                    std::cout << "CANCELED: Reach the end of the file." << std::endl;
                }
            });
    
        conversationTranscriber->SessionStopped.Connect([&recognitionEnd](const SessionEventArgs& e)
            {
                std::cout << "Session stopped.";
                recognitionEnd.set_value(); // Notify to stop recognition.
            });
    
        conversationTranscriber->StartTranscribingAsync().wait();
    
        // Waits for recognition end.
        recognitionEnd.get_future().wait();
    
        conversationTranscriber->StopTranscribingAsync().wait();
    }
    
    std::string GetEnvironmentVariable(const char* name)
    {
    #if defined(_MSC_VER)
        size_t requiredSize = 0;
        (void)getenv_s(&requiredSize, nullptr, 0, name);
        if (requiredSize == 0)
        {
            return "";
        }
        auto buffer = std::make_unique<char[]>(requiredSize);
        (void)getenv_s(&requiredSize, buffer.get(), requiredSize, name);
        return buffer.get();
    #else
        auto value = getenv(name);
        return value ? value : "";
    #endif
    }
    
  4. 获取示例音频文件或使用自己的 .wav 文件。 将 katiesteve.wav 替换为 .wav 文件的路径和名称。

    应用程序识别对话中多个参与者的语音。 你的音频文件应包含多个说话人。

  5. 若要更改语音识别语言,请将 en-US 替换为其他支持的语言。 例如,es-ES 代表西班牙语(西班牙)。 如果未指定语言,则默认语言为 en-US。 若要详细了解如何从多种使用的语言中进行识别,请参阅语言识别

  6. 构建并运行你的应用程序以开始对话听录:

    重要

    请确保设置 SPEECH_KEYSPEECH_REGION 环境变量。 如果未设置这些变量,示例会失败并显示错误消息。

转录的对话应以文本格式输出:

TRANSCRIBING:good morning
Speaker ID=Unknown
TRANSCRIBING:good morning steve
Speaker ID=Unknown
TRANSCRIBING:good morning steve how are you doing
Speaker ID=Guest-1
TRANSCRIBING:good morning steve how are you doing today
Speaker ID=Guest-1

TRANSCRIBED: Text=Good morning, Steve. How are you doing today?
Speaker ID=Guest-1

TRANSCRIBING:good
Speaker ID=Unknown
TRANSCRIBING:good morning
Speaker ID=Unknown
TRANSCRIBING:good morning kat
Speaker ID=Unknown
TRANSCRIBING:good morning katie i hope you're having a
Speaker ID=Guest-2
TRANSCRIBING:good morning katie i hope you're having a great start to your day
Speaker ID=Guest-2

TRANSCRIBED: Text=Good morning, Katie. I hope you're having a great start to your day.
Speaker ID=Guest-2

TRANSCRIBING:have you
Speaker ID=Unknown
TRANSCRIBING:have you tried
Speaker ID=Unknown
TRANSCRIBING:have you tried the latest
Speaker ID=Unknown
TRANSCRIBING:have you tried the latest real
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech service
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech service which
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech service which can
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech service which can tell you
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech service which can tell you who said
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech service which can tell you who said what
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech service which can tell you who said what in
Speaker ID=Guest-1
TRANSCRIBING:have you tried the latest real time diarization in microsoft speech service which can tell you who said what in real time
Speaker ID=Guest-1

TRANSCRIBED: Text=Have you tried the latest real time diarization in Microsoft Speech Service which can tell you who said what in real time?
Speaker ID=Guest-1

TRANSCRIBING:not yet
Speaker ID=Unknown
TRANSCRIBING:not yet i
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch trans
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization function
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces di
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to di
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize in real
Speaker ID=Guest-2
TRANSCRIBING:not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize in real time
Speaker ID=Guest-2

TRANSCRIBED: Text=Not yet. I've been using the batch transcription with diarization functionality, but it produces diarization results after the whole audio is processed. Is the new feature able to diarize in real time?
Speaker ID=Guest-2

TRANSCRIBING:absolutely
Speaker ID=Unknown
TRANSCRIBING:absolutely i
Speaker ID=Unknown
TRANSCRIBING:absolutely i recom
Speaker ID=Guest-1
TRANSCRIBING:absolutely i recommend
Speaker ID=Guest-1
TRANSCRIBING:absolutely i recommend you
Speaker ID=Guest-1
TRANSCRIBING:absolutely i recommend you give it a try
Speaker ID=Guest-1

TRANSCRIBED: Text=Absolutely, I recommend you give it a try.
Speaker ID=Guest-1

TRANSCRIBING:that's exc
Speaker ID=Unknown
TRANSCRIBING:that's exciting
Speaker ID=Unknown
TRANSCRIBING:that's exciting let me
Speaker ID=Guest-2
TRANSCRIBING:that's exciting let me try
Speaker ID=Guest-2
TRANSCRIBING:that's exciting let me try it right now
Speaker ID=Guest-2

TRANSCRIBED: Text=That's exciting. Let me try it right now.
Speaker ID=Guest-2

说话人被标识为 Guest-1、Guest-2 等,具体取决于对话中的说话人数量。

注意

当尚未识别说话人时,你可能会在一些早期中间结果中看到 Speaker ID=Unknown。 如果没有中间分割结果(如果未将 PropertyId::SpeechServiceResponse_DiarizeIntermediateResults 属性设置为“true”),则说话人 ID 始终为“未知”。

清理资源

可以使用 Azure 门户Azure 命令行接口 (CLI) 删除创建的语音资源。

参考文档 | 包 (Go) | GitHub 上的其他示例

Go 编程语言的语音 SDK 不支持对话听录。 选择其他编程语言,或本文开头链接的 Go 参考和示例。

参考文档 | GitHub 上的其他示例

在本快速入门中,你将运行一个应用程序,以便通过实时分割聚类进行语音转文本听录。 分割聚类用于区分参与对话的不同说话人。 语音服务提供有关哪个说话人正在说出转录语音的特定部分的信息。

说话人信息包含在说话人 ID 字段的结果中。 说话人 ID 是服务在从所提供的音频内容中识别不同说话人时分配给每个会话参与者的通用标识符。

提示

可以在 Speech Studio 中试用实时语音转文本,且无需注册或编写任何代码。 但是,Speech Studio 尚不支持分割聚类。

先决条件

设置环境

若要设置环境,请安装语音 SDK。 本快速入门中的示例适用于 Java 运行时

  1. 安装 Apache Maven。 然后运行 mvn -v 以确认安装成功。

  2. 在项目的根目录中创建一个新的 pom.xml 文件,并将以下内容复制到该文件中:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.microsoft.cognitiveservices.speech.samples</groupId>
        <artifactId>quickstart-eclipse</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <build>
            <sourceDirectory>src</sourceDirectory>
            <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                <source>1.8</source>
                <target>1.8</target>
                </configuration>
            </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
            <groupId>com.microsoft.cognitiveservices.speech</groupId>
            <artifactId>client-sdk</artifactId>
            <version>1.40.0</version>
            </dependency>
        </dependencies>
    </project>
    
  3. 安装语音 SDK 和依赖项。

    mvn clean dependency:copy-dependencies
    

设置环境变量。

需要对应用程序进行身份验证才能访问 Azure AI 服务。 本文介绍如何使用环境变量来存储凭据。 然后,你可以从代码访问环境变量来验证应用程序。 对于生产环境,请使用更安全的方式来存储和访问凭据。

重要

我们建议使用 Azure 资源的托管标识进行 Microsoft Entra ID 身份验证,以避免将凭据随云中运行的应用程序一起存储。

如果使用 API 密钥,请将其安全地存储在其他某个位置,例如 Azure 密钥保管库中。 请不要直接在代码中包含 API 密钥,并且切勿公开发布该密钥。

有关 Azure AI 服务安全性的详细信息,请参阅对 Azure AI 服务的请求进行身份验证

若要为语音资源密钥和区域设置环境变量,请打开控制台窗口,并按照操作系统和开发环境的说明进行操作。

  • 要设置 SPEECH_KEY 环境变量,请将“your-key”替换为你的资源的某一个密钥。
  • 要设置 SPEECH_REGION 环境变量,请将 “your-region”替换为你的资源的某一个地区。
setx SPEECH_KEY your-key
setx SPEECH_REGION your-region

注意

如果你只需要访问当前控制台中的环境变量,可使用 set(而不是 setx)来设置环境变量。

添加环境变量后,你可能需要重启任何需要读取环境变量的程序(包括控制台窗口)。 例如,如果使用 Visual Studio 作为编辑器,请在运行示例之前重启 Visual Studio。

使用对话听录对文件实施分割聚类

按照以下步骤创建用于对话听录的控制台应用程序。

  1. 在同一项目根目录中创建一个名为 ConversationTranscription.java 的新文件。

  2. 将以下代码复制到 ConversationTranscription.java 中:

    import com.microsoft.cognitiveservices.speech.*;
    import com.microsoft.cognitiveservices.speech.audio.AudioConfig;
    import com.microsoft.cognitiveservices.speech.transcription.*;
    
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    
    public class ConversationTranscription {
        // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
        private static String speechKey = System.getenv("SPEECH_KEY");
        private static String speechRegion = System.getenv("SPEECH_REGION");
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
    
            SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion);
            speechConfig.setSpeechRecognitionLanguage("en-US");
            AudioConfig audioInput = AudioConfig.fromWavFileInput("katiesteve.wav");
            speechConfig.setProperty(PropertyId.SpeechServiceResponse_DiarizeIntermediateResults, "true");
    
            Semaphore stopRecognitionSemaphore = new Semaphore(0);
    
            ConversationTranscriber conversationTranscriber = new ConversationTranscriber(speechConfig, audioInput);
            {
                // Subscribes to events.
                conversationTranscriber.transcribing.addEventListener((s, e) -> {
                    System.out.println("TRANSCRIBING: Text=" + e.getResult().getText() + " Speaker ID=" + e.getResult().getSpeakerId() );
                });
    
                conversationTranscriber.transcribed.addEventListener((s, e) -> {
                    if (e.getResult().getReason() == ResultReason.RecognizedSpeech) {
                        System.out.println();
                        System.out.println("TRANSCRIBED: Text=" + e.getResult().getText() + " Speaker ID=" + e.getResult().getSpeakerId() );
                        System.out.println();
                    }
                    else if (e.getResult().getReason() == ResultReason.NoMatch) {
                        System.out.println("NOMATCH: Speech could not be transcribed.");
                    }
                });
    
                conversationTranscriber.canceled.addEventListener((s, e) -> {
                    System.out.println("CANCELED: Reason=" + e.getReason());
    
                    if (e.getReason() == CancellationReason.Error) {
                        System.out.println("CANCELED: ErrorCode=" + e.getErrorCode());
                        System.out.println("CANCELED: ErrorDetails=" + e.getErrorDetails());
                        System.out.println("CANCELED: Did you update the subscription info?");
                    }
    
                    stopRecognitionSemaphore.release();
                });
    
                conversationTranscriber.sessionStarted.addEventListener((s, e) -> {
                    System.out.println("\n    Session started event.");
                });
    
                conversationTranscriber.sessionStopped.addEventListener((s, e) -> {
                    System.out.println("\n    Session stopped event.");
                });
    
                conversationTranscriber.startTranscribingAsync().get();
    
                // Waits for completion.
                stopRecognitionSemaphore.acquire();
    
                conversationTranscriber.stopTranscribingAsync().get();
            }
    
            speechConfig.close();
            audioInput.close();
            conversationTranscriber.close();
    
            System.exit(0);
        }
    }
    
  3. 获取示例音频文件或使用自己的 .wav 文件。 将 katiesteve.wav 替换为 .wav 文件的路径和名称。

    应用程序识别对话中多个参与者的语音。 你的音频文件应包含多个说话人。

  4. 若要更改语音识别语言,请将 en-US 替换为其他支持的语言。 例如,es-ES 代表西班牙语(西班牙)。 如果未指定语言,则默认语言为 en-US。 若要详细了解如何从多种使用的语言中进行识别,请参阅语言识别

  5. 运行新的控制台应用程序以开始对话听录:

    javac ConversationTranscription.java -cp ".;target\dependency\*"
    java -cp ".;target\dependency\*" ConversationTranscription
    

重要

请确保设置 SPEECH_KEYSPEECH_REGION 环境变量。 如果未设置这些变量,示例会失败并显示错误消息。

转录的对话应以文本格式输出:

TRANSCRIBING: Text=good morning Speaker ID=Unknown
TRANSCRIBING: Text=good morning steve Speaker ID=Unknown
TRANSCRIBING: Text=good morning steve how Speaker ID=Guest-1
TRANSCRIBING: Text=good morning steve how are you doing Speaker ID=Guest-1
TRANSCRIBING: Text=good morning steve how are you doing today Speaker ID=Guest-1

TRANSCRIBED: Text=Good morning, Steve. How are you doing today? Speaker ID=Guest-1

TRANSCRIBING: Text=good morning katie i hope Speaker ID=Guest-2
TRANSCRIBING: Text=good morning katie i hope you're having a Speaker ID=Guest-2
TRANSCRIBING: Text=good morning katie i hope you're having a great Speaker ID=Guest-2
TRANSCRIBING: Text=good morning katie i hope you're having a great start to Speaker ID=Guest-2
TRANSCRIBING: Text=good morning katie i hope you're having a great start to your day Speaker ID=Guest-2

TRANSCRIBED: Text=Good morning, Katie. I hope you're having a great start to your day. Speaker ID=Guest-2

TRANSCRIBING: Text=have you tried Speaker ID=Unknown
TRANSCRIBING: Text=have you tried the latest Speaker ID=Unknown
TRANSCRIBING: Text=have you tried the latest real Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what in Speaker ID=Guest-1
TRANSCRIBING: Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what in real time Speaker ID=Guest-1

TRANSCRIBED: Text=Have you tried the latest real time diarization in Microsoft Speech Service which can tell you who said what in real time? Speaker ID=Guest-1

TRANSCRIBING: Text=not yet Speaker ID=Unknown
TRANSCRIBING: Text=not yet i Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch trans Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization function Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces di Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to di Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize in real Speaker ID=Guest-2
TRANSCRIBING: Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize in real time Speaker ID=Guest-2

TRANSCRIBED: Text=Not yet. I've been using the batch transcription with diarization functionality, but it produces diarization results after the whole audio is processed. Is the new feature able to diarize in real time? Speaker ID=Guest-2

TRANSCRIBING: Text=absolutely Speaker ID=Unknown
TRANSCRIBING: Text=absolutely i recom Speaker ID=Guest-1
TRANSCRIBING: Text=absolutely i recommend Speaker ID=Guest-1
TRANSCRIBING: Text=absolutely i recommend you Speaker ID=Guest-1
TRANSCRIBING: Text=absolutely i recommend you give it a try Speaker ID=Guest-1

TRANSCRIBED: Text=Absolutely, I recommend you give it a try. Speaker ID=Guest-1

TRANSCRIBING: Text=that's exc Speaker ID=Unknown
TRANSCRIBING: Text=that's exciting Speaker ID=Unknown
TRANSCRIBING: Text=that's exciting let me try Speaker ID=Guest-2
TRANSCRIBING: Text=that's exciting let me try it right now Speaker ID=Guest-2

TRANSCRIBED: Text=That's exciting. Let me try it right now. Speaker ID=Guest-2

说话人被标识为 Guest-1、Guest-2 等,具体取决于对话中的说话人数量。

注意

当尚未识别说话人时,你可能会在一些早期中间结果中看到 Speaker ID=Unknown。 如果没有中间分割结果(如果未将 PropertyId.SpeechServiceResponse_DiarizeIntermediateResults 属性设置为“true”),则说话人 ID 始终为“未知”。

清理资源

可以使用 Azure 门户Azure 命令行接口 (CLI) 删除创建的语音资源。

参考文档 | 包 (npm) | GitHub 上的其他示例 | 库源代码

在本快速入门中,你将运行一个应用程序,以便通过实时分割聚类进行语音转文本听录。 分割聚类用于区分参与对话的不同说话人。 语音服务提供有关哪个说话人正在说出转录语音的特定部分的信息。

说话人信息包含在说话人 ID 字段的结果中。 说话人 ID 是服务在从所提供的音频内容中识别不同说话人时分配给每个会话参与者的通用标识符。

提示

可以在 Speech Studio 中试用实时语音转文本,且无需注册或编写任何代码。 但是,Speech Studio 尚不支持分割聚类。

先决条件

设置环境

如要设置环境,请安装适用于 JavaScript 的语音 SDK。 如果只是需要用于安装的包名称,请运行 npm install microsoft-cognitiveservices-speech-sdk。 有关安装说明指南,请参阅 SDK 安装指南

设置环境变量。

需要对应用程序进行身份验证才能访问 Azure AI 服务。 本文介绍如何使用环境变量来存储凭据。 然后,你可以从代码访问环境变量来验证应用程序。 对于生产环境,请使用更安全的方式来存储和访问凭据。

重要

我们建议使用 Azure 资源的托管标识进行 Microsoft Entra ID 身份验证,以避免将凭据随云中运行的应用程序一起存储。

如果使用 API 密钥,请将其安全地存储在其他某个位置,例如 Azure 密钥保管库中。 请不要直接在代码中包含 API 密钥,并且切勿公开发布该密钥。

有关 Azure AI 服务安全性的详细信息,请参阅对 Azure AI 服务的请求进行身份验证

若要为语音资源密钥和区域设置环境变量,请打开控制台窗口,并按照操作系统和开发环境的说明进行操作。

  • 要设置 SPEECH_KEY 环境变量,请将“your-key”替换为你的资源的某一个密钥。
  • 要设置 SPEECH_REGION 环境变量,请将 “your-region”替换为你的资源的某一个地区。
setx SPEECH_KEY your-key
setx SPEECH_REGION your-region

注意

如果你只需要访问当前控制台中的环境变量,可使用 set(而不是 setx)来设置环境变量。

添加环境变量后,你可能需要重启任何需要读取环境变量的程序(包括控制台窗口)。 例如,如果使用 Visual Studio 作为编辑器,请在运行示例之前重启 Visual Studio。

使用对话听录对文件实施分割聚类

按照以下步骤创建用于对话转录的新控制台应用程序。

  1. 在需要新项目的地方打开命令提示符窗口,并新建名为 ConversationTranscription.js 的文件。

  2. 安装适用于 JavaScript 的语音 SDK:

    npm install microsoft-cognitiveservices-speech-sdk
    
  3. 将以下代码复制到 ConversationTranscription.js 中:

    const fs = require("fs");
    const sdk = require("microsoft-cognitiveservices-speech-sdk");
    
    // This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
    const speechConfig = sdk.SpeechConfig.fromSubscription(process.env.SPEECH_KEY, process.env.SPEECH_REGION);
    
    function fromFile() {
        const filename = "katiesteve.wav";
    
        let audioConfig = sdk.AudioConfig.fromWavFileInput(fs.readFileSync(filename));
        let conversationTranscriber = new sdk.ConversationTranscriber(speechConfig, audioConfig);
    
        var pushStream = sdk.AudioInputStream.createPushStream();
    
        fs.createReadStream(filename).on('data', function(arrayBuffer) {
            pushStream.write(arrayBuffer.slice());
        }).on('end', function() {
            pushStream.close();
        });
    
        console.log("Transcribing from: " + filename);
    
        conversationTranscriber.sessionStarted = function(s, e) {
            console.log("SessionStarted event");
            console.log("SessionId:" + e.sessionId);
        };
        conversationTranscriber.sessionStopped = function(s, e) {
            console.log("SessionStopped event");
            console.log("SessionId:" + e.sessionId);
            conversationTranscriber.stopTranscribingAsync();
        };
        conversationTranscriber.canceled = function(s, e) {
            console.log("Canceled event");
            console.log(e.errorDetails);
            conversationTranscriber.stopTranscribingAsync();
        };
        conversationTranscriber.transcribed = function(s, e) {
            console.log("TRANSCRIBED: Text=" + e.result.text + " Speaker ID=" + e.result.speakerId);
        };
    
        // Start conversation transcription
        conversationTranscriber.startTranscribingAsync(
            function () {},
            function (err) {
                console.trace("err - starting transcription: " + err);
            }
        );
    
    }
    fromFile();
    
  4. 获取示例音频文件或使用自己的 .wav 文件。 将 katiesteve.wav 替换为 .wav 文件的路径和名称。

    应用程序识别对话中多个参与者的语音。 你的音频文件应包含多个说话人。

  5. 若要更改语音识别语言,请将 en-US 替换为其他支持的语言。 例如,es-ES 代表西班牙语(西班牙)。 如果未指定语言,则默认语言为 en-US。 若要详细了解如何从多种使用的语言中进行识别,请参阅语言识别

  6. 运行新的控制台应用程序,从文件开始进行语音识别:

    node.exe ConversationTranscription.js
    

重要

请确保设置 SPEECH_KEYSPEECH_REGION 环境变量。 如果未设置这些变量,示例会失败并显示错误消息。

转录的对话应以文本格式输出:

SessionStarted event
SessionId:E87AFBA483C2481985F6C9AF719F616B
TRANSCRIBED: Text=Good morning, Steve. Speaker ID=Unknown
TRANSCRIBED: Text=Good morning, Katie. Speaker ID=Unknown
TRANSCRIBED: Text=Have you tried the latest real time diarization in Microsoft Speech Service which can tell you who said what in real time? Speaker ID=Guest-1
TRANSCRIBED: Text=Not yet. I've been using the batch transcription with diarization functionality, but it produces diarization result until whole audio get processed. Speaker ID=Guest-2
TRANSCRIBED: Text=Is the new feature can diarize in real time? Speaker ID=Guest-2
TRANSCRIBED: Text=Absolutely. Speaker ID=Guest-1
TRANSCRIBED: Text=That's exciting. Let me try it right now. Speaker ID=Guest-2
Canceled event
undefined
SessionStopped event
SessionId:E87AFBA483C2481985F6C9AF719F616B

说话人被标识为 Guest-1、Guest-2 等,具体取决于对话中的说话人数量。

清理资源

可以使用 Azure 门户Azure 命令行接口 (CLI) 删除创建的语音资源。

参考文档 | 包(下载) | GitHub 上的其他示例

适用于 Objective-C 的语音 SDK 确实支持对话听录,但我们尚未提供有关此内容的指南。 请选择其他编程语言开始了解相关概念,或参阅本文开头链接的 Objective-C 引用和示例。

参考文档 | 包(下载) | GitHub 上的其他示例

适用于 Swift 的语音 SDK 确实支持对话听录,但我们尚未提供有关此内容的指南。 请选择其他编程语言开始了解相关概念,或参阅本文开头链接的 Swift 引用和示例。

参考文档 | 包 (PyPi) | GitHub 上的其他示例

在本快速入门中,你将运行一个应用程序,以便通过实时分割聚类进行语音转文本听录。 分割聚类用于区分参与对话的不同说话人。 语音服务提供有关哪个说话人正在说出转录语音的特定部分的信息。

说话人信息包含在说话人 ID 字段的结果中。 说话人 ID 是服务在从所提供的音频内容中识别不同说话人时分配给每个会话参与者的通用标识符。

提示

可以在 Speech Studio 中试用实时语音转文本,且无需注册或编写任何代码。 但是,Speech Studio 尚不支持分割聚类。

先决条件

设置环境

适用于 Python 的语音 SDK 可用作 Python 包索引 (PyPI) 模块。 适用于 Python 的语音 SDK 与 Windows、Linux 和 macOS 兼容。

安装 3.7 或更高版本的 Python。 首先请查看 SDK 安装指南以了解更多要求。

设置环境变量。

需要对应用程序进行身份验证才能访问 Azure AI 服务。 本文介绍如何使用环境变量来存储凭据。 然后,你可以从代码访问环境变量来验证应用程序。 对于生产环境,请使用更安全的方式来存储和访问凭据。

重要

我们建议使用 Azure 资源的托管标识进行 Microsoft Entra ID 身份验证,以避免将凭据随云中运行的应用程序一起存储。

如果使用 API 密钥,请将其安全地存储在其他某个位置,例如 Azure 密钥保管库中。 请不要直接在代码中包含 API 密钥,并且切勿公开发布该密钥。

有关 Azure AI 服务安全性的详细信息,请参阅对 Azure AI 服务的请求进行身份验证

若要为语音资源密钥和区域设置环境变量,请打开控制台窗口,并按照操作系统和开发环境的说明进行操作。

  • 要设置 SPEECH_KEY 环境变量,请将“your-key”替换为你的资源的某一个密钥。
  • 要设置 SPEECH_REGION 环境变量,请将 “your-region”替换为你的资源的某一个地区。
setx SPEECH_KEY your-key
setx SPEECH_REGION your-region

注意

如果你只需要访问当前控制台中的环境变量,可使用 set(而不是 setx)来设置环境变量。

添加环境变量后,你可能需要重启任何需要读取环境变量的程序(包括控制台窗口)。 例如,如果使用 Visual Studio 作为编辑器,请在运行示例之前重启 Visual Studio。

使用对话听录对文件实施分割聚类

按照以下步骤创建新的控制台应用程序。

  1. 在需要新项目的地方打开命令提示符窗口,并新建名为 conversation_transcription.py 的文件。

  2. 运行此命令以安装语音 SDK:

    pip install azure-cognitiveservices-speech
    
  3. 将以下代码复制到 conversation_transcription.py 中:

    import os
    import time
    import azure.cognitiveservices.speech as speechsdk
    
    def conversation_transcriber_recognition_canceled_cb(evt: speechsdk.SessionEventArgs):
        print('Canceled event')
    
    def conversation_transcriber_session_stopped_cb(evt: speechsdk.SessionEventArgs):
        print('SessionStopped event')
    
    def conversation_transcriber_transcribed_cb(evt: speechsdk.SpeechRecognitionEventArgs):
        print('\nTRANSCRIBED:')
        if evt.result.reason == speechsdk.ResultReason.RecognizedSpeech:
            print('\tText={}'.format(evt.result.text))
            print('\tSpeaker ID={}\n'.format(evt.result.speaker_id))
        elif evt.result.reason == speechsdk.ResultReason.NoMatch:
            print('\tNOMATCH: Speech could not be TRANSCRIBED: {}'.format(evt.result.no_match_details))
    
    def conversation_transcriber_transcribing_cb(evt: speechsdk.SpeechRecognitionEventArgs):
        print('TRANSCRIBING:')
        print('\tText={}'.format(evt.result.text))
        print('\tSpeaker ID={}'.format(evt.result.speaker_id))
    
    def conversation_transcriber_session_started_cb(evt: speechsdk.SessionEventArgs):
        print('SessionStarted event')
    
    def recognize_from_file():
        # This example requires environment variables named "SPEECH_KEY" and "SPEECH_REGION"
        speech_config = speechsdk.SpeechConfig(subscription=os.environ.get('SPEECH_KEY'), region=os.environ.get('SPEECH_REGION'))
        speech_config.speech_recognition_language="en-US"
        speech_config.set_property(property_id=speechsdk.PropertyId.SpeechServiceResponse_DiarizeIntermediateResults, value='true')
    
        audio_config = speechsdk.audio.AudioConfig(filename="katiesteve.wav")
        conversation_transcriber = speechsdk.transcription.ConversationTranscriber(speech_config=speech_config, audio_config=audio_config)
    
        transcribing_stop = False
    
        def stop_cb(evt: speechsdk.SessionEventArgs):
            #"""callback that signals to stop continuous recognition upon receiving an event `evt`"""
            print('CLOSING on {}'.format(evt))
            nonlocal transcribing_stop
            transcribing_stop = True
    
        # Connect callbacks to the events fired by the conversation transcriber
        conversation_transcriber.transcribed.connect(conversation_transcriber_transcribed_cb)
        conversation_transcriber.transcribing.connect(conversation_transcriber_transcribing_cb)
        conversation_transcriber.session_started.connect(conversation_transcriber_session_started_cb)
        conversation_transcriber.session_stopped.connect(conversation_transcriber_session_stopped_cb)
        conversation_transcriber.canceled.connect(conversation_transcriber_recognition_canceled_cb)
        # stop transcribing on either session stopped or canceled events
        conversation_transcriber.session_stopped.connect(stop_cb)
        conversation_transcriber.canceled.connect(stop_cb)
    
        conversation_transcriber.start_transcribing_async()
    
        # Waits for completion.
        while not transcribing_stop:
            time.sleep(.5)
    
        conversation_transcriber.stop_transcribing_async()
    
    # Main
    
    try:
        recognize_from_file()
    except Exception as err:
        print("Encountered exception. {}".format(err))
    
  4. 获取示例音频文件或使用自己的 .wav 文件。 将 katiesteve.wav 替换为 .wav 文件的路径和名称。

    应用程序识别对话中多个参与者的语音。 你的音频文件应包含多个说话人。

  5. 若要更改语音识别语言,请将 en-US 替换为其他支持的语言。 例如,es-ES 代表西班牙语(西班牙)。 如果未指定语言,则默认语言为 en-US。 若要详细了解如何从多种使用的语言中进行识别,请参阅语言识别

  6. 运行新的控制台应用程序以开始对话听录:

    python conversation_transcription.py
    

重要

请确保设置 SPEECH_KEYSPEECH_REGION 环境变量。 如果未设置这些变量,示例会失败并显示错误消息。

转录的对话应以文本格式输出:

TRANSCRIBING:
        Text=good morning
        Speaker ID=Unknown
TRANSCRIBING:
        Text=good morning steve
        Speaker ID=Unknown
TRANSCRIBING:
        Text=good morning steve how are
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=good morning steve how are you doing today
        Speaker ID=Guest-1

TRANSCRIBED:
        Text=Good morning, Steve. How are you doing today?
        Speaker ID=Guest-1

TRANSCRIBING:
        Text=good morning katie
        Speaker ID=Unknown
TRANSCRIBING:
        Text=good morning katie i hope you're having a
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=good morning katie i hope you're having a great start to
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=good morning katie i hope you're having a great start to your day
        Speaker ID=Guest-2

TRANSCRIBED:
        Text=Good morning, Katie. I hope you're having a great start to your day.
        Speaker ID=Guest-2

TRANSCRIBING:
        Text=have you
        Speaker ID=Unknown
TRANSCRIBING:
        Text=have you tried
        Speaker ID=Unknown
TRANSCRIBING:
        Text=have you tried the latest
        Speaker ID=Unknown
TRANSCRIBING:
        Text=have you tried the latest real
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech service
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech service which
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech service which can
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech service which can tell you
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said        
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what   
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what in
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=have you tried the latest real time diarization in microsoft speech service which can tell you who said what in real time
        Speaker ID=Guest-1

TRANSCRIBED:
        Text=Have you tried the latest real time diarization in Microsoft Speech Service which can tell you who said what in real time?
        Speaker ID=Guest-1

TRANSCRIBING:
        Text=not yet
        Speaker ID=Unknown
TRANSCRIBING:
        Text=not yet i
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch trans
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization function
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces di
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization     
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to di
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize in real
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=not yet i've been using the batch transcription with diarization functionality but it produces diarization results after the whole audio is processed is the new feature able to diarize in real time
        Speaker ID=Guest-2

TRANSCRIBED:
        Text=Not yet. I've been using the batch transcription with diarization functionality, but it produces diarization results after the whole audio is processed. Is the new feature able to diarize in real time?
        Speaker ID=Guest-2

TRANSCRIBING:
        Text=absolutely
        Speaker ID=Unknown
TRANSCRIBING:
        Text=absolutely i
        Speaker ID=Unknown
TRANSCRIBING:
        Text=absolutely i recom
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=absolutely i recommend
        Speaker ID=Guest-1
TRANSCRIBING:
        Text=absolutely i recommend you give it a try
        Speaker ID=Guest-1

TRANSCRIBED:
        Text=Absolutely, I recommend you give it a try.
        Speaker ID=Guest-1

TRANSCRIBING:
        Text=that's exc
        Speaker ID=Unknown
TRANSCRIBING:
        Text=that's exciting
        Speaker ID=Unknown
TRANSCRIBING:
        Text=that's exciting let me
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=that's exciting let me try
        Speaker ID=Guest-2
TRANSCRIBING:
        Text=that's exciting let me try it right now
        Speaker ID=Guest-2

TRANSCRIBED:
        Text=That's exciting. Let me try it right now.
        Speaker ID=Guest-2

说话人被标识为 Guest-1、Guest-2 等,具体取决于对话中的说话人数量。

注意

当尚未识别说话人时,你可能会在一些早期中间结果中看到 Speaker ID=Unknown。 如果没有中间分割结果(如果未将 PropertyId.SpeechServiceResponse_DiarizeIntermediateResults 属性设置为“true”),则说话人 ID 始终为“未知”。

清理资源

可以使用 Azure 门户Azure 命令行接口 (CLI) 删除创建的语音资源。

语音转文本 REST API 参考 | 适用于短音频的语音转文本 REST API 参考 | GitHub 上的其他示例

REST API 不支持对话听录。 请从此页顶部选择其他编程语言或工具。

语音 CLI 不支持对话听录。 请从此页顶部选择其他编程语言或工具。

下一步