次の方法で共有


クイック スタート: リアルタイムでの会話の文字起こしのマルチチャンネル ダイアライゼーション (プレビュー)

Note

現在、この機能はパブリック プレビュー段階にあります。 このプレビュー版はサービス レベル アグリーメントなしで提供されています。運用環境のワークロードに使用することはお勧めできません。 特定の機能はサポート対象ではなく、機能が制限されることがあります。 詳しくは、Microsoft Azure プレビューの追加使用条件に関するページをご覧ください。

会話の文字起こしのマルチチャンネル ダイアライゼーションを使用すると、音声を Speech サービスにストリーミングすることによって、複数の参加者を追加、削除、識別する機能を使用して、会議を文字起こしできます。 まず、REST API を使用して各参加者の音声署名を作成し、次に、それらの音声署名を Speech SDK で使用して会議を文字起こしします。 詳細については、会話の文字起こしの概要に関するページを参照してください。

重要

会話の文字起こしのマルチチャンネル ダイアライゼーション (プレビュー) は、2025 年 3 月 28 日に廃止されます。 他の音声テキスト変換機能への移行の詳細については、「会話の文字起こしマルチチャンネル ダイアライゼーションから移行する」を参照してください。

制限事項

  • 次のサブスクリプション リージョンでのみ使用できます: centraluseastasiaeastuswesteurope
  • 7 つのマイクの循環マルチマイク配列が必要です。 このマイク配列は、Microsoft の仕様を満たす必要があります。

Note

会話の文字起こしのマルチチャンネル ダイアライゼーション機能では、ConversationTranscriber ではなく MeetingTranscriber を使用し、CreateConversationAsync の代わりに CreateMeetingAsync を使用します。

前提条件

  • Azure サブスクリプション。 無料で作成できます
  • Azure ポータルで、音声リソースを作成します
  • Speech リソース キーとリージョンを取得します。 音声リソースがデプロイされたら、[リソースに移動] を選択して、キーを表示および管理します。

環境をセットアップする

何らかの操作を行うには、事前に Speech SDK for JavaScript をインストールしておく必要があります。 パッケージ名のインストールだけが必要な場合は、npm install microsoft-cognitiveservices-speech-sdk を実行します。 詳しいインストール手順については、SDK のインストール ガイドを参照してください。

声紋を作成する

ユーザー プロファイルを登録する場合は、最初の手順で会議の参加者の声紋を作成して、一意の話者として識別できるようにします。 特定の参加者を識別するために、事前に登録したユーザー プロファイルを使用しない場合、これは必須ではありません。

声紋を作成するための入力 .wav 音声ファイルは、16 ビット、16 kHz のサンプル レート、およびシングル チャンネル (モノラル) 形式である必要があります。 各オーディオ サンプルの推奨される長さは、30 秒から 2 分です。 オーディオ サンプルが短すぎると、話者を認識するときの精度が低下します。 一意の音声プロファイルを作成するため、.wav ファイルは 1 人の音声のサンプルである必要があります。

次の例は、JavaScript で REST API を使用して声紋を作成する方法を示しています。 subscriptionKeyregion、サンプル .wav ファイルへのパスを挿入する必要があります。

const fs = require('fs');
const axios = require('axios');
const formData = require('form-data');
 
const subscriptionKey = 'your-subscription-key';
const region = 'your-region';
 
async function createProfile() {
    let form = new formData();
    form.append('file', fs.createReadStream('path-to-voice-sample.wav'));
    let headers = form.getHeaders();
    headers['Ocp-Apim-Subscription-Key'] = subscriptionKey;
 
    let url = `https://signature.${region}.cts.speech.microsoft.com/api/v1/Signature/GenerateVoiceSignatureFromFormData`;
    let response = await axios.post(url, form, { headers: headers });
    
    // get signature from response, serialize to json string
    return JSON.stringify(response.data.Signature);
}
 
async function main() {
    // use this voiceSignature string with meeting transcription calls below
    let voiceSignatureString = await createProfile();
    console.log(voiceSignatureString);
}
main();

