빠른 시작: 통화 자동화를 사용하여 아웃바운드 통화 수행

Azure Communication Services 통화 자동화 API는 대화형 통화 환경을 만드는 강력한 방법입니다. 이 빠른 시작에서는 아웃바운드 통화를 수행하고 통화의 다양한 이벤트를 인식하는 방법을 설명합니다.

필수 조건

샘플 코드

GitHub에서 빠른 시작 샘플 코드를 다운로드하거나 복제합니다.

CallAutomation_OutboundCalling 폴더로 이동하고 코드 편집기에서 솔루션을 엽니다.

Azure DevTunnel 설정 및 호스트

Azure DevTunnels는 인터넷에서 호스트되는 로컬 웹 서비스를 공유할 수 있는 Azure 서비스입니다. 명령을 실행하여 로컬 개발 환경을 공용 인터넷에 연결합니다. DevTunnels는 영구 엔드포인트 URL을 만들고 익명 액세스를 허용합니다. 이 엔드포인트를 사용하여 Azure Communication Services 통화 자동화 서비스의 통화 이벤트를 애플리케이션에 알립니다.

devtunnel create --allow-anonymous
devtunnel port create -p 8080
devtunnel host

애플리케이션 구성 업데이트

다음으로 Program.cs 파일을 다음 값으로 업데이트합니다.

  • acsConnectionString: Azure Communication Services 리소스에 대한 연결 문자열입니다. 여기의 지침을 사용하여 Azure Communication Services 연결 문자열을 찾을 수 있습니다.
  • callbackUriHost: DevTunnel 호스트가 초기화되면 이 필드를 해당 URI로 업데이트합니다.
  • acsPhonenumber: 이 필드를 구입한 Azure Communication Services 전화 번호로 업데이트합니다. 이 전화 번호는 E164 전화 번호 형식(예: +18881234567)을 사용해야 합니다.
  • targetPhonenumber: 이 필드를 애플리케이션에서 전화를 걸 전화 번호로 업데이트합니다. 이 전화 번호는 E164 전화 번호 형식(예: +18881234567)을 사용해야 합니다.
  • cognitiveServiceEndpoint: Azure AI 서비스 엔드포인트를 사용하여 필드를 업데이트합니다.
  • targetTeamsUserId: (선택 사항) 통화에 추가하려는 Microsoft Teams 사용자 ID로 필드를 업데이트하세요. Graph API를 사용하여 Teams 사용자 ID 가져오기를 참조하세요.
// Your ACS resource connection string 
var acsConnectionString = "<ACS_CONNECTION_STRING>"; 

// Your ACS resource phone number will act as source number to start outbound call 
var acsPhonenumber = "<ACS_PHONE_NUMBER>"; 
 
// Target phone number you want to receive the call. 
var targetPhonenumber = "<TARGET_PHONE_NUMBER>";

// Base url of the app 
var callbackUriHost = "<CALLBACK_URI_HOST_WITH_PROTOCOL>"; 

// Your cognitive service endpoint 
var cognitiveServiceEndpoint = "<COGNITIVE_SERVICE_ENDPOINT>";

// (Optional) User Id of the target teams user you want to receive the call.
var targetTeamsUserId = "<TARGET_TEAMS_USER_ID>";

아웃바운드 통화 수행

Azure Communication Services에서 아웃바운드 통화를 수행하기 위해 이 샘플은 앞서 애플리케이션에서 정의한 targetPhonenumber를 사용하고 CreateCallAsync API를 사용하여 통화를 만듭니다. 이 코드는 대상 전화 번호를 사용하여 아웃바운드 통화를 수행합니다.

PhoneNumberIdentifier target = new PhoneNumberIdentifier(targetPhonenumber);
PhoneNumberIdentifier caller = new PhoneNumberIdentifier(acsPhonenumber);
var callbackUri = new Uri(callbackUriHost + "/api/callbacks");
CallInvite callInvite = new CallInvite(target, caller);
var createCallOptions = new CreateCallOptions(callInvite, callbackUri) {
  CallIntelligenceOptions = new CallIntelligenceOptions() {
    CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint)
  }
};
CreateCallResult createCallResult = await callAutomationClient.CreateCallAsync(createCallOptions);

통화 자동화 이벤트 처리

앞서 애플리케이션에서 callbackUriHost를 통화 자동화 서비스에 등록했습니다. 이 호스트는 서비스에서 발생하는 통화 이벤트를 알려주는 데 필요한 엔드포인트를 나타냅니다. 그런 다음, 이벤트를 반복하고 애플리케이션이 이해하려는 특정 이벤트를 검색할 수 있습니다. 아래 코드에서는 CallConnected 이벤트에 응답합니다.

