GitHub Copilot
ChatGPT
Claude
Codex CLI
Cursor
opencode
Skill
Text
azure-communication-callautomation-java
Build call automation workflows with Azure Communication Services Call Automation Java SDK. Use when implementing IVR systems, call routing, call recording, DTMF recognition, text-to-speech, or AI-powered call flows.
Virus-scanned
Reviewed automatically before listing.
Download
microsoft-skills-.github_plugins_azure-sdk-java_skills_azure-communication-callautomation-java-e58528d.zip · 6 KB
Install
skills CLI
npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-java/skills/azure-communication-callautomation-java
Claude Code
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git
git clone https://github.com/microsoft/skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Azure Communication Call Automation (Java)
Build server-side call automation workflows including IVR systems, call routing, recording, and AI-powered interactions.
Installation
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-communication-callautomation</artifactId>
<version>1.6.0</version>
</dependency>
Client Creation
import com.azure.communication.callautomation.CallAutomationClient;
import com.azure.communication.callautomation.CallAutomationClientBuilder;
import com.azure.core.credential.TokenCredential;
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
TokenCredential credential = new DefaultAzureCredentialBuilder()
.requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
.build();
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();
// With DefaultAzureCredential
CallAutomationClient client = new CallAutomationClientBuilder()
.endpoint("https://<resource>.communication.azure.com")
.credential(credential)
.buildClient();
// With connection string
CallAutomationClient client = new CallAutomationClientBuilder()
.connectionString("<connection-string>")
.buildClient();
Key Concepts
| Class | Purpose |
|---|---|
CallAutomationClient |
Make calls, answer/reject incoming calls, redirect calls |
CallConnection |
Actions in established calls (add participants, terminate) |
CallMedia |
Media operations (play audio, recognize DTMF/speech) |
CallRecording |
Start/stop/pause recording |
CallAutomationEventParser |
Parse webhook events from ACS |
Create Outbound Call
import com.azure.communication.callautomation.models.*;
import com.azure.communication.common.CommunicationUserIdentifier;
import com.azure.communication.common.PhoneNumberIdentifier;
// Call to PSTN number
PhoneNumberIdentifier target = new PhoneNumberIdentifier("+14255551234");
PhoneNumberIdentifier caller = new PhoneNumberIdentifier("+14255550100");
CreateCallOptions options = new CreateCallOptions(
new CommunicationUserIdentifier("<user-id>"), // Source
List.of(target)) // Targets
.setSourceCallerId(caller)
.setCallbackUrl("https://your-app.com/api/callbacks");
CreateCallResult result = client.createCall(options);
String callConnectionId = result.getCallConnectionProperties().getCallConnectionId();
Answer Incoming Call
// From Event Grid webhook - IncomingCall event
String incomingCallContext = "<incoming-call-context-from-event>";
AnswerCallOptions options = new AnswerCallOptions(
incomingCallContext,
"https://your-app.com/api/callbacks");
AnswerCallResult result = client.answerCall(options);
CallConnection callConnection = result.getCallConnection();
Play Audio (Text-to-Speech)
CallConnection callConnection = client.getCallConnection(callConnectionId);
CallMedia callMedia = callConnection.getCallMedia();
// Play text-to-speech
TextSource textSource = new TextSource()
.setText("Welcome to Contoso. Press 1 for sales, 2 for support.")
.setVoiceName("en-US-JennyNeural");
PlayOptions playOptions = new PlayOptions(
List.of(textSource),
List.of(new CommunicationUserIdentifier("<target-user>")));
callMedia.play(playOptions);
// Play audio file
FileSource fileSource = new FileSource()
.setUrl("https://storage.blob.core.windows.net/audio/greeting.wav");
callMedia.play(new PlayOptions(List.of(fileSource), List.of(target)));
Recognize DTMF Input
// Recognize DTMF tones
DtmfTone stopTones = DtmfTone.POUND;
CallMediaRecognizeDtmfOptions recognizeOptions = new CallMediaRecognizeDtmfOptions(
new CommunicationUserIdentifier("<target-user>"),
5) // Max tones to collect
.setInterToneTimeout(Duration.ofSeconds(5))
.setStopTones(List.of(stopTones))
.setInitialSilenceTimeout(Duration.ofSeconds(15))
.setPlayPrompt(new TextSource().setText("Enter your account number followed by pound."));
callMedia.startRecognizing(recognizeOptions);
Recognize Speech
// Speech recognition with AI
CallMediaRecognizeSpeechOptions speechOptions = new CallMediaRecognizeSpeechOptions(
new CommunicationUserIdentifier("<target-user>"))
.setEndSilenceTimeout(Duration.ofSeconds(2))
.setSpeechLanguage("en-US")
.setPlayPrompt(new TextSource().setText("How can I help you today?"));
callMedia.startRecognizing(speechOptions);
Call Recording
CallRecording callRecording = client.getCallRecording();
// Start recording
StartRecordingOptions recordingOptions = new StartRecordingOptions(
new ServerCallLocator("<server-call-id>"))
.setRecordingChannel(RecordingChannel.MIXED)
.setRecordingContent(RecordingContent.AUDIO_VIDEO)
.setRecordingFormat(RecordingFormat.MP4);
RecordingStateResult recordingResult = callRecording.start(recordingOptions);
String recordingId = recordingResult.getRecordingId();
// Pause/resume/stop
callRecording.pause(recordingId);
callRecording.resume(recordingId);
callRecording.stop(recordingId);
// Download recording (after RecordingFileStatusUpdated event)
callRecording.downloadTo(recordingUrl, Paths.get("recording.mp4"));
Add Participant to Call
CallConnection callConnection = client.getCallConnection(callConnectionId);
CommunicationUserIdentifier participant = new CommunicationUserIdentifier("<user-id>");
AddParticipantOptions addOptions = new AddParticipantOptions(participant)
.setInvitationTimeout(Duration.ofSeconds(30));
AddParticipantResult result = callConnection.addParticipant(addOptions);
Transfer Call
// Blind transfer
PhoneNumberIdentifier transferTarget = new PhoneNumberIdentifier("+14255559999");
TransferCallToParticipantResult result = callConnection.transferCallToParticipant(transferTarget);
Handle Events (Webhook)
import com.azure.communication.callautomation.CallAutomationEventParser;
import com.azure.communication.callautomation.models.events.*;
// In your webhook endpoint
public void handleCallback(String requestBody) {
List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(requestBody);
for (CallAutomationEventBase event : events) {
if (event instanceof CallConnected) {
CallConnected connected = (CallConnected) event;
System.out.println("Call connected: " + connected.getCallConnectionId());
} else if (event instanceof RecognizeCompleted) {
RecognizeCompleted recognized = (RecognizeCompleted) event;
// Handle DTMF or speech recognition result
DtmfResult dtmfResult = (DtmfResult) recognized.getRecognizeResult();
String tones = dtmfResult.getTones().stream()
.map(DtmfTone::toString)
.collect(Collectors.joining());
System.out.println("DTMF received: " + tones);
} else if (event instanceof PlayCompleted) {
System.out.println("Audio playback completed");
} else if (event instanceof CallDisconnected) {
System.out.println("Call ended");
}
}
}
Hang Up Call
// Hang up for all participants
callConnection.hangUp(true);
// Hang up only this leg
callConnection.hangUp(false);
Error Handling
import com.azure.core.exception.HttpResponseException;
try {
client.answerCall(options);
} catch (HttpResponseException e) {
if (e.getResponse().getStatusCode() == 404) {
System.out.println("Call not found or already ended");
} else if (e.getResponse().getStatusCode() == 400) {
System.out.println("Invalid request: " + e.getMessage());
}
}
Environment Variables
AZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com # Required for all auth methods
AZURE_COMMUNICATION_CONNECTION_STRING=endpoint=https://...;accesskey=... # Alternative to Entra ID auth
CALLBACK_BASE_URL=https://your-app.com/api/callbacks # Required for webhook callbacks
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
Trigger Phrases
- "call automation Java", "IVR Java", "interactive voice response"
- "call recording Java", "DTMF recognition Java"
- "text to speech call", "speech recognition call"
- "answer incoming call", "transfer call Java"
- "Azure Communication Services call automation"
Files (skills)
-
references
-
examples.md 16.1 KB
# Azure Communication Call Automation SDK for Java - Examples Comprehensive code examples for the Azure Communication Call Automation SDK for Java. ## Table of Contents - [Maven Dependency](#maven-dependency) - [Client Creation](#client-creation) - [Creating Outbound Calls](#creating-outbound-calls) - [Answering Inbound Calls](#answering-inbound-calls) - [Playing Audio/TTS](#playing-audiotts) - [Recognizing DTMF Tones](#recognizing-dtmf-tones) - [Recording Calls](#recording-calls) - [Transfer Calls](#transfer-calls) - [Add/Remove Participants](#addremove-participants) - [Handling Call Events](#handling-call-events) - [Async Client Patterns](#async-client-patterns) - [Error Handling](#error-handling) ## Maven Dependency ```xml <dependency> <groupId>com.azure</groupId> <artifactId>azure-communication-callautomation</artifactId> <version>1.5.2</version> </dependency> ``` ## Client Creation ### Sync Client ```java import com.azure.communication.callautomation.CallAutomationClient; import com.azure.communication.callautomation.CallAutomationClientBuilder; CallAutomationClient callAutomationClient = new CallAutomationClientBuilder() .connectionString("<Azure Communication Services connection string>") .buildClient(); ``` ### Async Client ```java import com.azure.communication.callautomation.CallAutomationAsyncClient; CallAutomationAsyncClient asyncClient = new CallAutomationClientBuilder() .connectionString("<acsConnectionString>") .buildAsyncClient(); ``` ## Creating Outbound Calls ### Single PSTN Call ```java import com.azure.communication.callautomation.models.*; import com.azure.communication.common.PhoneNumberIdentifier; import com.azure.core.util.Context; String callbackUri = "https://<myendpoint>/Events"; PhoneNumberIdentifier callerIdNumber = new PhoneNumberIdentifier("+18001234567"); PhoneNumberIdentifier target = new PhoneNumberIdentifier("+16471234567"); CallInvite callInvite = new CallInvite(target, callerIdNumber); CreateCallOptions createCallOptions = new CreateCallOptions(callInvite, callbackUri); // Optional: Add AI capabilities CallIntelligenceOptions callIntelligenceOptions = new CallIntelligenceOptions() .setCognitiveServicesEndpoint("https://your-cognitive-services.cognitiveservices.azure.com/"); createCallOptions.setCallIntelligenceOptions(callIntelligenceOptions); Response<CreateCallResult> result = callAutomationClient.createCallWithResponse( createCallOptions, Context.NONE ); String callConnectionId = result.getValue().getCallConnectionProperties().getCallConnectionId(); ``` ### Group Call ```java import com.azure.communication.common.CommunicationUserIdentifier; import java.util.ArrayList; import java.util.Arrays; import java.util.List; List<CommunicationIdentifier> targets = new ArrayList<>(Arrays.asList( new PhoneNumberIdentifier("+16471234567"), new CommunicationUserIdentifier("<user_id>") )); CreateGroupCallOptions groupCallOptions = new CreateGroupCallOptions(targets, callbackUri); groupCallOptions.setSourceCallIdNumber(callerIdNumber); Response<CreateCallResult> response = callAutomationClient.createGroupCallWithResponse( groupCallOptions, Context.NONE ); ``` ## Answering Inbound Calls ### Basic Answer ```java import com.azure.communication.callautomation.models.*; String incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>"; String callbackUri = "https://<myendpoint>/Events"; AnswerCallOptions answerCallOptions = new AnswerCallOptions(incomingCallContext, callbackUri); Response<AnswerCallResult> response = callAutomationClient.answerCallWithResponse( answerCallOptions, Context.NONE ); ``` ### Answer with AI Capabilities ```java CallIntelligenceOptions callIntelligenceOptions = new CallIntelligenceOptions() .setCognitiveServicesEndpoint("https://cognitive-services.cognitiveservices.azure.com/"); AnswerCallOptions answerCallOptions = new AnswerCallOptions(incomingCallContext, callbackUri) .setCallIntelligenceOptions(callIntelligenceOptions); Response<AnswerCallResult> response = callAutomationClient.answerCallWithResponse( answerCallOptions, Context.NONE ); ``` ### Answer with Transcription ```java TranscriptionOptions transcriptionOptions = new TranscriptionOptions( "wss://your-websocket-url", TranscriptionTransport.WEBSOCKET, "en-US", false, "your-endpoint-id" ); AnswerCallOptions answerCallOptions = new AnswerCallOptions(incomingCallContext, callbackUri) .setCallIntelligenceOptions(callIntelligenceOptions) .setTranscriptionOptions(transcriptionOptions); ``` ## Playing Audio/TTS ### Play Text-to-Speech to All ```java import com.azure.communication.callautomation.CallConnection; String textToPlay = "Welcome to Contoso. How can I help you today?"; TextSource textSource = new TextSource() .setText(textToPlay) .setVoiceName("en-US-NancyNeural"); CallConnection callConnection = callAutomationClient.getCallConnection(callConnectionId); callConnection.getCallMedia().playToAll(textSource); ``` ### Play Audio File to Participant ```java import java.util.Arrays; CommunicationIdentifier targetParticipant = new PhoneNumberIdentifier("+16471234567"); FileSource playSource = new FileSource() .setUrl("https://storage.blob.core.windows.net/audio/welcome.wav") .setPlaySourceCacheId("<playSourceId>"); // Optional: cache for repeated playback var playTo = Arrays.asList(targetParticipant); PlayOptions playOptions = new PlayOptions(playSource, playTo); callAutomationClient.getCallConnection(callConnectionId) .getCallMedia() .playWithResponse(playOptions, Context.NONE); ``` ### Play with SSML ```java String ssmlText = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\">" + "<voice name=\"en-US-JennyNeural\">Hello, welcome to our service!</voice></speak>"; SsmlSource ssmlSource = new SsmlSource() .setSsmlText(ssmlText); callConnection.getCallMedia().playToAll(ssmlSource); ``` ## Recognizing DTMF Tones ### DTMF Recognition ```java import java.time.Duration; import java.util.Arrays; CommunicationIdentifier targetParticipant = new PhoneNumberIdentifier("+16471234567"); int maxTonesToCollect = 3; TextSource playSource = new TextSource() .setText("Please enter 3 digits.") .setVoiceName("en-US-ElizabethNeural"); CallMediaRecognizeDtmfOptions recognizeOptions = new CallMediaRecognizeDtmfOptions( targetParticipant, maxTonesToCollect ) .setInitialSilenceTimeout(Duration.ofSeconds(30)) .setPlayPrompt(playSource) .setInterToneTimeout(Duration.ofSeconds(5)) .setInterruptPrompt(true) .setStopTones(Arrays.asList(DtmfTone.POUND)); callAutomationClient.getCallConnection(callConnectionId) .getCallMedia() .startRecognizingWithResponse(recognizeOptions, Context.NONE); ``` ### Speech or DTMF Recognition ```java CallMediaRecognizeSpeechOrDtmfOptions recognizeOptions = new CallMediaRecognizeSpeechOrDtmfOptions( targetParticipant, maxTonesToCollect, Duration.ofMillis(1000) ) .setPlayPrompt(playSource) .setInitialSilenceTimeout(Duration.ofSeconds(30)) .setInterruptPrompt(true) .setOperationContext("OpenQuestionSpeechOrDtmf"); callAutomationClient.getCallConnection(callConnectionId) .getCallMedia() .startRecognizingWithResponse(recognizeOptions, Context.NONE); ``` ### Choice Recognition ```java import java.util.List; List<RecognitionChoice> choices = Arrays.asList( new RecognitionChoice() .setLabel("Confirm") .setPhrases(Arrays.asList("Confirm", "Yes", "One")) .setTone(DtmfTone.ONE), new RecognitionChoice() .setLabel("Cancel") .setPhrases(Arrays.asList("Cancel", "No", "Two")) .setTone(DtmfTone.TWO) ); TextSource playSource = new TextSource() .setText("Say Confirm or press 1 to confirm, or say Cancel or press 2 to cancel.") .setVoiceName("en-US-ElizabethNeural"); CallMediaRecognizeChoiceOptions recognizeOptions = new CallMediaRecognizeChoiceOptions( targetParticipant, choices ) .setInterruptPrompt(true) .setInitialSilenceTimeout(Duration.ofSeconds(30)) .setPlayPrompt(playSource) .setOperationContext("AppointmentReminderMenu"); callAutomationClient.getCallConnection(callConnectionId) .getCallMedia() .startRecognizingWithResponse(recognizeOptions, Context.NONE); ``` ### Send DTMF Tones ```java List<DtmfTone> tones = Arrays.asList( DtmfTone.ONE, DtmfTone.TWO, DtmfTone.THREE, DtmfTone.POUND ); SendDtmfTonesOptions options = new SendDtmfTonesOptions( tones, new PhoneNumberIdentifier(targetPhoneNumber) ); options.setOperationContext("dtmfs-to-ivr"); callAutomationClient.getCallConnection(callConnectionId) .getCallMedia() .sendDtmfTonesWithResponse(options, Context.NONE); ``` ## Recording Calls ### Start Recording ```java import com.azure.communication.callautomation.CallRecording; CallRecording callRecording = callAutomationClient.getCallRecording(); StartRecordingOptions startRecordingOptions = new StartRecordingOptions( new ServerCallLocator(serverCallId) ) .setRecordingContent(RecordingContent.AUDIO_VIDEO) .setRecordingChannel(RecordingChannel.MIXED) .setRecordingFormat(RecordingFormat.MP4); Response<RecordingStateResult> response = callRecording.startWithResponse( startRecordingOptions, Context.NONE ); String recordingId = response.getValue().getRecordingId(); ``` ### Pause/Resume Recording ```java // Pause callRecording.pause(recordingId); // Resume callRecording.resume(recordingId); ``` ### Stop Recording ```java callRecording.stop(recordingId); ``` ### Download Recording ```java callRecording.downloadToWithResponse( recordingUrl, Paths.get("recording.mp4"), null, // HttpRange (optional) Context.NONE ); ``` ## Transfer Calls ### Blind Transfer ```java CommunicationIdentifier transferDestination = new PhoneNumberIdentifier("+16471234567"); TransferCallToParticipantOptions transferOptions = new TransferCallToParticipantOptions( transferDestination ); Response<TransferCallResult> response = callAutomationClient .getCallConnection(callConnectionId) .transferCallToParticipantWithResponse(transferOptions, Context.NONE); ``` ### Transfer with Announcement ```java TextSource transferee Prompt = new TextSource() .setText("Please hold while we transfer your call.") .setVoiceName("en-US-NancyNeural"); TransferCallToParticipantOptions transferOptions = new TransferCallToParticipantOptions( transferDestination ) .setSourceCallerIdNumber(new PhoneNumberIdentifier("+18001234567")) .setTransfereeGreeting(transfereePrompt); callAutomationClient.getCallConnection(callConnectionId) .transferCallToParticipantWithResponse(transferOptions, Context.NONE); ``` ## Add/Remove Participants ### Add Participant ```java CommunicationIdentifier participant = new PhoneNumberIdentifier("+16471234567"); PhoneNumberIdentifier callerId = new PhoneNumberIdentifier("+18001234567"); AddParticipantOptions addOptions = new AddParticipantOptions( new CallInvite(participant, callerId) ); Response<AddParticipantResult> response = callAutomationClient .getCallConnection(callConnectionId) .addParticipantWithResponse(addOptions, Context.NONE); ``` ### Remove Participant ```java CommunicationIdentifier participant = new PhoneNumberIdentifier("+16471234567"); callAutomationClient.getCallConnection(callConnectionId) .removeParticipant(participant); ``` ### List Participants ```java ListParticipantsResult participants = callAutomationClient .getCallConnection(callConnectionId) .listParticipants(); participants.getValues().forEach(p -> System.out.println("Participant: " + p.getIdentifier().getRawId())); ``` ## Handling Call Events ### Event Grid Webhook Handler (Spring Boot) ```java import com.azure.communication.callautomation.CallAutomationEventParser; import com.azure.communication.callautomation.models.events.*; import org.springframework.web.bind.annotation.*; @RestController public class CallbackController { @PostMapping("/Events") public ResponseEntity<String> handleCallEvents(@RequestBody String requestBody) { List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(requestBody); for (CallAutomationEventBase event : events) { String callConnectionId = event.getCallConnectionId(); if (event instanceof CallConnected) { handleCallConnected((CallConnected) event); } else if (event instanceof RecognizeCompleted) { handleRecognizeCompleted((RecognizeCompleted) event); } else if (event instanceof RecognizeFailed) { handleRecognizeFailed((RecognizeFailed) event); } else if (event instanceof PlayCompleted) { handlePlayCompleted((PlayCompleted) event); } else if (event instanceof CallDisconnected) { handleCallDisconnected((CallDisconnected) event); } } return ResponseEntity.ok(""); } private void handleCallConnected(CallConnected event) { System.out.println("Call connected: " + event.getCallConnectionId()); } private void handleRecognizeCompleted(RecognizeCompleted event) { CollectTonesResult result = (CollectTonesResult) event.getRecognizeResult(); String tones = result.getTones().stream() .map(DtmfTone::toString) .collect(Collectors.joining()); System.out.println("DTMF tones received: " + tones); } private void handleRecognizeFailed(RecognizeFailed event) { System.out.println("Recognition failed: " + event.getResultInformation().getMessage()); } private void handlePlayCompleted(PlayCompleted event) { System.out.println("Play completed: " + event.getOperationContext()); } private void handleCallDisconnected(CallDisconnected event) { System.out.println("Call disconnected: " + event.getCallConnectionId()); } } ``` ## Async Client Patterns ### Create Call Async ```java asyncClient.createCall(callInvite, callbackUri) .subscribe( result -> System.out.println("Call ID: " + result.getCallConnectionProperties().getCallConnectionId()), error -> System.err.println("Error: " + error.getMessage()) ); ``` ### Play Audio Async ```java asyncClient.getCallConnectionAsync(callConnectionId) .getCallMediaAsync() .playToAll(textSource) .subscribe( unused -> System.out.println("Play started"), error -> System.err.println("Error: " + error.getMessage()) ); ``` ### Recognize Async ```java asyncClient.getCallConnectionAsync(callConnectionId) .getCallMediaAsync() .startRecognizingWithResponse(recognizeOptions) .subscribe( response -> System.out.println("Recognition started"), error -> System.err.println("Error: " + error.getMessage()) ); ``` ## Error Handling ### Sync Error Handling ```java import com.azure.core.exception.HttpResponseException; try { Response<CreateCallResult> result = callAutomationClient.createCallWithResponse( createCallOptions, Context.NONE ); } catch (HttpResponseException e) { System.err.println("HTTP Status: " + e.getResponse().getStatusCode()); System.err.println("Error: " + e.getMessage()); } catch (Exception e) { System.err.println("Unexpected error: " + e.getMessage()); } ``` ### Async Error Handling ```java asyncClient.createCall(callInvite, callbackUri) .subscribe( result -> System.out.println("Success"), error -> { if (error instanceof HttpResponseException) { HttpResponseException httpError = (HttpResponseException) error; System.err.println("HTTP error: " + httpError.getResponse().getStatusCode()); } else { System.err.println("Error: " + error.getMessage()); } } ); ``` ### Common Error Codes | Code | Meaning | |------|---------| | 400 | Invalid request | | 401 | Authentication failed | | 403 | Not authorized | | 404 | Call/resource not found | | 429 | Rate limited | | 500 | Server error |
-
-
SKILL.md 9.1 KB
--- name: azure-communication-callautomation-java description: Build call automation workflows with Azure Communication Services Call Automation Java SDK. Use when implementing IVR systems, call routing, call recording, DTMF recognition, text-to-speech, or AI-powered call flows. license: MIT metadata: author: Microsoft version: "1.0.0" package: com.azure:azure-communication-callautomation --- # Azure Communication Call Automation (Java) Build server-side call automation workflows including IVR systems, call routing, recording, and AI-powered interactions. ## Installation ```xml <dependency> <groupId>com.azure</groupId> <artifactId>azure-communication-callautomation</artifactId> <version>1.6.0</version> </dependency> ``` ## Client Creation ```java import com.azure.communication.callautomation.CallAutomationClient; import com.azure.communication.callautomation.CallAutomationClientBuilder; import com.azure.core.credential.TokenCredential; import com.azure.identity.AzureIdentityEnvVars; import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.identity.ManagedIdentityCredentialBuilder; // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential> TokenCredential credential = new DefaultAzureCredentialBuilder() .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS) .build(); // Or use a specific credential directly in production: // See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes // TokenCredential credential = new ManagedIdentityCredentialBuilder().build(); // With DefaultAzureCredential CallAutomationClient client = new CallAutomationClientBuilder() .endpoint("https://<resource>.communication.azure.com") .credential(credential) .buildClient(); // With connection string CallAutomationClient client = new CallAutomationClientBuilder() .connectionString("<connection-string>") .buildClient(); ``` ## Key Concepts | Class | Purpose | |-------|---------| | `CallAutomationClient` | Make calls, answer/reject incoming calls, redirect calls | | `CallConnection` | Actions in established calls (add participants, terminate) | | `CallMedia` | Media operations (play audio, recognize DTMF/speech) | | `CallRecording` | Start/stop/pause recording | | `CallAutomationEventParser` | Parse webhook events from ACS | ## Create Outbound Call ```java import com.azure.communication.callautomation.models.*; import com.azure.communication.common.CommunicationUserIdentifier; import com.azure.communication.common.PhoneNumberIdentifier; // Call to PSTN number PhoneNumberIdentifier target = new PhoneNumberIdentifier("+14255551234"); PhoneNumberIdentifier caller = new PhoneNumberIdentifier("+14255550100"); CreateCallOptions options = new CreateCallOptions( new CommunicationUserIdentifier("<user-id>"), // Source List.of(target)) // Targets .setSourceCallerId(caller) .setCallbackUrl("https://your-app.com/api/callbacks"); CreateCallResult result = client.createCall(options); String callConnectionId = result.getCallConnectionProperties().getCallConnectionId(); ``` ## Answer Incoming Call ```java // From Event Grid webhook - IncomingCall event String incomingCallContext = "<incoming-call-context-from-event>"; AnswerCallOptions options = new AnswerCallOptions( incomingCallContext, "https://your-app.com/api/callbacks"); AnswerCallResult result = client.answerCall(options); CallConnection callConnection = result.getCallConnection(); ``` ## Play Audio (Text-to-Speech) ```java CallConnection callConnection = client.getCallConnection(callConnectionId); CallMedia callMedia = callConnection.getCallMedia(); // Play text-to-speech TextSource textSource = new TextSource() .setText("Welcome to Contoso. Press 1 for sales, 2 for support.") .setVoiceName("en-US-JennyNeural"); PlayOptions playOptions = new PlayOptions( List.of(textSource), List.of(new CommunicationUserIdentifier("<target-user>"))); callMedia.play(playOptions); // Play audio file FileSource fileSource = new FileSource() .setUrl("https://storage.blob.core.windows.net/audio/greeting.wav"); callMedia.play(new PlayOptions(List.of(fileSource), List.of(target))); ``` ## Recognize DTMF Input ```java // Recognize DTMF tones DtmfTone stopTones = DtmfTone.POUND; CallMediaRecognizeDtmfOptions recognizeOptions = new CallMediaRecognizeDtmfOptions( new CommunicationUserIdentifier("<target-user>"), 5) // Max tones to collect .setInterToneTimeout(Duration.ofSeconds(5)) .setStopTones(List.of(stopTones)) .setInitialSilenceTimeout(Duration.ofSeconds(15)) .setPlayPrompt(new TextSource().setText("Enter your account number followed by pound.")); callMedia.startRecognizing(recognizeOptions); ``` ## Recognize Speech ```java // Speech recognition with AI CallMediaRecognizeSpeechOptions speechOptions = new CallMediaRecognizeSpeechOptions( new CommunicationUserIdentifier("<target-user>")) .setEndSilenceTimeout(Duration.ofSeconds(2)) .setSpeechLanguage("en-US") .setPlayPrompt(new TextSource().setText("How can I help you today?")); callMedia.startRecognizing(speechOptions); ``` ## Call Recording ```java CallRecording callRecording = client.getCallRecording(); // Start recording StartRecordingOptions recordingOptions = new StartRecordingOptions( new ServerCallLocator("<server-call-id>")) .setRecordingChannel(RecordingChannel.MIXED) .setRecordingContent(RecordingContent.AUDIO_VIDEO) .setRecordingFormat(RecordingFormat.MP4); RecordingStateResult recordingResult = callRecording.start(recordingOptions); String recordingId = recordingResult.getRecordingId(); // Pause/resume/stop callRecording.pause(recordingId); callRecording.resume(recordingId); callRecording.stop(recordingId); // Download recording (after RecordingFileStatusUpdated event) callRecording.downloadTo(recordingUrl, Paths.get("recording.mp4")); ``` ## Add Participant to Call ```java CallConnection callConnection = client.getCallConnection(callConnectionId); CommunicationUserIdentifier participant = new CommunicationUserIdentifier("<user-id>"); AddParticipantOptions addOptions = new AddParticipantOptions(participant) .setInvitationTimeout(Duration.ofSeconds(30)); AddParticipantResult result = callConnection.addParticipant(addOptions); ``` ## Transfer Call ```java // Blind transfer PhoneNumberIdentifier transferTarget = new PhoneNumberIdentifier("+14255559999"); TransferCallToParticipantResult result = callConnection.transferCallToParticipant(transferTarget); ``` ## Handle Events (Webhook) ```java import com.azure.communication.callautomation.CallAutomationEventParser; import com.azure.communication.callautomation.models.events.*; // In your webhook endpoint public void handleCallback(String requestBody) { List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(requestBody); for (CallAutomationEventBase event : events) { if (event instanceof CallConnected) { CallConnected connected = (CallConnected) event; System.out.println("Call connected: " + connected.getCallConnectionId()); } else if (event instanceof RecognizeCompleted) { RecognizeCompleted recognized = (RecognizeCompleted) event; // Handle DTMF or speech recognition result DtmfResult dtmfResult = (DtmfResult) recognized.getRecognizeResult(); String tones = dtmfResult.getTones().stream() .map(DtmfTone::toString) .collect(Collectors.joining()); System.out.println("DTMF received: " + tones); } else if (event instanceof PlayCompleted) { System.out.println("Audio playback completed"); } else if (event instanceof CallDisconnected) { System.out.println("Call ended"); } } } ``` ## Hang Up Call ```java // Hang up for all participants callConnection.hangUp(true); // Hang up only this leg callConnection.hangUp(false); ``` ## Error Handling ```java import com.azure.core.exception.HttpResponseException; try { client.answerCall(options); } catch (HttpResponseException e) { if (e.getResponse().getStatusCode() == 404) { System.out.println("Call not found or already ended"); } else if (e.getResponse().getStatusCode() == 400) { System.out.println("Invalid request: " + e.getMessage()); } } ``` ## Environment Variables ```bash AZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com # Required for all auth methods AZURE_COMMUNICATION_CONNECTION_STRING=endpoint=https://...;accesskey=... # Alternative to Entra ID auth CALLBACK_BASE_URL=https://your-app.com/api/callbacks # Required for webhook callbacks AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production ``` ## Trigger Phrases - "call automation Java", "IVR Java", "interactive voice response" - "call recording Java", "DTMF recognition Java" - "text to speech call", "speech recognition call" - "answer incoming call", "transfer call Java" - "Azure Communication Services call automation"
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.