このスクリプトを実行すると、voiceSignatureString 変数に声紋文字列が返されます。 この関数を 2 回実行して、下記の voiceSignatureStringUser1 および voiceSignatureStringUser2 変数への入力として使用する 2 つの文字列を作成します。

Note

声紋は、REST API を使用してのみ作成できます。

会議を文字起こしする

次のサンプル コードは、2 人の話者の会議をリアルタイムで文字起こしする方法を示しています。 上の手順に従って各話者の音声署名文字列が作成されていることを前提としています。 subscriptionKeyregion、および文字起こしする音声のパス filepath を、実際の情報に置き換えます。

事前登録されたユーザー プロファイルを使用しない場合、speaker1、speaker2 などとして不明なユーザーの最初の認識を完了するまでにさらに数秒かかります。

Note

署名の作成にアプリケーション全体で同じ subscriptionKey が使用されていることを確認してください。そうでないと、エラーが発生します。

このサンプル コードは、次の処理を実行します。

  • 文字起こしに使用するプッシュ ストリームを作成し、サンプル .wav ファイルをそれに書き込みます。
  • createMeetingAsync() を使用して Meeting を作成します。
  • コンストラクターを使用して MeetingTranscriber を作成します。
  • 会議に参加者を追加します。 上記の手順の出力として、文字列 voiceSignatureStringUser1voiceSignatureStringUser2 が得られます。
  • イベントに登録し、文字起こしを開始します。
  • 音声サンプルを提供せずに話者を区別したい場合は、会議の文字起こしの概要に関するページにあるように、DifferentiateGuestSpeakers 機能を有効にします。

話者の識別または区別が有効になっている場合は、既に transcribed 結果を受け取っている場合でも、サービスは蓄積されたオーディオ情報によってそれらを評価します。 サービスで、以前の結果に正しくない speakerId が割り当てられていることが検出された場合、ほぼ同じで speakerIdUtteranceId のみが異なる Transcribed 結果が再び送信されます。 UtteranceId の形式は {index}_{speakerId}_{Offset} であるため、transcribed 結果を受け取ると、UtteranceId を使用して、現在の transcribed 結果が前の結果を修正するかどうかを判断できます。 クライアントまたは UI ロジックで、以前の出力の上書きなどの動作を決定したり、最新の結果を無視したりできます。

(function() {
    "use strict";
    var sdk = require("microsoft-cognitiveservices-speech-sdk");
    var fs = require("fs");
    
    var subscriptionKey = "your-subscription-key";
    var region = "your-region";
    var filepath = "audio-file-to-transcribe.wav"; // 8-channel audio
    
    var speechTranslationConfig = sdk.SpeechTranslationConfig.fromSubscription(subscriptionKey, region);
    var audioConfig = sdk.AudioConfig.fromWavFileInput(fs.readFileSync(filepath));
    speechTranslationConfig.setProperty("ConversationTranscriptionInRoomAndOnline", "true");

    // en-us by default. Adding this code to specify other languages, like zh-cn.
    speechTranslationConfig.speechRecognitionLanguage = "en-US";
    
    // create meeting and transcriber
    var meeting = sdk.Meeting.createMeetingAsync(speechTranslationConfig, "myMeeting");
    var transcriber = new sdk.MeetingTranscriber(audioConfig);
    
    // attach the transcriber to the meeting
    transcriber.joinMeetingAsync(meeting,
    function () {
        // add first participant using voiceSignature created in enrollment step
        var user1 = sdk.Participant.From("user1@example.com", "en-us", voiceSignatureStringUser1);
        meeting.addParticipantAsync(user1,
        function () {
            // add second participant using voiceSignature created in enrollment step
            var user2 = sdk.Participant.From("user2@example.com", "en-us", voiceSignatureStringUser2);
            meeting.addParticipantAsync(user2,
            function () {
                transcriber.sessionStarted = function(s, e) {
                console.log("(sessionStarted)");
                };
                transcriber.sessionStopped = function(s, e) {
                console.log("(sessionStopped)");
                };
                transcriber.canceled = function(s, e) {
                console.log("(canceled)");
                };
                transcriber.transcribed = function(s, e) {
                console.log("(transcribed) text: " + e.result.text);
                console.log("(transcribed) speakerId: " + e.result.speakerId);
                };
    
                // begin meeting transcription
                transcriber.startTranscribingAsync(
                function () { },
                function (err) {
                    console.trace("err - starting transcription: " + err);
                });
        },
        function (err) {
            console.trace("err - adding user1: " + err);
        });
    },
    function (err) {
        console.trace("err - adding user2: " + err);
    });
    },
    function (err) {
    console.trace("err - " + err);
    });
}()); 

