Microsoft Foundry의 Voice Live API는 음성으로 대화하는 에이전트를 만드는 데 사용되는 API입니다. 이와 관련된 .NET SDK (Azure.AI.VoiceLive)가 1.2.0 버전으로 업데이트되어, 기존에 제공된 기능을 한 번에 살펴보고 싶어 조사하게 되었습니다. 이전 기사에서는 SDK 1.1.0 시점에서는 '공식 SDK로는 2026-06-01-preview를 선택할 수 없으므로, 최신 preview 버전을 사용하려면 API를 직접 호출하는 방법밖에 없다'고 설명했지만, 1.2.0 버전에서 이 전제가 바뀌었습니다.
위치적으로 볼 때, API 측면에서 Preview 제공 등 기능이 선행 구현된 상태이며, SDK는 나중에 API에 맞춰 기능을 따라가는 구조인 것 같습니다. 다만, API의 경우 기본적으로 API를 실행할 수 있는 메커니즘만 있다면 개발 언어 등의 제약은 크게 받지 않습니다. 반면, 메시지 등 사용자가 직접 구축해야 하는 부분이 많아 다소 번거로운 측면이 있습니다.
SDK가 제공됨으로써 실용적인 면에서 큰 변화는, 이전에는 API를 직접 호출하지 않으면 시도할 수 없었던 기능들이 몇 줄의 코드로 작성 가능해졌다는 점이라고 생각합니다. 사진으로 아바타를 생성하는 것, WebSocket을 통해 받는 아바타 영상, MCP(Multi-Channel Protocol), 툴 대기 시간 동안의 짧은 발화(interim response) 등이 이에 해당합니다.
본 기사에서는 SDK 1.2.0에서 선택 가능해진 API 버전, 추가된 타입, 그리고 SDK에 포함되지 않은 기능들의 분류, 그리고 1.1.0 대비 변경 사항을 소개합니다.
이 글은 앞으로 이어질 Voice Live 기능 해설 시리즈의 기반이 됩니다. 이후 회차에서는 'SDK 1.2.0 + API 2026-07-15 (GA)'를 기준으로 기능을 하나씩 다룰 예정입니다.
검증에 사용된 코드는 다음과 같습니다 (SDK 1.2.0 대응 완료). [IMG:N]
본 기사는 2026년 10월 기준의 정보입니다. 대상은 .NET SDK (Azure.AI.VoiceLive) 1.2.0과 Voice Live API 2026-07-15 (둘 다 작성 시점 기준 최신 버전)입니다. 2026-07-15는 각 언어의 SDK에서 기본 버전으로 설정되어 있습니다.
.NET SDK에서는 연결할 API 버전을 VoiceLiveClientOptions.ServiceVersion을 통해 선택합니다. 1.1.0과 1.2.0에서 선택 가능한 버전은 다음과 같습니다:
| ServiceVersion | API 버전 | 구분 | 1.1.0 | 1.2.0 |
|---|
V2025_10_01 | 2025-10-01 | GA | 〇 | 〇 |
V2026_01_01_PREVIEW | 2026-01-01-preview | preview | 〇 | 〇 |
V2026_04_10 | 2026-04-10 | GA | - | 〇 |
| (없음) | 2026-06-01-preview | preview | - | - |
V2026_07_15 | 2026-07-15 | GA | - | 〇 |
2026-06-01-preview는 1.2.0에서도 선택할 수 없습니다. 즉, '6월 버전은 SDK에서 선택할 수 없다'는 점은 변함이 없으며, 오히려 6월 버전의 기능 대부분이 GA (2026-07-15)로 SDK에서 사용 가능해졌다고 하는 것이 더 정확하다고 생각합니다.
API 버전은 VoiceLiveClientOptions를 만들 때만 지정할 수 있으며, 세션을 시작할 때는 변경할 수 없습니다. 버전을 바꿀 때는 옵션과 클라이언트를 다시 만들어야 합니다. 예를 들어, 처음에 다음과 같이 작성합니다:
var clientOptions = new VoiceLiveClientOptions(
VoiceLiveClientOptions.ServiceVersion.V2026_07_15);
var endpoint = new Uri("https://<your-resource>.cognitiveservices.azure.com");
...
2026-07-15의 API 레퍼런스는 MS Learn에서 공개되어 있습니다.
What's new의 핵심은 다음과 같습니다:
2026-06-01-preview 대비 추가된 것은 세션의 expires_at
(서버가 결정하는 세션 만료 기한) 외에, 6월 버전의 native voice, client EC reference, streaming text input, parallel tool calls, hosted agent invocation은 07-15에서도 계속 사용 가능합니다.
- smart turn detection과 WebRTC는 preview 상태를 유지합니다.
이를 SDK 1.2.0 내용과 비교하면, 기능별 대응은 다음과 같습니다. SDK 열의 범례는, 〇가 타입으로 작성 가능함, △가 타입은 있으나 작성에 수고가 필요함, ×가 SDK에서 작성 불가능함 (API를 직접 호출해야 함)입니다.
| 기능 | API 2026-07-15 |
|---|
| SDK 1.2.0 | SDK에서의 작성 방식 |
| --- | --- |
| Photo avatar (scene 포함) | 〇 |
| ... | InvokeInput 및 ServerEventResponseInvocationDelta |
세션 만료 기한 (expires_at) | 〇 (07-15에서 추가) |
| Interim response | 〇 |
| client EC reference | 〇 |
| native voice / streaming text input | 〇 |
| API를 직접 호출해야 함 | |
foundry_agent 도구 | 〇 (2026-04-10부터) |
| smart turn detection / WebRTC 음성 연결 | preview |
샘플 SDK 콘솔에서는 표에서 〇인 기능 중 다음 10가지 기능을 2026-07-15로 실기 확인했습니다.
Photo avatar / Photo avatar + scene / WebSocket 영상 (response.video.delta) / azure-personal voice / Semantic EOU (다국어) / Auto-truncation / MCP 서버 / Interim response / Parallel tool calls / avatar-sync voice
이 표의 〇△×는 SDK가 따라잡을 때마다 바뀝니다. 6월 버전을 API 직접 호출로 검증했던 기능들은 GA화와 1.2.0 대응에 힘입어 SDK 측으로 이동했습니다. 현재 API를 직접 호출하고 있는 foundry_agent 역시, SDK가 대응한다면 〇로 바뀔 것이라고 생각합니다.
1.2.0에서 6월 버전의 기능이 한꺼번에 SDK에 들어왔다고 생각했지만, 1.1.0과 1.2.0의 타입을 비교해 보니, 늘어난 타입은 단 6개였습니다 (삭제된 타입은 없습니다). photo avatar나 WebSocket 영상, interim response, MCP의 타입은 사실 1.1.0부터 존재했습니다.
1.1.0에 타입이 있었음에도 'SDK로는 시도할 수 없다'고 판단했던 이유는, 타입이 있어도 그 기능을 반환해 주는 API 버전을 선택할 수 없었기 때문입니다.
알기 쉬운 예가 WebSocket 영상입니다. ServerEventResponseVideoDelta 타입은 1.1.0에 있었지만, 1.1.0에서 선택 가능한 최신 2026-01-01-preview의 서버 이벤트에는 response.video.delta가 없습니다. 즉, 받을 타입은 존재하지만, 전달해 주는 버전과 연결할 수 없는 상태였습니다.
1.2.0에서 바뀐 것은 타입이 아니라, 2026-04-10 / 2026-07-15와 같은 GA 버전에 연결될 수 있게 된 것입니다. 이로써 1.1.0부터 존재했던 타입들이 실제로 사용 가능해졌습니다.
1.1.0 시절에 이것들을 시도하려면 API를 직접 호출해야 했지만, 지금은 SDK의 몇 줄 코드로 작성할 수 있습니다. 예를 들어 사진으로 만드는 아바타는 타입을 구성하여 Avatar에 넣기만 하면 됩니다.
options.Avatar = new AvatarConfiguration(character, customized)
{
AvatarKind = AvatarConfigKind.PhotoAvatar,
...
}
각 기능의 상세 내용은 이후 시리즈에서 하나씩 다룰 예정입니다.
1.2.0에서 추가된 타입과 1.1.0부터 존재했던 타입 목록
조사 방법: NuGet 패키지에 포함된 XML 문서에서 타입과 멤버 목록을 추출하여 버전별로 차이점을 비교했습니다. XML에는 internal 타입도 포함되므로, 공개 범위는 어셈블리 메타데이터(System.Reflection.Metadata를 사용하여 TypeAttributes 읽기)를 통해 확인하고 있습니다.
| 1.2.0에서 추가된 타입 | 대응하는 기능 | 공개 범위 |
|---|
EchoCancellationReferenceSource | client EC reference | public |
ServerEventResponseInvocationDelta | hosted agent invocation | public |
AzureRealtimeNativeVoice | azure-realtime-native voice | internal |
AzureRealtimeNativeVoiceName | 동상 (위와 동일) | internal |
ClientEventInputTextDelta | streaming text input | internal |
ClientEventInputTextDone | 동상 (위와 동일) | internal |
타입이 아닌 멤버로 추가된 것은 다음과 같습니다.
ServiceVersion.V2026_04_10
/V2026_07_15
VoiceLiveSessionOptions.AllowParallelToolCalls
(parallel tool calls)
AudioEchoCancellation.ReferenceSource
/Channels
(client EC reference)
ResponseCreateParams.InvokeInput
(hosted agent invocation)
VoiceLiveSessionResponse.ExpiresOn
(expires_at)
1.1.0부터 존재했던 타입은 다음과 같습니다.
| 기능 | 타입 (1.1.0부터 존재) |
|---|
| Photo avatar | AvatarConfigKind.PhotoAvatar / PhotoAvatarBaseMode / SceneParams |
| WebSocket 영상 | AvatarOutputProtocol / ServerEventResponseVideoDelta |
| Interim response | LlmInterimResponseConfig / StaticInterimResponseConfig |
| MCP | VoiceLiveMcpServerDefinition / McpApprovalKind |
| Personal voice / avatar-sync voice | AzurePersonalVoice / AzureAvatarSyncVoice |
| Semantic EOU | AzureSemanticEouDetectionMultilingual 외 |
| Auto-truncation | AzureSemanticVadTurnDetection.AutoTruncate |
1.2.0에서도 SDK에서 바로 사용할 수 없는 기능들이 남아 있습니다. 여기서 주의해야 할 점은, SDK에 해당 타입이 없다는 것과 그 기능이 preview 버전이라는 것은 별개의 문제라는 것입니다. 기능 표에서 '×'와 '△'로 표시된 항목들을 이유별로 살펴보겠습니다.
Foundry 에이전트를 세션의 도구(tool)로 호출하는 foundry_agent
도구(공식적인 chat-supervisor 패턴)는 이미 2026-04-10(GA) 리퍼런스에서 정의되어 있습니다. 그럼에도 불구하고 SDK 1.2.0에는 해당 타입이 없습니다.
이는 preview 버전이라서가 아니라, SDK 구현이 API를 따라가지 못했기 때문입니다. session.update의 tools에 JSON 형태로 작성하면 GA API로 사용할 수 있습니다. 이 시리즈에서도 이번 한 번만은 API를 직접 호출하는 방식으로 작성할 예정입니다.
hosted agent invocation은 Invocations 프로토콜을 통해 작동하는 호스트 에이전트와 음성으로 대화할 수 있는 기능입니다. Voice Live는 에이전트가 반환하는 텍스트를 읽어주고, 그 외의 이벤트는 response.invocation.delta로 그대로 클라이언트에게 전달합니다. 어떤 이벤트가 도착할지는 에이전트의 구현에 따라 다릅니다. 이는 음성으로 반환되는 내용과는 별개로, 에이전트 고유 데이터를 클라이언트에 전달하기 위한 메커니즘인 것으로 보입니다. 에이전트에게 입력은 response.create의 invoke_input을 통해 전달할 수 있습니다. SDK 1.2.0에는 수신용 ServerEventResponseInvocationDelta가 포함되어 있습니다.
foundry_agent는 이름만 비슷할 뿐이므로, 혼동하지 않도록 주의해야 합니다.
1.2.0에서 추가된 6가지 타입 중 4개는 internal이었습니다.
AzureRealtimeNativeVoice (native voice)와 ClientEventInputTextDelta/Done (streaming text input)은 타입 자체는 SDK 내에 존재하지만, 앱에서는 사용할 수 없습니다.
둘 다 07-15 기준으로 GA(General Availability)로 '계속 사용 가능'하다고 명시된 기능이므로, 사용하려면 API를 직접 호출해야 합니다.
07-15의 What's new에는 다음과 같이 명시되어 있습니다.
Smart turn detection and WebRTC remain in preview.
— Voice Live 2026-07-15
API reference
SDK 1.2.0이 가진 발화 종단(EOU: End Of Utterance) 감지 타입 역시, semantic 계열의 세 가지(AzureSemanticEouDetection/...En/...Multilingual)만 존재하며, smart turn detection에 해당하는 타입은 없습니다.
공식 문서에서 preview로 제공되고 SDK에도 없는 기능이므로, 이는 'preview로 제공되는 기능'입니다. 2026-06-01-preview를 API를 직접 호출하여 지정했을 때, smart turn detection은 실제 기기에서 작동했습니다.
지금까지의 기능을 API로 구현하려면, SDK가 대신 처리해주던 부분을 개발자가 직접 작성해야 합니다.
- 메시지(
session.update 등)의 JSON을 직접 구성합니다. 모든 키 이름은 snake_case여야 하며, 수동으로 작성하면 오류를 범하기 쉽습니다.
- preview 기능은 연결할 API 버전에 preview 버전(
2026-06-01-preview 등)을 지정해야 합니다.
- client EC reference처럼, 연결 시 쿼리(
&features=client_ec_reference:true)로 활성화하는 기능이 있습니다.
도구 호출 대기 시간 동안 '확인하겠습니다'와 같은 짧은 발화를 재생시키는 interim response에는 설정용 LlmInterimResponseConfig라는 타입이 있습니다. 그런데 이를 수신하는 VoiceLiveSessionOptions.InterimResponse의 타입이 BinaryData입니다.
따라서, 타입을 이용해 구성한 후 개발자가 직접 직렬화(serialize)하여 전달해야 합니다.
var interim = new LlmInterimResponseConfig
{
Triggers = { InterimResponseTrigger.Tool, InterimResponseTrigger.Latency },
...
ModelReaderWriter.Write를 통하면 실제로 전송되는 JSON의 키 이름(interim_response/llm_interim_response 등 모두 snake_case)이 올바르게 출력됩니다. JSON을 수동으로 작성할 경우 키 이름을 잘못 지정하기 쉬우므로, 타입 시스템을 거칠 수 있는 상황에서는 사용하는 것이 더 안전합니다.
client EC reference는 에코 제거 참조에 있어 서버 내부 TTS가 아닌 실제 스피커에서 발생한 소리를 사용하는 기능입니다. 1.2.0부터 EchoCancellationReferenceSource를 통해 지원됩니다.
AudioEchoCancellation.ReferenceSource와 /Channels가 추가되었기 때문에, 설정 자체는 타입으로 작성할 수 있습니다.
다만, 전송할 음성을 "마이크"와 "실제 재생음"을 번갈아 배치한 스테레오 PCM으로 만들어야 합니다. 이 참조 음성의 시간 동기화가 어려우며, 타입이 있어도 구현의 대부분은 앱 측에서 이루어져야 합니다. 연결 시 &features=client_ec_reference:true를 추가해야 하는 점도 함께 자세히는 음성 입력 품질 부분에서 다루겠습니다.
1.2.0을 작업하면서 걸린 점 세 가지를 적어드립니다. 모두 컴파일은 통하기 때문에 알아차리기 어렵습니다.
음성의 SessionUpdateResponseAudioDelta.Delta는 디코드된 BinaryData이지만, 영상의 ServerEventResponseVideoDelta.Delta는 base64 형식의 string 그대로입니다. 둘 다 IntelliSense 설명이 "base64-encoded"라서 설명만으로는 구별할 수 없습니다. 타입을 보고 판단해 주세요.
case ServerEventResponseVideoDelta videoDelta:
// 음성과 달리 base64 문자열 그대로 도착하므로 직접 디코드해야 함
byte[] frame = Convert.FromBase64String(videoDelta.Delta);
...
AzureAvatarSyncVoice 생성자가 받는 것은 기본 모델(PersonalVoiceModels)입니다. 그런데 PersonalVoiceModels는 문자열로부터 암시적 변환이 가능하기 때문에, 아바타 이름을 전달해도 컴파일이 통하고 아바타 이름이 모델명으로 전송됩니다.
아바타 이름은 AvatarConfiguration의 Character에 넣습니다 (+ Customized = true).
semantic EOU와 smart turn detection 모두 VAD의 end_of_utterance_detection에 중첩하여 작성하기 때문에 설정 형태가 매우 유사합니다. 샘플 SDK 콘솔에서도 초기에는 "smart end-of-turn"이라는 이름으로 semantic EOU를 전송했었습니다 (현재는 semantic_eou로 이름이 변경되었습니다).
semantic EOU와 smart turn detection은 별개의 개념입니다. SDK 1.2.0에서 사용할 수 있는 것은 semantic EOU 쪽입니다.
1.1.0에서 1.2.0으로의 마이그레이션은 간단합니다. 샘플에서는 패키지 버전을 올리는 것만으로 빌드가 통했고, 테스트도 모두 통과했습니다. 의존성은 점진적으로 Azure.Core가 1.57.0에서 1.61.0으로 올라가고 System.ClientModel 1.15.0이 포함됩니다.
SDK 1.2.0이 의존하는 Azure.Core (1.61.0)에는 DefaultAzureCredential과 같은 자격 증명(credential) 타입이 포함되어 있습니다. 오래된 Azure.Identity (샘플에서는 1.14.2)를 참조한 상태로 두면, 동일한 타입이 중복 정의되어 CS0433 오류가 발생합니다. 이 경우, Azure.Identity의 참조를 제거해 주세요. 새로운 Azure.Identity (1.21.0 등)에서는 해당 타입이 Azure.Core 쪽으로 이동한 것으로 보입니다.
1.1.0의 베타 버전 (1.1.0-beta.4 등)에서 업그레이드하는 경우, 베타와 GA 사이에서 이름이 변경된 타입에 걸릴 수 있습니다. 1.0.0에는 애초에 MCP나 아바타 종류의 타입이 없기 때문에 영향을 받는 것은 베타 단계에서 선행 사용했던 사용자입니다. 샘플에서 수정한 부분은 다음 세 가지입니다.
| 1.1.0-beta.4 | 1.1.0 (GA) 이후 |
|---|
MCPApprovalType | McpApprovalKind |
AvatarConfiguration.Type | AvatarConfiguration.AvatarKind |
| URL을 문자열로 전달 | System.Uri로 전달 |
options.Tools.Add(new VoiceLiveMcpServerDefinition("deepwiki", new Uri(url))
{
RequireApproval = new RequireApprovalOption(McpApprovalKind.Never)
...
- SDK 1.2.0에서는
2026-04-10
/
2026-07-15
(둘 다 GA)를 선택할 수 있게 되었습니다. 2026-06-01-preview는 선택할 수 없습니다. - 1.2.0에서 바뀐 것은 타입 자체가 아니라, 1.1.0부터 존재했던 타입을 실제로 사용할 수 있는 GA 버전과 연결되게 되었다는 점입니다.
- 1.2.0에서 추가된 타입은 6개이며, 그중 4개는 internal입니다.
- SDK로 작성할 수 없는 기능은 API가 GA 버전으로 출시되었으나 SDK가 아직 미지원하는 것들(foundry_agent, native voice, streaming text input)과, API에서도 preview 단계인 것들(smart turn detection, WebRTC)로 나뉩니다. - interim response와 client EC reference는 타입은 존재하지만 작성하기에 번거로움이 따릅니다.
- 기능이 GA 버전으로 SDK에 공개된 타입이 있다면 SDK를 사용하고, 그 외의 것은 API를 직접 호출하여 작성합니다.
- 1.1.0에서 1.2.0으로 마이그레이션할 때는 코드를 수정하지 않고 할 수 있었습니다.
다음부터는 이 SDK 1.2.0 + 2026-07-15를 기반으로 기능을 하나씩 다루겠습니다.
| 회차 | 테마 | SDK 1.2.0에서 작성 가능한지 |
|---|
| 1 | 에이전트의 '틈' 메우기 (semantic EOU / auto-truncation / interim response) | 〇 |
| ... | × API 직접 호출 | |
| 5 | Personal Voice (공개됨) | 〇 |
| 6 | 아바타 사용 구분 (표준・사진・비디오) | 〇 |
| 7 | WebSocket 비디오와 WebRTC | 〇 |
| 특별 | WebRTC 음성 연결에 .NET의 SIPSorcery로 연결하기 | × API 직접 호출(preview) |