livekit sip api에서 create_sip_participant 와 transfe...
# ask-ai
l
livekit sip api에서 create_sip_participant 와 transfer_sip_participant 이 둘의 차이점이 뭐야?
t
Thanks for reaching out, Dan(송희웅). I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
요청하신 부분( LiveKit SIP API의 `create_sip_participant`와 `transfer_sip_participant`의 차이)에 대해 정리해드릴게요. •
create_sip_participant
◦ 목적: 새 통화를 걸어 새로운 SIP 참가자를 LiveKit 룸에 추가합니다. ◦ 동작: 지정한 전화번호로 아웃바운드 콜을 시작하고, 상대가 응답하면 그 참가자가 룸에 참여합니다. ◦ 주요 파라미터:
sip_trunk_id
,
sip_call_to
,
room_name
,
participant_identity
, 등. ◦ 사용 예: 룸안에 아직 없던 외부 번호를 호출해서 새 참가자를 만들고 싶을 때 사용합니다. •
transfer_sip_participant
◦ 목적: 이미 룸에 있거나 통화 중인 기존 SIP 참가자를 다른 번호(또는 SIP 대상으로)로 전송(transfer)합니다. ◦ 동작: SIP REFER 같은 메커니즘으로 현재 세션을 다른 대상에게 이전하고, 기존 세션은 종료됩니다. ◦ 주요 파라미터:
room_name
,
participant_identity
,
transfer_to
. ◦ 사용 예: 통화 중인 상담원을 외부 번호로 콜백/콜전달 하거나, 현재 통화를 다른 라인으로 연결하고 싶을 때 사용합니다. ◦ 참고: SIP 트렁크 공급자에서 SIP REFER 전송을 허용해야 제대로 동작합니다. 핵심 차이 요약: •
create_sip_participant
= 새 통화를 "생성"해서 룸에 참가자 추가 •
transfer_sip_participant
= 이미 있는 통화를 "전송(이동)"해서 다른 번호로 연결 더 도와드릴 부분이 있을까요? 예를 들어 사용하려는 시나리오(아웃바운드 콜, 통화 중 전달 등)를 알려주시면 어떤 API를 써야 할지 구체적으로 추천드릴게요. Sources: Agents telephony integration | LiveKit Documentation | SIP Lifecycle Management Agent | LiveKit Documentation
l
transfer_sip_participant
으로는 상대방과 전화가 연결되었는지까지의 여부를 알수는 없는데,
create_sip_participant
으로는 가능한것 같아. 그러면
create_sip_participant
으로 전화를 걸고 연결에 성공한후 세션을 끝내버리면 두명에게 연결된 전화가 끊어질까?
t
좋은 질문이에요 — `create_sip_participant`로 전화를 걸어 연결이 성공한 후 세션을 끝내면 호출된 쪽(외부 SIP/전화) 연결도 끊깁니다. 간단히 요약드리면: • `create_sip_participant`로 생성된 SIP 참가자는 LiveKit 룸의 참가자입니다. 따라서 룸이나 세션이 종료되면 해당 참가자 연결도 함께 종료됩니다. • `wait_until_answered=True`로 호출하면 상대가 응답했는지 확인할 수는 있지만, 응답 성공 후에도 통화는 여전히 룸 세션에 종속되어 있습니다. • 룸을 삭제하거나 세션(예: agent 세션)을 종료하면 그 룸에 있는 모든 참가자(생성된 SIP 참가자 포함)가 제거되어 통화가 끊깁니다. 원하시는 동작에 따라 추천드리는 선택지: • 통화를 유지하려면 세션/룸을 종료하지 않고 유지하세요. • 통화를 LiveKit 세션과 분리해 유지해야 한다면, SIP 트렁크 제공자 쪽에서 직접 콜을 브리지하거나, `transfer_sip_participant`를 이용해 외부로 콜을 전송(참고: SIP REFER 필요)하는 방식을 고려해야 합니다. (`transfer_sip_participant`는 기존 통화를 다른 번호로 이전하나, 전송 성공 여부를 별도로 확인하는 로직이 필요할 수 있습니다.) 원하시면 지금 사용하시는 시나리오(예: 상담원 콜백, 외부 브리지로 이관 등)를 알려주세요. 어떤 API와 흐름이 가장 적합한지 구체적으로 도와드릴게요. Sources: SIP Lifecycle Management Agent | LiveKit Documentation | Job lifecycle | LiveKit Documentation | Agents telephony integration | LiveKit Documentation
l
transfer_sip_participant
으로 성공 여부를 별도로 확인하는 로직을 추가하는 방법이 있어?
t
좋은 질문이에요 — `transfer_sip_participant`로 전달을 시도한 뒤 성공 여부를 확인하는 방법을 정리해 드릴게요. 핵심은 LiveKit에서 전달 자체의 성공 이벤트를 별도로 제공하지 않기 때문에, 참가자 이벤트와 참가자 속성 변화를 조합해 성공 여부를 추론하는 방식입니다. 우선 어떤 부분에 답변드리는지 간단히 확인합니다: • "transfer_sip_participant 호출 후 상대방(전송 대상)이 실제로 연결되었는지 확인하는 로직"에 대해 설명드릴게요. 추천하는 확인 방법들(우선순위 포함): 1. participant_attributes_changed에서
sip.callStatus
모니터링 (권장) ◦
sip.callStatus
값이 `active`로 바뀌면 전달이 성공(수신자가 통화를 받음)한 것으로 판단할 수 있습니다. ◦ 값 예시:
dialing
,
ringing
,
active
,
hangup
,
automation
등. ◦ 구현 포인트:
transfer_sip_participant
호출 후 해당 참가자에 대한
participant_attributes_changed
이벤트를 수신하여 상태 변화를 확인하세요. 1. participant_disconnected 이벤트로 원래 참가자 종료 확인 ◦ 전달이 성공하면 원래 SIP 참가자(룸에 있던 쪽)가 룸에서 제거됩니다. `participant_disconnected`가 발생하면 전달이 완료됐을 가능성이 높습니다. ◦ 주의: 단순한 종료(hangup)와 구분해야 하므로 `sip.callStatus`와 함께 보면 더 정확합니다. 1. participant_connected 이벤트로 전송 대상의 새 참가자 연결 확인 ◦ 전달 대상이 같은 룸에 새 SIP 참가자로 들어오는 구성이라면
participant_connected
이벤트로 수신 여부를 확인할 수 있습니다. 1. API 호출 예외 처리로 초기 요청 실패 감지 ◦
transfer_sip_participant
호출 자체가 실패하면 예외가 발생하므로, 이 경우는 즉시 전달 시도 자체가 실패한 것으로 처리합니다. 다만 호출 성공은 전달 시도만 의미하며 실제 연결 성공은 위 이벤트로 확인해야 합니다. 추가 고려사항 및 구현 팁: • SIP 트렁크 설정: SIP REFER(transfer) 기능이 트렁크 쪽에서 활성화되어 있어야 합니다. 트렁크 공급자에서 전송 허용 설정이 필요합니다(예: Twilio의 PSTN Transfer 활성화 등). • 타이밍: 전달 과정에서 상태 변화가 순차적으로(예:
dialing
→
ringing
→
active
→
hangup
) 발생할 수 있으니, 상태 전환 로직을 꼼꼼히 처리하세요. • 안정성: 이벤트를 기반으로 판단하므로, 상태 변화가 오지 않거나 타임아웃이 발생하는 경우(예: 전달 대기 시간이 지나면 실패로 처리)에 대한 타임아웃/재시도 정책을 두는 것이 좋습니다. • 알림/연동: 성공/실패 상태를 외부 시스템(Webhook, DB 업데이트, 알림 등)에 전파하면 운영상 유용합니다. 간단한 예시(파이썬, 이벤트 핸들러 아이디어):
Copy code
@ctx.room.on("participant_attributes_changed")
def on_attributes_changed(changed_attributes, participant):
    if participant.kind != rtc.ParticipantKind.PARTICIPANT_KIND_SIP:
        return
    if 'sip.callStatus' in changed_attributes:
        status = changed_attributes['sip.callStatus']
        if status == 'active':
            # 전달 성공 처리
        elif status == 'hangup':
            # 전달 실패/종료 처리