前提条件

  • Azure サブスクリプション。 無料で作成できます
  • Azure ポータルで、音声リソースを作成します
  • Speech リソース キーとリージョンを取得します。 音声リソースがデプロイされたら、[リソースに移動] を選択して、キーを表示および管理します。

環境をセットアップする

Speech SDK は NuGet パッケージとして提供されていて、.NET Standard 2.0 が実装されています。 Azure Cognitive Service for Speech SDK は、このガイドの後半でインストールしますが、まず、これ以上要件がないかプラットフォーム固有のインストール手順を確認してください。

声紋を作成する

ユーザー プロファイルを登録する場合は、最初の手順で会議の参加者の声紋を作成して、一意の話者として識別できるようにします。 特定の参加者を識別するために、事前に登録したユーザー プロファイルを使用しない場合、これは必須ではありません。

声紋を作成するための入力 .wav 音声ファイルは、16 ビット、16 kHz のサンプル レート、およびシングル チャンネル (モノラル) 形式である必要があります。 各オーディオ サンプルの推奨される長さは、30 秒から 2 分です。 オーディオ サンプルが短すぎると、話者を認識するときの精度が低下します。 一意の音声プロファイルを作成するため、.wav ファイルは 1 人の音声のサンプルである必要があります。

次の例は、C# で REST API を使用して音声署名を作成する方法を示しています。 subscriptionKeyregion、サンプル .wav ファイルへのパスを挿入する必要があります。

using System;
using System.IO;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Newtonsoft.Json;

[DataContract]
internal class VoiceSignature
{
    [DataMember]
    public string Status { get; private set; }

    [DataMember]
    public VoiceSignatureData Signature { get; private set; }

    [DataMember]
    public string Transcription { get; private set; }
}

[DataContract]
internal class VoiceSignatureData
{
    internal VoiceSignatureData()
    { }

    internal VoiceSignatureData(int version, string tag, string data)
    {
        this.Version = version;
        this.Tag = tag;
        this.Data = data;
    }

    [DataMember]
    public int Version { get; private set; }

    [DataMember]
    public string Tag { get; private set; }

    [DataMember]
    public string Data { get; private set; }
}

private static async Task<string> GetVoiceSignatureString()
{
    var subscriptionKey = "your-subscription-key";
    var region = "your-region";

    byte[] fileBytes = File.ReadAllBytes("path-to-voice-sample.wav");
    var content = new ByteArrayContent(fileBytes);
    var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
    var response = await client.PostAsync($"https://signature.{region}.cts.speech.microsoft.com/api/v1/Signature/GenerateVoiceSignatureFromByteArray", content);
    
    var jsonData = await response.Content.ReadAsStringAsync();
    var result = JsonConvert.DeserializeObject<VoiceSignature>(jsonData);
    return JsonConvert.SerializeObject(result.Signature);
}

関数 GetVoiceSignatureString() を実行すると、声紋文字列が正しい形式で返されます。 この関数を 2 回実行して、下記の voiceSignatureStringUser1 および voiceSignatureStringUser2 変数への入力として使用する 2 つの文字列を作成します。

Note

声紋は、REST API を使用してのみ作成できます。

会議を文字起こしする

次のサンプル コードは、2 人の話者の会議をリアルタイムで文字起こしする方法を示しています。 上の手順に従って各話者の音声署名文字列が作成されていることを前提としています。 subscriptionKeyregion、および文字起こしする音声のパス filepath を、実際の情報に置き換えます。

事前登録されたユーザー プロファイルを使用しない場合、speaker1、speaker2 などとして不明なユーザーの最初の認識を完了するまでにさらに数秒かかります。

Note