app.MapPost("/api/callbacks", async (CloudEvent[] cloudEvents, ILogger < Program > logger) => {
  foreach(var cloudEvent in cloudEvents) {
    logger.LogInformation($"Event received: {JsonConvert.SerializeObject(cloudEvent)}");
    CallAutomationEventBase parsedEvent = CallAutomationEventParser.Parse(cloudEvent);
    logger.LogInformation($"{parsedEvent?.GetType().Name} parsedEvent received for call connection id: {parsedEvent?.CallConnectionId}");
    var callConnection = callAutomationClient.GetCallConnection(parsedEvent.CallConnectionId);
    var callMedia = callConnection.GetCallMedia();
    if (parsedEvent is CallConnected) {
      //Handle Call Connected Event
    }
  }
});

(선택 사항) 통화에 Microsoft Teams 사용자 추가

MicrosoftTeamsUserIdentifier 및 Teams 사용자 ID와 함께 AddParticipantAsync 메서드를 사용하여 통화에 Microsoft Teams 사용자를 추가할 수 있습니다. 먼저 Microsoft Teams 사용자가 통화할 수 있도록 Azure Communication Services 리소스에 대한 권한 부여를 위한 필수 단계를 완료해야 합니다. 선택적으로 SourceDisplayName을(를) 전달하여 Teams 사용자에 대한 알림 메시지에 표시되는 텍스트를 제어할 수도 있습니다.

await callConnection.AddParticipantAsync(
    new CallInvite(new MicrosoftTeamsUserIdentifier(targetTeamsUserId))
    {
        SourceDisplayName = "Jack (Contoso Tech Support)"
    });

통화 녹음/녹화 시작

또한 통화 자동화 서비스를 사용하면 음성 및 영상 통화의 녹음/녹화를 시작하고 저장할 수 있습니다. 여기에서 통화 녹음/녹화 API의 다양한 기능에 대해 자세히 알아볼 수 있습니다.

CallLocator callLocator = new ServerCallLocator(parsedEvent.ServerCallId);
var recordingResult = await callAutomationClient.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator));
recordingId = recordingResult.Value.RecordingId;

환영 메시지 재생 및 인식

TextSource를 사용하여 서비스에 환영 메시지를 위해 합성 및 사용할 텍스트를 제공할 수 있습니다. Azure Communication Services 통화 자동화 서비스는 CallConnected 이벤트 시 이 메시지를 재생합니다.

다음으로, 이 텍스트를 CallMediaRecognizeChoiceOptions에 전달하고 StartRecognizingAsync를 호출합니다. 이렇게 하면 애플리케이션에서 호출자가 선택하는 옵션을 인식할 수 있습니다.

if (parsedEvent is CallConnected callConnected) {
  logger.LogInformation($"Start Recording...");
  CallLocator callLocator = new ServerCallLocator(parsedEvent.ServerCallId);
  var recordingResult = await callAutomationClient.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator));
  recordingId = recordingResult.Value.RecordingId;

  var choices = GetChoices();

  // prepare recognize tones 
  var recognizeOptions = GetMediaRecognizeChoiceOptions(mainMenu, targetPhonenumber, choices);

  // Send request to recognize tones 
  await callMedia.StartRecognizingAsync(recognizeOptions);
}

CallMediaRecognizeChoiceOptions GetMediaRecognizeChoiceOptions(string content, string targetParticipant, List < RecognitionChoice > choices, string context = "") {
  var playSource = new TextSource(content) {
    VoiceName = SpeechToTextVoice
  };

  var recognizeOptions = new CallMediaRecognizeChoiceOptions(targetParticipant: new PhoneNumberIdentifier(targetParticipant), choices) {
    InterruptCallMediaOperation = false,
      InterruptPrompt = false,
      InitialSilenceTimeout = TimeSpan.FromSeconds(10),
      Prompt = playSource,
      OperationContext = context
  };
  return recognizeOptions;
}

List < RecognitionChoice > GetChoices() {
  return new List < RecognitionChoice > {
    new RecognitionChoice("Confirm", new List < string > {
      "Confirm",
      "First",
      "One"
    }) {
      Tone = DtmfTone.One
    },
    new RecognitionChoice("Cancel", new List < string > {
      "Cancel",
      "Second",
      "Two"
    }) {
      Tone = DtmfTone.Two
    }
  };
}

선택 이벤트 처리

Azure Communication Services 통화 자동화는 설치한 웹후크에 대해 api/callbacks를 트리거하고 RecognizeCompleted 이벤트로 알림을 제공합니다. 이 이벤트는 수신된 입력에 응답하고 작업을 트리거하는 기능을 제공합니다. 그런 다음, 애플리케이션은 수신된 특정 입력에 따라 호출자에게 메시지를 재생합니다.

if (parsedEvent is RecognizeCompleted recognizeCompleted) {
  var choiceResult = recognizeCompleted.RecognizeResult as ChoiceResult;
  var labelDetected = choiceResult?.Label;
  var phraseDetected = choiceResult?.RecognizedPhrase;

  // If choice is detected by phrase, choiceResult.RecognizedPhrase will have the phrase detected,  
  // If choice is detected using dtmf tone, phrase will be null  
  logger.LogInformation("Recognize completed succesfully, labelDetected={labelDetected}, phraseDetected={phraseDetected}", labelDetected, phraseDetected);

  var textToPlay = labelDetected.Equals(ConfirmChoiceLabel, StringComparison.OrdinalIgnoreCase) ? ConfirmedText : CancelText;

  await HandlePlayAsync(callMedia, textToPlay);
}

