스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
Push to Talk를 통한 음성 통신 향상
앱에 워키토키 통신을 구현하도록 지원합니다. 버튼을 탭하는 것만으로 빠른 통신이 가능하도록 Push to Talk 앱에 눈에 띄는 시스템 UI를 추가하는 방법을 알아보세요. PushToTalk 프레임워크에 대해 소개하고 백그라운드에서도 오디오를 송수신할 수 있도록 앱을 구성하는 방법을 보여드립니다. 이 세션을 최대한 활용하려면 앱 백엔드에서 오디오 전송을 처리하는 방법을 숙지하시는 것이 좋습니다. 또한 APN에 대한 기본적인 이해가 필요합니다.
리소스
관련 비디오
Tech Talks
WWDC22
-
다운로드
♪ 부드러운 힙합 음악 ♪ ♪ 안녕하세요, Kevin입니다 새 PushToTalk 프레임워크의 엔지니어죠 iOS 앱에서 워키토키 시스템을 경험하게 하는 프레임워크입니다 나중에 동료 Trevor 함께 여러분의 앱에서 어떻게 음성 통신을 향상시킬 수 있는지 이야기해 볼게요 우선 PushToTalk 프레임워크를 소개하고 앱에 어떻게 적용하는지 설명해 볼게요 다음은 PushToTalk용 앱을 구성하는 방법에 대해 알아보죠 그 후에 트레버가 이 프레임워크를 사용해 오디오를 송수신하는 방법을 살펴볼 거예요 마지막으로 트레버가 모범 사례를 소개할 겁니다 사용자의 배터리 수명을 유지하면서 Push To Talk 사용자 환경을 개선하는 사례죠 새 PushToTalk 프레임워크의 주요 기능부터 시작해 볼게요 PushToTalk 프레임워크로 워키토키 스타일의 경험을 사용자에게 제공하는 새로운 오디오 통신 앱을 iOS에 구축할 수 있습니다 Push To Talk 앱은 빠른 의사소통이 필수적인 건강 관리, 응급 서비스 등의 분야에서 활용도가 높죠 Push To Talk의 좋은 경험을 제공하려면 사용자가 오디오 전송 기능에 빠르게 접근하는 동시에 누가 응답하는지 확인하는 방법이 필요합니다 동시에 Push To Talk 앱은 사용자가 온종일 앱을 사용하는 동안 배터리 수명을 유지할 만큼 전원 효율적이어야 합니다 PushToTalk 프레임워크가 제공하는 API는 사용자가 직접 앱을 시작할 필요 없이 시스템 어디서나 접근할 수 있는 시스템 UI를 활용할 수 있습니다 시스템 UI로 오디오 전송을 빠르게 활성화할 수 있고 배경에서 앱을 실행해 오디오를 녹음하고 서버로 스트리밍할 수 있죠 시스템은 앱이 서버에서 오디오를 재생할 때 말하는 사람을 표시해서 사용자에게 투명성을 제공합니다 PushToTalk 프레임워크는 새로운 푸시 알림 유형을 도입해 새 오디오를 재생할 수 있을 때 앱에 알리는 방식이죠 앱에서 이 알림을 받으면 오디오를 스트리밍하고 재생할 수 있도록 배경에서 실행됩니다 PushToTalk 프레임워크는 기존 종단 간 통신 솔루션 및 백엔드 인프라와 호환되도록 설계했습니다 Push To Talk 워크플로를 앱에서 이미 구현했다면 PushToTalk 프레임워크를 기존 코드에 통합하는 건 쉬울 겁니다 앱은 프레임워크를 통해서 자체 오디오 인코딩 및 스트리밍 프로세스를 구현해 사용자 간에 오디오를 전송할 수 있습니다 앱에서 오디오 전송을 처리하는 방법에 대한 유연성이 제공되며 다른 플랫폼과도 호환됩니다 마지막으로 많은 Push To Talk 앱은 오디오 녹음과 전송을 트리거하기 위해 무선 블루투스 액세서리에 의존합니다 여러분의 앱은 CoreBluetooth 프레임워크으로 이런 액세서리와 계속 통합할 수 있고 PushToTalk에서 오디오 녹음을 트리거할 수 있습니다 첫 번째 Push To Talk 앱을 구축하는 경우 코드 설계를 시작할 때 이런 통합 관련 사항을 염두에 두세요 새 PushToTalk 프레임워크의 코드를 살펴보기 전에 Push To Talk 환경이 앱에서 어떻게 작동되는지 보여 드리고 싶네요 Trevor 제가 만든 데모 앱으로 PushToTalk의 작동을 보여 드릴게요 우선 가입 버튼을 눌러서 Push To Talk 세션과 연결합니다 우린 이 세션을 채널이라고 부르죠 일단 채널에 가입하면 채널의 다른 사용자와 오디오를 송수신할 수 있죠 Trevor 다른 동료들이 같은 채널에 가입해 있어서 온종일 통신할 수 있습니다 앱에서 오디오를 직접 보내 볼게요 마이크 버튼을 사용합니다 하지만 PushToTalk 프레임워크는 시스템의 어디서든 전송 기능에 접근할 수 있게 해 줘요 Push To Talk 채널이 활성화된 상태일 땐 상태 표시줄에 파란 알약 모양 도형이 나타납니다 이 도형을 누르면 시스템 UI가 표시되죠 시스템 UI에는 가입한 Push To Talk 채널 이름과 앱에서 제공하는 이미지가 표시돼서 사용자가 채널을 빠르게 알아볼 수 있어요 대화 버튼을 길게 누른 다음 시스템 차임벨을 기다렸다가 말을 시작해도 된다고 알리면 채널로 오디오를 전송할 수 있습니다
트레버, 안녕하세요 WWDC 발표 할 준비 됐어요? 오버 제 기기에서 Kevin의 메시지를 받았을 때 Kevin의 이름과 이미지가 포함된 알림이 와서 누구한테 메시지를 받는지 분명하게 알 수 있습니다 시스템 UI를 도입하면 Kevin의 메시지에 빠르게 응답하거나 하던 작업을 중단하지 않고도 채널을 떠날 수 있죠 Kevin을 기다리게 하긴 싫으니 지금 답할게요 Kevin, 금방 준비할게요 오버 PushToTalk 시스템 UI는 잠금 화면에서도 접근할 수 있어 사용자는 잠금을 해제할 필요 없이 메시지를 수신하고 응답할 수 있어요
네, 이따 봐요! 오버 이제 PushToTalk의 작동 방식을 설명했으니 이제 앱에 프레임워크를 통합하는 법을 알아볼게요 PushToTalk 프레임워크를 지원하기 위해선 Xcode 프로젝트를 몇 가지 수정해야 합니다 먼저 새 Push To Talk 배경 모드를 추가해야 합니다 그러면 백그라운드에서 앱을 실행해 Push To Talk 이벤트에 응답할 수 있죠 다음으로 프레임워크의 기능을 사용하려면 앱에 Push To Talk 기능을 추가해야 합니다 푸시 알림 기능은 APNS가 백그라운드에서 앱을 깨워 수신된 오디오를 재생할 때 필요합니다 마지막으로 앱은 사용자에게 녹음 권한을 요청하고 Info.plist에 마이크 목적 문자열을 포함해야 합니다 이제 코드를 통합할 준비가 됐습니다 Push To Talk의 첫 번째 단계는 채널에 가입하는 겁니다 채널은 시스템에 대해 Push To Talk 세션을 나타내고 설명합니다 앱은 채널 관리자를 통해 채널과 상호 작용 하죠 채널 관리자는 채널에 가입하고 오디오 전송이나 수신 같은 작업을 수행할 수 있는 앱의 기본 인터페이스입니다 채널에 가입하면 Push To Talk 시스템 UI를 사용할 수 있고 채널의 수명 내내 쓸 수 있는 APNS 장치 토큰을 받습니다 오디오 전송과 수신을 시작하려면 채널에 먼저 가입해야 합니다 첫 단계는 클래스 이니셜라이저를 사용해 채널 관리자를 만드는 겁니다 이 이니셜라이저를 사용하려면 채널 관리자 대리자와 채널 복원 대리자를 제공해야 하죠 이니셜라이저를 여러 번 호출하면 똑같은 공유 인스턴스가 반환되지만 인스턴스 변수에 채널 관리자를 저장하는 것을 권합니다 앱이 ApplicationDelegate의 didFinishLaunchingWithOptions 메서드로 시작되는 동안 채널 관리자를 최대한 빨리 초기화하는 게 중요합니다 이렇게 하면 채널 관리자가 빠르게 초기화되어 기존 채널을 복원할 수 있고 앱이 백그라운드에서 실행될 때 푸시 알림이 앱으로 전달됩니다 이제 채널에 가입할 준비가 끝났네요 여러분의 앱에서 누군가 채널에 가입한 경우 채널을 식별하는 UUID와 시스템에 채널을 설명하는 기술자를 제공해야 합니다 채널의 수명 내내 채널 관리자와 상호 작용 할 때 동일한 UUID가 사용되죠 기술자는 이름과 이미지를 포함합니다 채널을 대표하는 고유한 이미지를 제공하면 사용자가 시스템과 상호 작용 할 때 채널을 더 쉽게 식별할 수 있습니다 앱이 채널 관리자에서 requestJoin 메서드를 호출해 채널에 가입합니다 앱이 전면에서 실행 중일 때만 채널에 가입할 수 있다는 거 유의하세요 앱이 채널에 가입하면 채널 관리자 대리자의 didJoinChannel 메서드가 호출됩니다 이 대리자 메서드는 앱이 채널에 가입했음을 나타내죠 또 대리자의 receivedEphemeralPushToken 메서드가 호출되는데 Push To Talk 알림을 기기에 보내는 데 사용하는 APNS 토큰으로 이루어집니다 이 토큰은 Push To Talk 채널의 수명만큼만 활성화됩니다 APNS 푸시 토큰은 가변 길이이며 그 길이를 앱에 하드코딩하면 안 된다는 걸 명심하세요 다른 채널이 이미 활성화되어 있을 때 채널에 가입하려고 하면 채널 가입 요청이 실패할 수도 있습니다 이 경우 오류 처리기가 호출되고 오류는 실패 원인을 표시합니다 사용자가 채널을 탈퇴하면 대리자의 채널 탈퇴 메서드가 호출되죠 앱에서 프로그래밍 문제로 탈퇴를 요청해 탈퇴하는 경우도 있고 사용자가 시스템 UI에서 직접 탈퇴 버튼을 누르는 경우도 있습니다 채널 관리자 대리자는 채널 탈퇴 요청이 실패하면 호출되는 채널 탈퇴 오류 처리 메서드가 있습니다 PushToTalk는 앱 종료하거나 장치를 재부팅하고 앱을 다시 시작할 때 이전 채널 복원을 지원합니다 시스템이 이 작업을 수행하려면 시스템을 업데이트할 채널 기술자를 제공해야 합니다 여기 복원 대리자에게 캐시된 채널 기술자를 가져오는 도우미 메서드가 있습니다 시스템의 응답성을 유지하려면 이 메서드에서 최대한 빨리 돌아와야 하고 채널 기술자 검색을 위한 네트워크 요청처럼 장시간 실행되거나 차단되는 작업을 수행해선 안 됩니다 Push To Talk 세션의 수명 주기 동안 채널 정보가 변경될 때마다 기술자에 대한 업데이트를 제공해야 합니다 또 서비스 상태 개체를 사용해 네트워크 연결이나 서버 가용성에 대한 변경 사항을 시스템에 알려야 합니다 여기 채널에 대한 기술자를 업데이트하고 있습니다 이 메서드를 호출해서 채널 이름 또는 이미지를 업데이트할 수 있죠 이 예시에서는 앱의 서버 연결이 재연결 상태임을 나타내기 위해 시스템에 업데이트를 제공합니다 이 업데이트로 시스템 UI가 알맞게 변하고 서비스 상태가 연결 중이거나 연결이 끊긴 경우 사용자가 오디오를 전송하는 걸 막습니다 연결이 다시 설정되면 서비스 상태를 '준비'로 업데이트해야 합니다 이제 PushToTalk을 사용해 오디오를 보내고 받는 법을 다시 살펴볼게요 트레버, API의 나머지 부분을 설명할 준비 됐어요? 오버
네, 보내 주세요, 오버
지금까지 PushToTalk 프레임워크를 구성하는 방법을 배웠습니다 이제 오디오를 보내고 받는 법을 살펴보죠 PushToTalk 프레임워크의 핵심 기능은 사용자가 빠르게 오디오를 전송하게 하는 거죠 사용자는 앱 안에서도 또는 시스템의 Push To Talk UI에서도 오디오를 전송할 수 있습니다 여러분의 앱이 CoreBluetooth를 통해서 블루투스 액세서리를 지원한다면 주변 장치의 특성 변화에 대응해 배경에서 오디오 전송을 시작할 수 있습니다 오디오를 전송할 때 PushToTalk 프레임워크는 장치의 마이크 잠금을 해제하고 앱의 오디오 세션을 활성화하여 배경에서 오디오를 녹음할 수 있게 합니다 이 과정을 자세히 살펴보죠 앱 내에서 오디오 전송을 시작하려면 requestBeginTransmitting 기능을 호출하면 됩니다 앱이 전면에서 실행 중이거나 블루투스 주변 장치의 특성 변화에 반응할 때 호출할 수 있죠 시스템이 전송을 시작할 수 없는 경우 대리자가 failedToBeginTransmitting InChannel 메서드를 호출해 실패한 원인을 표시합니다 예를 들어 사용자의 휴대전화가 통화 중일 때 Push To Talk 전송은 시작할 수 없습니다 전송을 멈추려면 stopTransmitting 메서드를 채널 관리자에게서 호출합니다 사용자가 전송 상태가 아닐 때처럼 전송 중단 시도가 실패할 때 발생하는 오류를 처리하려면 채널 관리자 대리자에게 연결된 failedToStopTransmitting InChannel 메서드를 호출합니다 앱 내에서 전송을 시작하든 사용자가 시스템 UI에서 시작하든 채널 관리자 대리자는 '전송 시작' 콜백을 받습니다 전송 소스는 메서드로 전달되고 전송이 시스템 UI로 시작됐는지 API로 시작됐는지 또는 하드웨어 버튼 이벤트로 시작됐는지 여부를 나타내죠 전송이 시작되면 앱의 오디오 세션을 시스템이 활성화할 겁니다 그게 녹음을 시작할 수 있다는 신호입니다 오디오 세션을 마음대로 시작하거나 중지하면 안 됩니다 전송이 끝나면 채널 관리자 대리자는 전송 종료와 오디오 세션 비활성화 이벤트를 수신합니다 전송이 활성화된 동안 오디오 세션이 여러분이 앱 안에서 처리해야 하는 수신 전화나 FaceTime 호출 등의 다른 소스 때문에 중단될 수도 있다는 걸 명심하세요 PushToTalk 프레임워크를 이용하면 백그라운드에서 다른 사용자의 오디오를 수신하고 재생할 수 있습니다 이 과정은 새로운 Apple 푸시 알림 유형에 의존하죠 Push To Talk 앱에 특화된 기능입니다 Push To Talk 서버에 사용자가 수신할 새 오디오가 있는 경우 채널을 가입할 때 받은 장치 푸시 토큰을 사용해 사용자에게 Push To Talk 알림을 보내야 합니다 앱에서 보낸 푸시 알림을 받으면 활성 스피커를 프레임워크에 보고해야 합니다 활성 스피커는 시스템을 시켜 앱의 오디오 세션을 활성화하고 재생을 시작하게 하죠 새로운 Push To Talk 알림은 iOS의 다른 알림 유형과 유사하며 Push To Talk 앱으로 알림을 전달하기 위해 설정해야 하는 특정 속성이 있습니다 먼저 요청 헤더에서 APNS 푸시 유형을 'pushtotalk'로 설정해야 합니다 그다음 APNS 항목 헤더의 끝에 '.voip-ptt'를 추가하면서 앱의 번들 식별자로 설정해야 합니다 푸시 페이로드에는 활성 스피커의 이름이나 세션이 종료돼서 앱이 Push To Talk 채널을 떠나야 한다는 표시처럼 앱과 관련된 사용자 지정 키가 포함될 수 있죠 aps 본문의 속성은 비워 둘 수 있습니다 그리고 다른 소통 관련 앱들의 푸시 유형처럼 Push To Talk 페이로드는 APNS 우선 순위가 10이어야 즉시 전달을 요청할 수 있고 더는 관련 없는 오래된 푸시들이 나중에 전달되는 걸 방지하기 위해 APNS 만료가 0이어야 합니다 서버에서 Push To Talk 알림을 보내면 백그라운드에서 앱이 시작되고 수신 푸시 대리자 메서드가 호출됩니다 푸시 페이로드를 받으면 푸시 알림의 결과로 수행할 작업을 나타내는 푸시 결과 유형을 구성해야 합니다 원격 사용자가 말하는 걸 나타내려면 활성 참가자의 정보가 포함된 푸시 결과를 반환합니다 참가자의 이름과 선택한 이미지가 담겨 있죠 그러면 시스템이 채널의 활성 참가자를 설정하고 채널이 수신 모드임을 나타냅니다 그 후 시스템이 오디오 세션을 활성화하고 didActivateaudioSession 대리자 메서드를 호출합니다 재생을 시작하기 전에 이 메서드의 호출을 기다려야 합니다 서버가 사용자를 채널에서 내보내기로 한 경우 푸시 페이로드에 표시됩니다 leaveChannel 푸시 결과를 반환하면 되죠 이 메서드에서 가능한 한 빨리 PTPushResult를 반환하고 스레드를 차단하지 않는 게 중요합니다 활성 원격 참가자를 설정하려고 할 때 이미지가 로컬에 저장되지 않은 경우 스피커 이름만 사용해서 활성 원격 참가자를 반환할 수 있습니다 그다음 이미지를 별도 스레드에 다운로드하고 이미지를 불러오면 채널 관리자에서 setActiveRemoteParticipant를 호출하여 activeRemoteParticipant를 업데이트합니다 원격 참가자가 말을 마치면 activeRemoteParticipant를 0으로 설정해야 합니다 이렇게 하면 사용자가 채널에서 더 이상 오디오를 수신하지 않고 시스템이 오디오를 비활성화해야 함을 나타내죠 그러면 시스템 Push To Talk UI도 업데이트되고 사용자가 다시 오디오를 전송할 수 있습니다 이제 PushToTalk를 앱에 통합하는 방법에 대한 기본적인 이야기가 끝났으니 사용자 환경을 최적화하고 배터리 수명을 보존하는 몇 가지 모범 사례를 살펴보죠
PushToTalk 프레임워크는 사용자가 전송을 시작하고 시스템 어디서든 채널을 떠날 수 있는 시스템 UI를 제공합니다 또 앱이 전면에 있을 때 맞춤형 Push To Talk UI를 구현할 수 있습니다 PushToTalk 프레임워크는 공유 시스템 리소스를 활용합니다 시스템에서 Push To Talk 앱은 한 번에 하나만 활성화할 수 있고 Push To Talk 통신은 통화, FaceTime, VoIP 전화로 대신할 수 있죠 앱은 PushToTalk 실패를 적절하게 처리하고 상황에 맞게 대응해야 합니다 앞서 언급한 것처럼 PushToTalk 프레임워크는 오디오 세션 활성화와 비활성화를 처리합니다 하지만 여러분이 앱을 시작할 때 녹음과 재생을 할 수 있도록 오디오 세션의 범주를 구성해야 하죠 시스템은 사용자에게 내장된 음향 효과를 제공해서 전송 시 마이크 활성화 여부를 알립니다 이런 이벤트에 다른 음향 효과를 쓰면 안 됩니다 또 여러분의 앱에서 AVAudioSession 알림을 모니터링하고 응답하는 것도 중요합니다 세션 중단이나 경로 변경 실패 같은 알림이 있죠 Push To Talk 앱은 다른 오디오 앱과 마찬가지로 이러한 오디오 세션 이벤트의 영향을 받을 수 있습니다 배터리 수명을 보존하려면 앱을 최적화하는 게 중요하죠 PushToTalk 프레임워크는 오디오를 송수신할 때처럼 필요할 때 배경 런타임을 앱에 제공합니다 사용자가 앱을 사용하지 않을 때는 배터리 수명 보존을 위해 시스템에 의해 일시 중단되죠 자신의 오디오 세션을 활성화하거나 비활성화해서는 안 됩니다 오디오 세션 활성화는 적절한 때에 시스템이 처리합니다 이렇게 하면 오디오 세션이 시스템 내에서 적절한 우선 순위를 갖고 사용되지 않을 때 일시 중단될 수 있습니다 Push To Talk 서버는 새 푸시 알림 유형을 사용해 재생할 새 오디오나 Push To Talk 세션의 종료를 앱에 알려야 합니다 앱의 배터리 수명 개선에 대해 더 자세히 알고 싶다면 '전원 끄기: 배터리 소모량 개선' 세션을 봐 주세요 Push To Talk 앱이 배경에 있고 앱이 오디오를 전송하거나 수신하지 않으면 시스템에 의해 일시 중단됩니다 앱이 일시 중단되면 모든 네트워크 연결이 끊어집니다 보안 TLS 연결을 설정하는 데 필요한 단계를 줄이고 초기 연결 속도를 향상시키기 위해 Network.framework와 QUIC의 적용을 고려해야 합니다 Network.framework에는 QUIC의 지원 기능이 있습니다 더 자세히 알고 싶으시면 '응답성이 높은 앱을 위한 네트워킹 지연 감소'를 보고 QUIC 사용 방법에 대해 알아보세요 PushToTalk 프레임워크는 앱 내에서 강력하고 전력 효율적인 워키토키 스타일의 통신 환경을 구축할 수 있습니다 여러분이 이미 iOS에 워키토키 스타일을 구현하는 앱을 갖고 있다면 기존 앱을 업데이트해서 새 API를 사용해 보세요 새로운 워키토키 앱을 구현하고 있다면 지금 PushToTalk 프레임워크를 사용해 보세요 마지막으로 새 프레임워크를 테스트하고 앱과 통합하기 시작할 때 피드백을 보내 주세요 고맙습니다 WWDC를 즐기세요 그럼 이만, 오버 ♪
-
-
6:52 - Creating a Channel Manager
func setupChannelManager() async throws { channelManager = try await PTChannelManager.channelManager(delegate: self, restorationDelegate: self) }
-
7:33 - Joining a Channel
func joinChannel(channelUUID: UUID) { let channelImage = UIImage(named: "ChannelIcon") channelDescriptor = PTChannelDescriptor(name: "Awesome Crew", image: channelImage) // Ensure that your channel descriptor and UUID are persisted to disk for later use. channelManager.requestJoinChannel(channelUUID: channelUUID, descriptor: channelDescriptor) }
-
8:11 - PTChannelManagerDelegate didJoinChannel
func channelManager(_ channelManager: PTChannelManager, didJoinChannel channelUUID: UUID, reason: PTChannelJoinReason) { // Process joining the channel print("Joined channel with UUID: \(channelUUID)") } func channelManager(_ channelManager: PTChannelManager, receivedEphemeralPushToken pushToken: Data) { // Send the variable length push token to the server print("Received push token") }
-
8:45 - PTChannelManagerDelegate failedToJoinChannel
func channelManager(_ channelManager: PTChannelManager, failedToJoinChannel channelUUID: UUID, error: Error) { let error = error as NSError switch error.code { case PTChannelError.channelLimitReached.rawValue: print("The user has already joined a channel") default: break } }
-
9:00 - PTChannelManagerDelegate didLeaveChannel
func channelManager(_ channelManager: PTChannelManager, didLeaveChannel channelUUID: UUID, reason: PTChannelLeaveReason) { // Process leaving the channel print("Left channel with UUID: \(channelUUID)") }
-
9:22 - PTChannelRestorationDelegate
func channelDescriptor(restoredChannelUUID channelUUID: UUID) -> PTChannelDescriptor { return getCachedChannelDescriptor(channelUUID) }
-
10:12 - Provide channel descriptor updates
func updateChannel(_ channelDescriptor: PTChannelDescriptor) async throws { try await channelManager.setChannelDescriptor(channelDescriptor, channelUUID: channelUUID) }
-
10:20 - Provide service status updates
func reportServiceIsReconnecting() async throws { try await channelManager.setServiceStatus(.connecting, channelUUID: channelUUID) } func reportServiceIsConnected() async throws { try await channelManager.setServiceStatus(.ready, channelUUID: channelUUID) }
-
11:48 - Start transmission from within your app
func startTransmitting() { channelManager.requestBeginTransmitting(channelUUID: channelUUID) } // PTChannelManagerDelegate func channelManager(_ channelManager: PTChannelManager, failedToBeginTransmittingInChannel channelUUID: UUID, error: Error) { let error = error as NSError switch error.code { case PTChannelError.callIsActive.rawValue: print("The system has another ongoing call that is preventing transmission.") default: break } }
-
12:22 - Stop transmission from within your app
func stopTransmitting() { channelManager.stopTransmitting(channelUUID: channelUUID) } func channelManager(_ channelManager: PTChannelManager, failedToStopTransmittingInChannel channelUUID: UUID, error: Error) { let error = error as NSError switch error.code { case PTChannelError.transmissionNotFound.rawValue: print("The user was not in a transmitting state") default: break } }
-
12:41 - Responding to begin transmission delegate events
func channelManager(_ channelManager: PTChannelManager, channelUUID: UUID, didBeginTransmittingFrom source: PTChannelTransmitRequestSource) { print("Did begin transmission from: \(source)") } func channelManager(_ channelManager: PTChannelManager, didActivate audioSession: AVAudioSession) { print("Did activate audio session") // Configure your audio session and begin recording }
-
13:19 - Responding to end transmission delegate events
func channelManager(_ channelManager: PTChannelManager, channelUUID: UUID, didEndTransmittingFrom source: PTChannelTransmitRequestSource) { print("Did end transmission from: \(source)") } func channelManager(_ channelManager: PTChannelManager, didDeactivate audioSession: AVAudioSession) { print("Did deactivate audio session") // Stop recording and clean up resources }
-
15:29 - Receiving Push to Talk Pushes
func incomingPushResult(channelManager: PTChannelManager, channelUUID: UUID, pushPayload: [String : Any]) -> PTPushResult { guard let activeSpeaker = pushPayload["activeSpeaker"] as? String else { // If no active speaker is set, the only other valid operation // is to leave the channel return .leaveChannel } let activeSpeakerImage = getActiveSpeakerImage(activeSpeaker) let participant = PTParticipant(name: activeSpeaker, image: activeSpeakerImage) return .activeRemoteParticipant(participant) }
-
17:03 - Stop receiving audio
func stopReceivingAudio() { channelManager.setActiveRemoteParticipant(nil, channelUUID: channelUUID) }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.