署名の作成にアプリケーション全体で同じ subscriptionKey が使用されていることを確認してください。そうでないと、エラーが発生します。

このサンプル コードは、次の処理を実行します。

  • 文字起こしするサンプル .wav ファイルから AudioConfig を作成します。
  • CreateMeetingAsync() を使用して Meeting を作成します。
  • コンストラクターを使用して MeetingTranscriber を作成し、必要なイベントにサブスクライブします。
  • 会議に参加者を追加します。 上記の手順の関数 GetVoiceSignatureString() の出力として、文字列 voiceSignatureStringUser1voiceSignatureStringUser2 が得られます。
  • 会議に参加し、文字起こしを開始します。
  • 音声サンプルを提供せずに話者を区別したい場合は、会議の文字起こしの概要に関するページにあるように、DifferentiateGuestSpeakers 機能を有効にします。

注意

AudioStreamReaderGitHub で取得できるヘルパー クラスです。

話者の識別または区別が有効になっている場合は、既に Transcribed 結果を受け取っている場合でも、サービスは蓄積されたオーディオ情報によってそれらを評価します。 サービスで、以前の結果に正しくない UserId が割り当てられていることが検出された場合、ほぼ同じで UserIdUtteranceId のみが異なる Transcribed 結果が再び送信されます。 UtteranceId の形式は {index}_{UserId}_{Offset} であるため、Transcribed 結果を受け取ると、UtteranceId を使用して、現在の Transcribed 結果が前の結果を修正するかどうかを判断できます。 クライアントまたは UI ロジックで、以前の出力の上書きなどの動作を決定したり、最新の結果を無視したりできます。

関数 TranscribeMeetingsAsync() を呼び出して、会議の文字起こしを開始します。

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;
using Microsoft.CognitiveServices.Speech.Transcription;

class TranscribeMeeting
{
    // all your other code

    public static async Task TranscribeMeetingsAsync(string voiceSignatureStringUser1, string voiceSignatureStringUser2)
    {
        var subscriptionKey = "your-subscription-key";
        var region = "your-region";
        var filepath = "audio-file-to-transcribe.wav";

        var config = SpeechConfig.FromSubscription(subscriptionKey, region);
        config.SetProperty("ConversationTranscriptionInRoomAndOnline", "true");

        // en-us by default. Adding this code to specify other languages, like zh-cn.
        // config.SpeechRecognitionLanguage = "zh-cn";
        var stopRecognition = new TaskCompletionSource<int>();

        using (var audioInput = AudioConfig.FromWavFileInput(filepath))
        {
            var meetingID = Guid.NewGuid().ToString();
            using (var meeting = await Meeting.CreateMeetingAsync(config, meetingID))
            {
                // create a meeting transcriber using audio stream input
                using (var meetingTranscriber = new MeetingTranscriber(audioInput))
                {
                    meetingTranscriber.Transcribing += (s, e) =>
                    {
                        Console.WriteLine($"TRANSCRIBING: Text={e.Result.Text} SpeakerId={e.Result.UserId}");
                    };

                    meetingTranscriber.Transcribed += (s, e) =>
                    {
                        if (e.Result.Reason == ResultReason.RecognizedSpeech)
                        {
                            Console.WriteLine($"TRANSCRIBED: Text={e.Result.Text} SpeakerId={e.Result.UserId}");
                        }
                        else if (e.Result.Reason == ResultReason.NoMatch)
                        {
                            Console.WriteLine($"NOMATCH: Speech could not be recognized.");
                        }
                    };

                    meetingTranscriber.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);
                        }
                    };

                    meetingTranscriber.SessionStarted += (s, e) =>
                    {
                        Console.WriteLine($"\nSession started event. SessionId={e.SessionId}");
                    };

                    meetingTranscriber.SessionStopped += (s, e) =>
                    {
                        Console.WriteLine($"\nSession stopped event. SessionId={e.SessionId}");
                        Console.WriteLine("\nStop recognition.");
                        stopRecognition.TrySetResult(0);
                    };

                    // Add participants to the meeting.
                    var speaker1 = Participant.From("User1", "en-US", voiceSignatureStringUser1);
                    var speaker2 = Participant.From("User2", "en-US", voiceSignatureStringUser2);
                    await meeting.AddParticipantAsync(speaker1);
                    await meeting.AddParticipantAsync(speaker2);

                    // Join to the meeting and start transcribing
                    await meetingTranscriber.JoinMeetingAsync(meeting);
                    await meetingTranscriber.StartTranscribingAsync().ConfigureAwait(false);

                    // waits for completion, then stop transcription
                    Task.WaitAny(new[] { stopRecognition.Task });
                    await meetingTranscriber.StopTranscribingAsync().ConfigureAwait(false);
                }
            }
        }
    }
}