async Task HandlePlayAsync(CallMedia callConnectionMedia, string text) {
  // Play goodbye message 
  var GoodbyePlaySource = new TextSource(text) {
    VoiceName = "en-US-NancyNeural"
  };
  await callConnectionMedia.PlayToAllAsync(GoodbyePlaySource);
}

전화 끊기 및 녹음/녹화 중지

마지막으로, 통화를 종료해야 하는 조건을 감지하면 HangUpAsync 메서드를 사용하여 전화를 끊을 수 있습니다.

if ((parsedEvent is PlayCompleted) || (parsedEvent is PlayFailed))
{
    logger.LogInformation($"Stop recording and terminating call.");
    callAutomationClient.GetCallRecording().Stop(recordingId);
    await callConnection.HangUpAsync(true);
}

코드 실행

VS Code를 사용하여 애플리케이션을 실행하려면 터미널 창을 열고 다음 명령을 실행합니다.

dotnet run

필수 조건

샘플 코드

GitHub에서 빠른 시작 샘플 코드를 다운로드하거나 복제합니다.

CallAutomation_OutboundCalling 폴더로 이동하고 코드 편집기에서 솔루션을 엽니다.

Azure DevTunnel 설정 및 호스트

Azure DevTunnels는 인터넷에서 호스트되는 로컬 웹 서비스를 공유할 수 있는 Azure 서비스입니다. DevTunnel 명령을 실행하여 로컬 개발 환경을 공용 인터넷에 연결합니다. 그러면 DevTunnels가 영구 엔드포인트 URL을 사용하고 익명 액세스를 허용하는 터널을 만듭니다. Azure Communication Services는 이 엔드포인트를 사용하여 Azure Communication Services 통화 자동화 서비스의 통화 이벤트를 애플리케이션에 알립니다.

devtunnel create --allow-anonymous
devtunnel port create -p MY_SPRINGAPP_PORT
devtunnel host

애플리케이션 구성 업데이트

그런 다음 /resources 폴더에서 application.yml 파일을 열고 다음 값을 구성합니다.

  • connectionstring: Azure Communication Services 리소스에 대한 연결 문자열입니다. 여기의 지침을 사용하여 Azure Communication Services 연결 문자열을 찾을 수 있습니다.
  • basecallbackuri: DevTunnel 호스트가 초기화되면 이 필드를 해당 URI로 업데이트합니다.
  • callerphonenumber: 이 필드를 구입한 Azure Communication Services 전화 번호로 업데이트합니다. 이 전화 번호는 E164 전화 번호 형식(예: +18881234567)을 사용해야 합니다.
  • targetphonenumber: 이 필드를 애플리케이션에서 전화를 걸 전화 번호로 업데이트합니다. 이 전화 번호는 E164 전화 번호 형식(예: +18881234567)을 사용해야 합니다.
  • cognitiveServiceEndpoint: Azure AI 서비스 엔드포인트를 사용하여 필드를 업데이트합니다.
  • targetTeamsUserId: (선택 사항) 통화에 추가하려는 Microsoft Teams 사용자 ID로 필드를 업데이트하세요. Graph API를 사용하여 Teams 사용자 ID 가져오기를 참조하세요.
acs:
  connectionstring: <YOUR ACS CONNECTION STRING> 
  basecallbackuri: <YOUR DEV TUNNEL ENDPOINT> 
  callerphonenumber: <YOUR ACS PHONE NUMBER ex. "+1425XXXAAAA"> 
  targetphonenumber: <YOUR TARGET PHONE NUMBER ex. "+1425XXXAAAA"> 
  cognitiveServiceEndpoint: <YOUR COGNITIVE SERVICE ENDPOINT>
  targetTeamsUserId: <(OPTIONAL) YOUR TARGET TEAMS USER ID ex. "ab01bc12-d457-4995-a27b-c405ecfe4870">

아웃바운드 통화 수행 및 미디어 재생

Azure Communication Services에서 아웃바운드 통화를 수행하기 위해 이 샘플은 application.yml 파일에 정의된 targetphonenumber를 사용하고 createCallWithResponse API를 사용하여 통화를 만듭니다.

PhoneNumberIdentifier caller = new PhoneNumberIdentifier(appConfig.getCallerphonenumber());
PhoneNumberIdentifier target = new PhoneNumberIdentifier(appConfig.getTargetphonenumber());
CallInvite callInvite = new CallInvite(target, caller);
CreateCallOptions createCallOptions = new CreateCallOptions(callInvite, appConfig.getCallBackUri());
CallIntelligenceOptions callIntelligenceOptions = new CallIntelligenceOptions().setCognitiveServicesEndpoint(appConfig.getCognitiveServiceEndpoint());
createCallOptions = createCallOptions.setCallIntelligenceOptions(callIntelligenceOptions);
Response<CreateCallResult> result = client.createCallWithResponse(createCallOptions, Context.NONE);