원하시면 제가 도와드릴 수 있는 추가 항목: • 현재 사용 중인 SIP 트렁크(예: Twilio 등)와 설정을 알려주시면 REFER 활성화 여부 및 추가 설정 팁을 드릴게요. •
sip.callStatus
기반으로 구체적 타임아웃/재시도 로직 예시 코드를 원하시면 제공해 드릴게요. 어떤 방식으로 구현할 계획이신가요? (예: 이벤트 기반 알림 전송, DB에 상태 기록, 사용자에게 실시간 피드백 등) 그러면 더 구체적으로 맞춰서 도와드릴게요. Sources: Agents telephony integration | LiveKit Documentation | SIP Lifecycle Management Agent | LiveKit Documentation
l
transfer_sip_participant
로 전화를 걸면, 즉 API가 성공하면 상대방과의 통화가 실제로 연결되기 전에 "participant_disconnected" 이벤트가 발생되고 session이 끝나버리는데, participant_attributes_changed 이벤트로 상대방과 실제 통화가 연결되었는지 알수가 있어?
t
질문 감사해요 — 핵심은 “API 호출이 성공(전달 시도 시작)한 직후 `participant_disconnected`가 발생하고 세션이 끝나버리는데, 실제로 상대방이 받아서 통화가 연결된 시점을 `participant_attributes_changed`로 확인할 수 있느냐”입니다. 답변은 아래와 같습니다. 요약(결론) • 네. `participant_attributes_changed`에서의
sip.callStatus
변경을 모니터링하면 실제로 전달 대상이 전화를 받아 통화가 연결된(
active
) 시점을 감지할 수 있습니다. • 다만
transfer_sip_participant
호출 직후에 원래 참가자가 룸에서 끊어지는(
participant_disconnected
) 것은 정상일 수 있으며, 이것만으로는 전달 성공(상대가 받음)을 보장하지 않습니다. `sip.callStatus == 'active'`를 확인해야 실제 연결로 판단할 수 있습니다. 이유와 동작 흐름 • `transfer_sip_participant`는 LiveKit에서 기존 참가자 세션을 외부로 REFER(전송)하도록 요청합니다. API 호출 성공은 “전송 요청을 보냈다”는 의미이지, 상대가 수신하여 통화가 성사되었다는 보장은 아닙니다. • 전송을 시작하면 원래 룸에 있던 참가자는 즉시 제거될 수 있습니다(예: 룸의 세션 종결이나 참가기지 제거). 따라서 `participant_disconnected`가 먼저 오더라도 전달 대상의 연결 성공 여부는 별도로 확인해야 합니다. • 전달 대상의 실제 연결 상태는 SIP 관련 참가자 속성(
sip.callStatus
)로 보고됩니다. 값이 `active`가 되면 상대가 통화를 수락하여 연결된 것입니다. 구현 권장 방법(실무 팁) 1. transfer 요청은 try/except로 감싸 초기 실패를 즉시 감지 2. transfer 후에는 다음 이벤트들을 조합해서 판단 ◦ `participant_disconnected`: 원래 참가자(전달 대상이 아닌 쪽)가 룸에서 나갔음을 알림 — 전달 진행의 한 부분 ◦ `participant_attributes_changed`에서
sip.callStatus
검사: ▪︎
active
→ 전달 대상이 실제로 받았음(성공) ▪︎ `ringing`/`dialing` → 아직 응답 전 ▪︎
hangup
→ 전달 실패 또는 수신자가 거부했음 ◦ (가능하면) `participant_connected`: 전달 대상이 새 참가자로 들어오는 경우 이를 통해 추가 확인 가능 1. 타임아웃/재시도 정책: 만약 `sip.callStatus`가 일정 시간 내에 `active`로 바뀌지 않으면 실패로 처리하고 재시도하거나 로그/알림을 남기세요. 2. SIP 트렁크 설정 확인: 트렁크 제공자가 REFER를 제대로 처리하도록 설정되어 있어야
sip.callStatus
업데이트가 정확하게 들어옵니다. 간단한 이벤트 핸들러 예시(Python 스타일)
Copy code
@ctx.room.on("participant_attributes_changed")
def on_attributes_changed(changed_attributes, participant):
    if participant.kind != rtc.ParticipantKind.PARTICIPANT_KIND_SIP:
        return
    if 'sip.callStatus' in changed_attributes:
        status = changed_attributes['sip.callStatus']
        if status == 'active':
            # 전달 성공: 상대방과 실제 연결됨
        elif status == 'hangup':
            # 전달 실패 또는 거부