前提条件

  • Azure サブスクリプション。 無料で作成できます
  • Azure ポータルで、音声リソースを作成します
  • Speech リソース キーとリージョンを取得します。 音声リソースがデプロイされたら、[リソースに移動] を選択して、キーを表示および管理します。

環境をセットアップする

何らかの操作を行う前に、Speech SDK for Python をインストールしてください。 pip install azure-cognitiveservices-speech を実行することで、PyPI から Speech SDK をインストールできます。

声紋を作成する

ユーザー プロファイルを登録する場合は、最初の手順で会議の参加者の声紋を作成して、一意の話者として識別できるようにします。 特定の参加者を識別するために、事前に登録したユーザー プロファイルを使用しない場合、これは必須ではありません。

声紋を作成するための入力 .wav 音声ファイルは、16 ビット、16 kHz のサンプル レート、およびシングル チャンネル (モノラル) 形式である必要があります。 各オーディオ サンプルの推奨される長さは、30 秒から 2 分です。 オーディオ サンプルが短すぎると、話者を認識するときの精度が低下します。 一意の音声プロファイルを作成するため、.wav ファイルは 1 人の音声のサンプルである必要があります。

次の例は、Python で REST API を使用して声紋を作成する方法を示しています。 subscriptionKeyregion、サンプル .wav ファイルへのパスを挿入する必要があります。

import requests
from scipy.io.wavfile import read
import json

speech_key, service_region = "your-subscription-key", "your-region"
endpoint = f"https://signature.{service_region}.cts.speech.microsoft.com/api/v1/Signature/GenerateVoiceSignatureFromByteArray"

#Enrollment audio for each speaker. In this example, two speaker enrollment audio files are added.
enrollment_audio_speaker1 = "enrollment-audio-speaker1.wav"
enrollment_audio_speaker2 = "enrollment-audio-speaker2.wav"

def voice_data_converter(enrollment_audio):
  with open(enrollment_audio, "rb") as wav_file:
    input_wav = wav_file.read()
  return input_wav
  
def voice_signature_creator(endpoint, speech_key, enrollment_audio):
  data = voice_data_converter(enrollment_audio)
  headers = {"Ocp-Apim-Subscription-Key":speech_key}
  r = requests.post(url = endpoint,headers = headers, data = data)
  voice_signature_string = json.dumps(r.json()['Signature'])
  return voice_signature_string

voice_signature_user1 = voice_signature_creator(endpoint, speech_key, enrollment_audio_speaker1)
voice_signature_user2 = voice_signature_creator(endpoint, speech_key, enrollment_audio_speaker2)

これら 2 つの voice_signature_string をサンプル コードで後で変数 voice_signature_user1voice_signature_user2 への入力として使用できます。

Note

声紋は、REST API を使用してのみ作成できます。

会議を文字起こしする

次のサンプル コードは、2 人の話者の会議をリアルタイムで文字起こしする方法を示しています。 前の手順に従って各話者の音声署名文字列が作成されていることを前提としています。 subscriptionKeyregion、および文字起こしする音声のパス filepath を、実際の情報に置き換えます。

事前登録されたユーザー プロファイルを使用しない場合、speaker1、speaker2 などとして不明なユーザーの最初の認識を完了するまでにさらに数秒かかります。

Note

署名の作成にアプリケーション全体で同じ subscriptionKey が使用されていることを確認してください。そうでないと、エラーが発生します。