(선택 사항) 통화에 Microsoft Teams 사용자 추가

MicrosoftTeamsUserIdentifier 및 Teams 사용자 ID와 함께 addParticipant 메서드를 사용하여 통화에 Microsoft Teams 사용자를 추가할 수 있습니다. 먼저 Microsoft Teams 사용자가 통화할 수 있도록 Azure Communication Services 리소스에 대한 권한 부여를 위한 필수 단계를 완료해야 합니다. 선택적으로 SourceDisplayName을(를) 전달하여 Teams 사용자에 대한 알림 메시지에 표시되는 텍스트를 제어할 수도 있습니다.

client.getCallConnection(callConnectionId).addParticipant(
    new CallInvite(new MicrosoftTeamsUserIdentifier(targetTeamsUserId))
        .setSourceDisplayName("Jack (Contoso Tech Support)"));

통화 녹음/녹화 시작

또한 통화 자동화 서비스를 사용하면 음성 및 영상 통화의 녹음/녹화를 시작하고 저장할 수 있습니다. 여기에서 통화 녹음/녹화 API의 다양한 기능에 대해 자세히 알아볼 수 있습니다.

ServerCallLocator serverCallLocator = new ServerCallLocator(
    client.getCallConnection(callConnectionId)
        .getCallProperties()
        .getServerCallId());
        
StartRecordingOptions startRecordingOptions = new StartRecordingOptions(serverCallLocator);

Response<RecordingStateResult> response = client.getCallRecording()
    .startWithResponse(startRecordingOptions, Context.NONE);

recordingId = response.getValue().getRecordingId();

통화 이벤트에 응답

앞서 애플리케이션에서 basecallbackuri를 통화 자동화 서비스에 등록했습니다. URI는 서비스가 발생하는 통화 이벤트를 알리는 데 사용할 엔드포인트를 나타냅니다. 그런 다음, 이벤트를 반복하고 애플리케이션이 이해하려는 특정 이벤트를 검색할 수 있습니다. 아래 코드에서는 CallConnected 이벤트에 응답합니다.

List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(reqBody);
for (CallAutomationEventBase event : events) {
    String callConnectionId = event.getCallConnectionId();
    if (event instanceof CallConnected) {
        log.info("CallConnected event received");
    }
    else if (event instanceof RecognizeCompleted) {
        log.info("Recognize Completed event received");
    }
}

환영 메시지 재생 및 인식

TextSource를 사용하여 서비스에 환영 메시지를 위해 합성 및 사용할 텍스트를 제공할 수 있습니다. Azure Communication Services 통화 자동화 서비스는 CallConnected 이벤트 시 이 메시지를 재생합니다.

다음으로, 이 텍스트를 CallMediaRecognizeChoiceOptions에 전달하고 StartRecognizingAsync를 호출합니다. 이렇게 하면 애플리케이션에서 호출자가 선택하는 옵션을 인식할 수 있습니다.

var playSource = new TextSource().setText(content).setVoiceName("en-US-NancyNeural");

var recognizeOptions = new CallMediaRecognizeChoiceOptions(new PhoneNumberIdentifier(targetParticipant), getChoices())
  .setInterruptCallMediaOperation(false)
  .setInterruptPrompt(false)
  .setInitialSilenceTimeout(Duration.ofSeconds(10))
  .setPlayPrompt(playSource)
  .setOperationContext(context);

client.getCallConnection(callConnectionId)
  .getCallMedia()
  .startRecognizing(recognizeOptions);

private List < RecognitionChoice > getChoices() {
  var choices = Arrays.asList(
    new RecognitionChoice().setLabel(confirmLabel).setPhrases(Arrays.asList("Confirm", "First", "One")).setTone(DtmfTone.ONE),
    new RecognitionChoice().setLabel(cancelLabel).setPhrases(Arrays.asList("Cancel", "Second", "Two")).setTone(DtmfTone.TWO)
  );

  return choices;
}

선택 이벤트 처리

Azure Communication Services 통화 자동화는 설치한 웹후크에 대해 api/callbacks를 트리거하고 RecognizeCompleted 이벤트로 알림을 제공합니다. 이 이벤트는 수신된 입력에 응답하고 작업을 트리거하는 기능을 제공합니다. 그런 다음, 애플리케이션은 수신된 특정 입력에 따라 호출자에게 메시지를 재생합니다.

else if (event instanceof RecognizeCompleted) {
  log.info("Recognize Completed event received");

  RecognizeCompleted acsEvent = (RecognizeCompleted) event;

  var choiceResult = (ChoiceResult) acsEvent.getRecognizeResult().get();

  String labelDetected = choiceResult.getLabel();

  String phraseDetected = choiceResult.getRecognizedPhrase();

  log.info("Recognition completed, labelDetected=" + labelDetected + ", phraseDetected=" + phraseDetected + ", context=" + event.getOperationContext());

  String textToPlay = labelDetected.equals(confirmLabel) ? confirmedText : cancelText;

  handlePlay(callConnectionId, textToPlay);
}