주의사항 • 일부 SIP 공급자나 설정에서는 REFER로 전송 후 상태 업데이트가 제대로 전달되지 않을 수 있습니다. 이 경우에는 트렁크 공급자 설정(예: Twilio의 PSTN Transfer 등)을 확인해야 합니다. • 이벤트 순서가 환경에 따라 달라질 수 있으므로(예: `participant_disconnected`가 먼저), 판단 로직은 복수의 신호(속성 변화 + 연결/종료 이벤트 + 타임아웃)를 조합하도록 설계하세요. 원하시면: • 현재 사용 중인 SIP 트렁크(예: Twilio 등)와 transfer 시 발생하는 실제 이벤트 로그(타임스탬프 포함)를 알려주시면, 어떤 이벤트 순서가 발생하는지 보고 더 구체적으로 실패/성공 판별 로직을 함께 설계해 드릴게요.
l
테스트해보니깐 status = 'hangup" 이 바로나와. 전화가 아직 연결중인데. 불가능한거지?
t
불편을 드려서 죄송해요 — 테스트에서
transfer_sip_participant
호출 후 곧바로 `sip.callStatus == 'hangup'`이 나오는 상황에 대해 답드릴게요. 간단 결론 • 불가능하다고 단정할 수는 없습니다. 그러나 "즉시 'hangup'이 나오는" 현상은 일반적으로 SIP 트렁크나 전달(REFER) 처리 흐름에서 상태 업데이트가 제대로 오지 않거나, 전달 과정에서 수신 쪽에서 즉시 끊음(또는 거부)이 발생했음을 뜻합니다. 따라서 원천 문제를 확인해야 합니다. 가능한 원인과 확인/해결 방법 1. SIP 트렁크가 REFER(transfer) 상태 업데이트를 전달하지 않음 ◦ 일부 제공자는 REFER 이후의 콜 진행상태(ringing/active)를 LiveKit으로 전달하지 않습니다. 이 경우 LiveKit은 전달 시도 후 곧바로 기존 세션을 정리하고 `hangup`을 보낼 수 있습니다. ◦ 조치: 트렁크 공급자(예: Twilio 등)의 "PSTN Transfer" 같은 설정이 켜져 있는지 확인하세요. 공급자 로그에서 REFER 이후 상태 이벤트가 발생하는지 확인해 주세요. 1. 전달 대상(수신자)이 즉시 거부하거나 회선 문제로 빠르게 종료됨 ◦ 전송 대상이 바로 거부(버튼 눌러 끊음)하거나 벨소리가 울리지 못하고 종료되는 경우 `hangup`이 빠르게 옵니다. ◦ 조치: 전달 대상 번호로 직접 수동 호출 테스트를 해보거나, 공급자 로그에서 해당 콜의 SIP 흐름(100 Trying, 180 Ringing, 200 OK, BYE 등)을 확인하세요. 1. LiveKit 이벤트/속성 업데이트 지연 또는 누락 ◦ LiveKit은 SIP 상태를 participant attributes로 노출하지만, 일부 이벤트가 누락되거나 순서가 섞일 수 있습니다. ◦ 조치: 전달 시 타임스탬프가 있는 로그를 남겨
transfer
요청,
participant_disconnected
, `participant_attributes_changed`의 발생 순서를 비교하세요. 1. REFER 타입(콜드/웜)과 구현 차이 ◦ 어떤 트렁크는 콜드(콜을 끊고 전송) 스타일로 처리해서 기존 참가자 종료가 빠르게 발생할 수 있습니다. ◦ 조치: 트렁크 문서에서 REFER 동작(콜 유지 vs 즉시 종료)을 확인하거나, 다른 REFER 모드가 가능한지 확인하세요. 권장 진단 절차 (우선순위) 1. transfer 요청 직후의 LiveKit 로그(타임스탬프 포함)와 SIP 트렁크 로그를 확보해 비교하세요. 2. 트렁크 공급자 콘솔에서 해당 콜의 SIP 메시지 흐름을 확인(100/180/200/BYE 등). 3. 트렁크에서 REFER 후 상태 이벤트(180/200)가 LiveKit으로 전송되는지 확인. 4. 단순 재현: 동일 번호로 일반 아웃바운드(
create_sip_participant
) 호출했을 때의 SIP 흐름과 비교해 차이를 보세요. 5. 임시 대안: 전달 성공 여부를 보장하려면, 전송 대신 먼저 `create_sip_participant`로 대상에 전화를 걸어 `wait_until_answered=True`로 확인한 뒤(상대 연결 확인) 룸 내부 로직으로 브리지/연결을 전환하는 패턴을 고려해보세요. 제가 도와드릴 수 있는 것 • 현재 사용 중인 SIP 트렁크 공급자(예: Twilio 등)와, transfer 시의 LiveKit 로그 또는 트렁크의 SIP 로그 일부(타임스탬프, 상태 코드)를 공유해 주시면, 발생 원인을 함께 분석해 드릴게요. • 또는
create_sip_participant
기반의 우회 패턴(먼저 통화 연결 확인 후 룸으로 합류) 예시 코드를 원하시면 제공해 드리겠습니다. 원하시면 지금 가지고 계신 로그의 핵심 타임스탬프/상태 라인(개인 정보/전화번호는 마스킹)만 붙여 보내주세요. 함께 살펴보고 원인 좁혀드릴게요.