サンプルは次のことを実行します。

  • サブスクリプション情報を使用して Speech 構成を作成します。
  • プッシュ ストリームを使用してオーディオ構成を作成します。
  • MeetingTranscriber を作成し、会議の文字起こしによって発生したイベントをサブスクライブします。
  • 会議を作成するための会議識別子。
  • 会議に参加者を追加します。 前の手順の出力として、文字列 voiceSignatureStringUser1voiceSignatureStringUser2 が得られます。
  • wave ファイル全体を一度に読み取り、SDK にストリーミングして文字起こしを開始します。
  • 音声サンプルを提供せずに話者を区別したい場合は、会議の文字起こしの概要に関するページにあるように、DifferentiateGuestSpeakers 機能を有効にします。

話者の識別または区別が有効になっている場合は、transcribed の結果を受け取っている場合でも、サービスは蓄積されたオーディオ情報によってそれらを評価します。 サービスで、以前の結果に正しくない speakerId が割り当てられていることが検出された場合、ほぼ同じで speakerIdUtteranceId のみが異なる Transcribed 結果が再び送信されます。 UtteranceId の形式は {index}_{speakerId}_{Offset} であるため、transcribed 結果を受け取ると、UtteranceId を使用して、現在の transcribed 結果が前の結果を修正するかどうかを判断できます。 クライアントまたは UI ロジックで、以前の出力の上書きなどの動作を決定したり、最新の結果を無視したりできます。

import azure.cognitiveservices.speech as speechsdk
import time
import uuid
from scipy.io import wavfile

speech_key, service_region="your-subscription-key","your-region"
meetingfilename= "audio-file-to-transcribe.wav" # 8 channel, 16 bits, 16kHz audio

def meeting_transcription():
    
    speech_config = speechsdk.SpeechConfig(subscription=speech_key, region=service_region)
    speech_config.set_property_by_name("ConversationTranscriptionInRoomAndOnline", "true")
    # If you want to differentiate speakers without providing voice samples, uncomment the following line.
    # speech_config.set_property_by_name("DifferentiateGuestSpeakers", "true")

    channels = 8
    bits_per_sample = 16
    samples_per_second = 16000
    
    wave_format = speechsdk.audio.AudioStreamFormat(samples_per_second, bits_per_sample, channels)
    stream = speechsdk.audio.PushAudioInputStream(stream_format=wave_format)
    audio_config = speechsdk.audio.AudioConfig(stream=stream)

    transcriber = speechsdk.transcription.MeetingTranscriber(audio_config)

    meeting_id = str(uuid.uuid4())
    meeting = speechsdk.transcription.Meeting(speech_config, meeting_id)
    done = False

    def stop_cb(evt: speechsdk.SessionEventArgs):
        """callback that signals to stop continuous transcription upon receiving an event `evt`"""
        print('CLOSING {}'.format(evt))
        nonlocal done
        done = True
        
    transcriber.transcribed.connect(lambda evt: print('TRANSCRIBED: {}'.format(evt)))
    transcriber.session_started.connect(lambda evt: print('SESSION STARTED: {}'.format(evt)))
    transcriber.session_stopped.connect(lambda evt: print('SESSION STOPPED {}'.format(evt)))
    transcriber.canceled.connect(lambda evt: print('CANCELED {}'.format(evt)))
    # stop continuous transcription on either session stopped or canceled events
    transcriber.session_stopped.connect(stop_cb)
    transcriber.canceled.connect(stop_cb)

    # Note user voice signatures are not required for speaker differentiation.
    # Use voice signatures when adding participants when more enhanced speaker identification is required.
    user1 = speechsdk.transcription.Participant("user1@example.com", "en-us", voice_signature_user1)
    user2 = speechsdk.transcription.Participant("user2@example.com", "en-us", voice_signature_user2)

    meeting.add_participant_async(user1).get()
    meeting.add_participant_async(user2).get()
    transcriber.join_meeting_async(meeting).get()
    transcriber.start_transcribing_async()
    
    sample_rate, wav_data = wavfile.read(meetingfilename)
    stream.write(wav_data.tobytes())
    stream.close()
    while not done:
        time.sleep(.5)

    transcriber.stop_transcribing_async()