private void handlePlay(final String callConnectionId, String textToPlay) {
  var textPlay = new TextSource()
    .setText(textToPlay)
    .setVoiceName("en-US-NancyNeural");

  client.getCallConnection(callConnectionId)
    .getCallMedia()
    .playToAll(textPlay);
}

호출 중단

마지막으로, 통화를 종료해야 하는 조건을 감지하면 hangUp 메서드를 사용하여 전화를 끊을 수 있습니다.

client.getCallConnection(callConnectionId).hangUp(true);

코드 실행

pom.xml 파일이 포함된 디렉터리로 이동하고 다음 mvn 명령을 사용합니다.

  • 애플리케이션 컴파일: mvn compile
  • 패키지 빌드: mvn package
  • 앱 실행: mvn exec:java

필수 조건

샘플 코드

GitHub에서 빠른 시작 샘플 코드를 다운로드하거나 복제합니다.

CallAutomation_OutboundCalling 폴더로 이동하고 코드 편집기에서 솔루션을 엽니다.

환경 설정

샘플 코드를 다운로드하고, 프로젝트 디렉터리로 이동하고, 필요한 종속성을 설치하고 개발자 환경을 설정하는 npm 명령을 실행합니다.

npm install

Azure DevTunnel 설정 및 호스트

Azure DevTunnels는 인터넷에서 호스트되는 로컬 웹 서비스를 공유할 수 있는 Azure 서비스입니다. DevTunnel CLI 명령을 사용하여 로컬 개발 환경을 공용 인터넷에 연결합니다. 이 엔드포인트를 사용하여 Azure Communication Services 통화 자동화 서비스의 통화 이벤트를 애플리케이션에 알립니다.

devtunnel create --allow-anonymous
devtunnel port create -p 8080
devtunnel host

애플리케이션 구성 업데이트

그런 다음 .env 파일을 다음 값으로 업데이트합니다.

  • CONNECTION_STRING: Azure Communication Services 리소스에 대한 연결 문자열입니다. 여기의 지침을 사용하여 Azure Communication Services 연결 문자열을 찾을 수 있습니다.
  • CALLBACK_URI: DevTunnel 호스트가 초기화되면 이 필드를 해당 URI로 업데이트합니다.
  • TARGET_PHONE_NUMBER: 이 필드를 애플리케이션에서 전화를 걸 전화 번호로 업데이트합니다. 이 전화 번호는 E164 전화 번호 형식(예: +18881234567)을 사용해야 합니다.
  • ACS_RESOURCE_PHONE_NUMBER: 이 필드를 구입한 Azure Communication Services 전화 번호로 업데이트합니다. 이 전화 번호는 E164 전화 번호 형식(예: +18881234567)을 사용해야 합니다.
  • COGNITIVE_SERVICES_ENDPOINT: Azure AI 서비스 엔드포인트를 사용하여 필드를 업데이트합니다.
  • TARGET_TEAMS_USER_ID: (선택 사항) 통화에 추가하려는 Microsoft Teams 사용자 ID로 필드를 업데이트하세요. Graph API를 사용하여 Teams 사용자 ID 가져오기를 참조하세요.
CONNECTION_STRING="<YOUR_CONNECTION_STRING>" 
ACS_RESOURCE_PHONE_NUMBER ="<YOUR_ACS_NUMBER>" 
TARGET_PHONE_NUMBER="<+1XXXXXXXXXX>" 
CALLBACK_URI="<VS_TUNNEL_URL>" 
COGNITIVE_SERVICES_ENDPOINT="<COGNITIVE_SERVICES_ENDPOINT>" 
TARGET_TEAMS_USER_ID="<TARGET_TEAMS_USER_ID>"

아웃바운드 통화 수행 및 미디어 재생

Azure Communication Services에서 아웃바운드 통화를 수행하려면 환경에 제공한 전화 번호를 사용합니다. 전화 번호가 E164 전화 번호 형식(예: +18881234567)인지 확인합니다.

코드는 제공한 target_phone_number를 사용하여 해당 번호로 아웃바운드 통화를 수행합니다.

const callInvite: CallInvite = {
	targetParticipant: callee,
	sourceCallIdNumber: {
		phoneNumber: process.env.ACS_RESOURCE_PHONE_NUMBER || "",
	},
};

const options: CreateCallOptions = {
	cognitiveServicesEndpoint: process.env.COGNITIVE_SERVICES_ENDPOINT
};

console.log("Placing outbound call...");
acsClient.createCall(callInvite, process.env.CALLBACK_URI + "/api/callbacks", options);

(선택 사항) 통화에 Microsoft Teams 사용자 추가

microsoftTeamsUserId 속성과 함께 addParticipant 메서드를 사용하여 통화에 Microsoft Teams 사용자를 추가할 수 있습니다. 먼저 Microsoft Teams 사용자가 통화할 수 있도록 Azure Communication Services 리소스에 대한 권한 부여를 위한 필수 단계를 완료해야 합니다. 선택적으로 sourceDisplayName을(를) 전달하여 Teams 사용자에 대한 알림 메시지에 표시되는 텍스트를 제어할 수도 있습니다.

await acsClient.getCallConnection(callConnectionId).addParticipant({
    targetParticipant: { microsoftTeamsUserId: process.env.TARGET_TEAMS_USER_ID },
    sourceDisplayName: "Jack (Contoso Tech Support)"
});

통화 녹음/녹화 시작

또한 통화 자동화 서비스를 사용하면 음성 및 영상 통화의 녹음/녹화를 시작하고 저장할 수 있습니다. 여기에서 통화 녹음/녹화 API의 다양한 기능에 대해 자세히 알아볼 수 있습니다.

const callLocator: CallLocator = {
    id: serverCallId,
    kind: "serverCallLocator",
};

const recordingOptions: StartRecordingOptions = {
    callLocator: callLocator,
};

const response = await acsClient.getCallRecording().start(recordingOptions);

recordingId = response.recordingId;

통화 이벤트에 응답

앞서 애플리케이션에서 CALLBACK_URI를 통화 자동화 서비스에 등록했습니다. URI는 서비스가 발생하는 통화 이벤트를 알리는 데 사용하는 엔드포인트를 나타냅니다. 그런 다음, 이벤트를 반복하고 애플리케이션이 이해하려는 특정 이벤트를 검색할 수 있습니다. CallConnected 이벤트에 응답하여 알림을 받고 다운스트림 작업을 시작합니다. TextSource를 사용하여 서비스에 환영 메시지를 위해 합성 및 사용할 텍스트를 제공할 수 있습니다. Azure Communication Services 통화 자동화 서비스는 CallConnected 이벤트 시 이 메시지를 재생합니다.

다음으로, 이 텍스트를 CallMediaRecognizeChoiceOptions에 전달하고 StartRecognizingAsync를 호출합니다. 이렇게 하면 애플리케이션에서 호출자가 선택하는 옵션을 인식할 수 있습니다.

callConnectionId = eventData.callConnectionId;
serverCallId = eventData.serverCallId;
console.log("Call back event received, callConnectionId=%s, serverCallId=%s, eventType=%s", callConnectionId, serverCallId, event.type);
callConnection = acsClient.getCallConnection(callConnectionId);
const callMedia = callConnection.getCallMedia();

if (event.type === "Microsoft.Communication.CallConnected") {
 	console.log("Received CallConnected event");
 	await startRecording();
	await startRecognizing(callMedia, mainMenu, "");
}

async function startRecognizing(callMedia: CallMedia, textToPlay: string, context: string) {
	const playSource: TextSource = {
 		text: textToPlay,
 		voiceName: "en-US-NancyNeural",
 		kind: "textSource"
 	};

 	const recognizeOptions: CallMediaRecognizeChoiceOptions = {
 		choices: await getChoices(),
 		interruptPrompt: false,
 		initialSilenceTimeoutInSeconds: 10,
 		playPrompt: playSource,
 		operationContext: context,
 		kind: "callMediaRecognizeChoiceOptions"
 	};

 	await callMedia.startRecognizing(callee, recognizeOptions)
 }

선택 이벤트 처리

Azure Communication Services 통화 자동화는 설치한 웹후크에 대해 api/callbacks를 트리거하고 RecognizeCompleted 이벤트로 알림을 제공합니다. 이 이벤트는 수신된 입력에 응답하고 작업을 트리거하는 기능을 제공합니다. 그런 다음, 애플리케이션은 수신된 특정 입력에 따라 호출자에게 메시지를 재생합니다.

else if (event.type === "Microsoft.Communication.RecognizeCompleted") { 
	if(eventData.recognitionType === "choices"){ 
        	console.log("Recognition completed, event=%s, resultInformation=%s",eventData, eventData.resultInformation); 
        	var context = eventData.operationContext; 
            	const labelDetected = eventData.choiceResult.label;  
            	const phraseDetected = eventData.choiceResult.recognizedPhrase; 
            	console.log("Recognition completed, labelDetected=%s, phraseDetected=%s, context=%s", labelDetected, phraseDetected, eventData.operationContext); 
            	const textToPlay = labelDetected === confirmLabel ? confirmText : cancelText;            
            	await handlePlay(callMedia, textToPlay); 
        } 
}  
 
async function handlePlay(callConnectionMedia:CallMedia, textContent:string){ 
	const play : TextSource = { text:textContent , voiceName: "en-US-NancyNeural", kind: "textSource"} 
	await callConnectionMedia.playToAll([play]); 
} 

호출 중단

마지막으로, 통화를 종료해야 하는 조건을 감지하면 hangUp() 메서드를 사용하여 전화를 끊을 수 있습니다.

  await acsClient.getCallRecording().stop(recordingId);
  callConnection.hangUp(true);

코드 실행

애플리케이션을 실행하려면 터미널 창을 열고 다음 명령을 실행합니다.

  npm run dev

필수 조건

샘플 코드

GitHub에서 빠른 시작 샘플 코드를 다운로드하거나 복제합니다.

CallAutomation_OutboundCalling 폴더로 이동하고 코드 편집기에서 솔루션을 엽니다.

Python 환경 설정

다음 명령을 사용하여 Python 환경을 만들어 활성화하고 필요한 패키지를 설치합니다. 여기에서 패키지 관리에 대해 자세히 알아볼 수 있습니다.

pip install -r requirements.txt

Azure DevTunnel 설정 및 호스트

Azure DevTunnels는 인터넷에서 호스트되는 로컬 웹 서비스를 공유할 수 있는 Azure 서비스입니다. 명령을 사용하여 로컬 개발 환경을 공용 인터넷에 연결합니다. DevTunnels가 영구 엔드포인트 URL을 사용하고 익명 액세스를 허용하는 터널을 만듭니다. 이 엔드포인트를 사용하여 Azure Communication Services 통화 자동화 서비스의 통화 이벤트를 애플리케이션에 알립니다.

devtunnel create --allow-anonymous
devtunnel port create -p 8080
devtunnel host

애플리케이션 구성 업데이트

그런 다음 main.py 파일을 다음 값으로 업데이트합니다.

  • ACS_CONNECTION_STRING: Azure Communication Services 리소스에 대한 연결 문자열입니다. 여기의 지침을 사용하여 Azure Communication Services 연결 문자열을 찾을 수 있습니다.
  • CALLBACK_URI_HOST: DevTunnel 호스트가 초기화되면 이 필드를 해당 URI로 업데이트합니다.
  • TARGET_PHONE_NUMBER: 이 필드를 애플리케이션에서 전화를 걸 전화 번호로 업데이트합니다. 이 전화 번호는 E164 전화 번호 형식(예: +18881234567)을 사용해야 합니다.
  • ACS_PHONE_NUMBER: 이 필드를 구입한 Azure Communication Services 전화 번호로 업데이트합니다. 이 전화 번호는 E164 전화 번호 형식(예: +18881234567)을 사용해야 합니다.
  • COGNITIVE_SERVICES_ENDPOINT: Azure AI 서비스 엔드포인트를 사용하여 필드를 업데이트합니다.
  • TARGET_TEAMS_USER_ID: (선택 사항) 통화에 추가하려는 Microsoft Teams 사용자 ID로 필드를 업데이트하세요. Graph API를 사용하여 Teams 사용자 ID 가져오기를 참조하세요.
# Your ACS resource connection string 
ACS_CONNECTION_STRING = "<ACS_CONNECTION_STRING>" 

# Your ACS resource phone number will act as source number to start outbound call 
ACS_PHONE_NUMBER = "<ACS_PHONE_NUMBER>" 

# Target phone number you want to receive the call. 
TARGET_PHONE_NUMBER = "<TARGET_PHONE_NUMBER>" 

# Callback events URI to handle callback events. 
CALLBACK_URI_HOST = "<CALLBACK_URI_HOST_WITH_PROTOCOL>" 
CALLBACK_EVENTS_URI = CALLBACK_URI_HOST + "/api/callbacks" 

#Your Cognitive service endpoint 
COGNITIVE_SERVICES_ENDPOINT = "<COGNITIVE_SERVICES_ENDPOINT>" 

#(OPTIONAL) Your target Microsoft Teams user Id ex. "ab01bc12-d457-4995-a27b-c405ecfe4870"
TARGET_TEAMS_USER_ID = "<TARGET_TEAMS_USER_ID>"

아웃바운드 통화 수행

Azure Communication Services에서 아웃바운드 통화를 수행하려면 먼저 전화를 받을 전화 번호를 제공합니다. 간단히 하기 위해 target_phone_numberE164 전화 번호 형식(예: +18881234567)으로 업데이트할 수 있습니다.

제공한 target_phone_number를 사용하여 아웃바운드 통화를 수행합니다.

target_participant = PhoneNumberIdentifier(TARGET_PHONE_NUMBER) 
source_caller = PhoneNumberIdentifier(ACS_PHONE_NUMBER) 
call_invite = CallInvite(target=target_participant, source_caller_id_number=source_caller) 
call_connection_properties = call_automation_client.create_call(call_invite, CALLBACK_EVENTS_URI, 
cognitive_services_endpoint=COGNITIVE_SERVICES_ENDPOINT) 
    app.logger.info("Created call with connection id: %s",
call_connection_properties.call_connection_id) 
return redirect("/") 

(선택 사항) 통화에 Microsoft Teams 사용자 추가

MicrosoftTeamsUserIdentifier 및 Teams 사용자 ID와 함께 add_participant 메서드를 사용하여 통화에 Microsoft Teams 사용자를 추가할 수 있습니다. 먼저 Microsoft Teams 사용자가 통화할 수 있도록 Azure Communication Services 리소스에 대한 권한 부여를 위한 필수 단계를 완료해야 합니다. 선택적으로 source_display_name을(를) 전달하여 Teams 사용자에 대한 알림 메시지에 표시되는 텍스트를 제어할 수도 있습니다.

call_connection_client.add_participant(target_participant = CallInvite(
    target = MicrosoftTeamsUserIdentifier(user_id=TARGET_TEAMS_USER_ID),
    source_display_name = "Jack (Contoso Tech Support)"))

통화 녹음/녹화 시작

또한 통화 자동화 서비스를 사용하면 음성 및 영상 통화의 녹음/녹화를 시작하고 저장할 수 있습니다. 여기에서 통화 녹음/녹화 API의 다양한 기능에 대해 자세히 알아볼 수 있습니다.

recording_properties = call_automation_client.start_recording(ServerCallLocator(event.data['serverCallId']))
recording_id = recording_properties.recording_id

통화 이벤트에 응답

앞서 애플리케이션에서 CALLBACK_URI_HOST를 통화 자동화 서비스에 등록했습니다. URI는 서비스가 발생하는 통화 이벤트를 알리는 데 사용하는 엔드포인트를 나타냅니다. 그런 다음, 이벤트를 반복하고 애플리케이션이 이해하려는 특정 이벤트를 검색할 수 있습니다. 아래 코드에서는 CallConnected 이벤트에 응답합니다.

@app.route('/api/callbacks', methods=['POST'])
def callback_events_handler():
    for event_dict in request.json:
        event = CloudEvent.from_dict(event_dict)
        if event.type == "Microsoft.Communication.CallConnected":
            # Handle Call Connected Event
            ...
            return Response(status=200)

환영 메시지 재생 및 인식

TextSource를 사용하여 서비스에 환영 메시지를 위해 합성 및 사용할 텍스트를 제공할 수 있습니다. Azure Communication Services 통화 자동화 서비스는 CallConnected 이벤트 시 이 메시지를 재생합니다.

다음으로, 이 텍스트를 CallMediaRecognizeChoiceOptions에 전달하고 StartRecognizingAsync를 호출합니다. 이렇게 하면 애플리케이션에서 호출자가 선택하는 옵션을 인식할 수 있습니다.


get_media_recognize_choice_options( 
    call_connection_client=call_connection_client, 
    text_to_play=MainMenu,  
    target_participant=target_participant, 
    choices=get_choices(),context="") 

def get_media_recognize_choice_options(call_connection_client: CallConnectionClient, text_to_play: str, target_participant:str, choices: any, context: str): 
    play_source =  TextSource (text= text_to_play, voice_name= SpeechToTextVoice) 
    call_connection_client.start_recognizing_media( 
        input_type=RecognizeInputType.CHOICES, 

        target_participant=target_participant,
        choices=choices, 
        play_prompt=play_source, 
        interrupt_prompt=False, 
        initial_silence_timeout=10, 
        operation_context=context 
    ) 

def get_choices(): 
    choices = [ 
        RecognitionChoice(label = ConfirmChoiceLabel, phrases= ["Confirm", "First", "One"], tone = DtmfTone.ONE), 
        RecognitionChoice(label = CancelChoiceLabel, phrases= ["Cancel", "Second", "Two"], tone = DtmfTone.TWO) 
    ] 
return choices 

선택 이벤트 처리

Azure Communication Services 통화 자동화는 설치한 웹후크에 대해 api/callbacks를 트리거하고 RecognizeCompleted 이벤트로 알림을 제공합니다. 이 이벤트는 수신된 입력에 응답하고 작업을 트리거하는 기능을 제공합니다. 그런 다음, 애플리케이션은 수신된 특정 입력에 따라 호출자에게 메시지를 재생합니다.

elif event.type == "Microsoft.Communication.RecognizeCompleted":
	app.logger.info("Recognize completed: data=%s", event.data)
if event.data['recognitionType'] == "choices":
	labelDetected = event.data['choiceResult']['label'];
phraseDetected = event.data['choiceResult']['recognizedPhrase'];
app.logger.info("Recognition completed, labelDetected=%s, phraseDetected=%s, context=%s", labelDetected, phraseDetected, event.data.get('operationContext'))
if labelDetected == ConfirmChoiceLabel:
	textToPlay = ConfirmedText
else:
	textToPlay = CancelText
handle_play(call_connection_client = call_connection_client, text_to_play = textToPlay)
def handle_play(call_connection_client: CallConnectionClient, text_to_play: str):
	play_source = TextSource(text = text_to_play, voice_name = SpeechToTextVoice)
call_connection_client.play_media_to_all(play_source)

호출 중단

마지막으로, 통화를 종료해야 하는 조건을 감지하면 hang_up() 메서드를 사용하여 전화를 끊을 수 있습니다. 마지막으로 통화 녹음/녹화 작업을 안전하게 중지할 수도 있습니다.

call_automation_client.stop_recording(recording_id)
call_connection_client.hang_up(is_for_everyone=True)

코드 실행

VS Code를 사용하여 애플리케이션을 실행하려면 터미널 창을 열고 다음 명령을 실행합니다.

python main.py