본문으로 건너뛰기
Version: 5.5

릴리스 노트

iOS/macOS용 PlanetKit 5.5의 릴리스 노트입니다.

PlanetKit 5.5.2

릴리스 일자: 2025-02-26

PlanetKitAudioRouteChangeDelegate에 이전 오디오 경로 정보 추가

PlanetKitAudioRouteChangeDelegatedidAudioRouteChange에 이전 PlanetKitAudioRoute 값을 추가했습니다.

API

변경
  • PlanetKitAudioRouteChangeDelegate protocol 1-to-1 callGroup call

    이전 버전PlanetKit 5.5.2
    didAudioRouteChange(audioRoute: PlanetKitAudioRoute)didAudioRouteChange(current: PlanetKitAudioRoute, previous: PlanetKitAudioRoute)

PlanetKitCall.speakerOut()PlanetKitConference.speakerOut()의 버그 수정

스피커 출력 기능을 사용할 때 특정 조건에서 스피커가 꺼지지 않는 문제를 해결하여 모든 상황에서 일관된 오디오 관리를 보장합니다.

PlanetKit 내부 카메라 모듈에서 버그 수정

카메라가 중단(interrupt)될 때 의도하지 않은 효과가 발생하는 PlanetKit 내부 카메라 모듈의 문제를 해결하여 카메라 작동의 안정성과 신뢰성을 향상시켰습니다.

PlanetKit 5.5.1

릴리스 일자: 2025-01-15

통화 시작 시 음성 전송 시작 지연 문제 수정

1대1 통화 및 그룹 통화 시작 시 로컬 사용자의 음성 전송을 시작하는 데 500ms 지연이 발생하는 문제를 해결했습니다.

Flutter 지원을 위한 SDK 변경 반영

SDK에 PlanetKit Flutter 지원용 코드를 추가했습니다.

PlanetKit 5.5.0

릴리스 일자: 2024-12-09

PlanetKitInitialMyVideoState 추가

PlanetKitInitialMyVideoState는 영상 통화가 활성화될 때 로컬 사용자의 비디오 상태를 결정하기 위해 추가된 열거형 클래스입니다.

  • 이제 초기 비디오 상태를 resume이나 pause로 설정할 수 있습니다.
  • PlanetKitInitialMyVideoState 유형의 속성 또는 파라미터의 기본값은 PlanetKitInitialMyVideoState.resume입니다.

API

추가
  • PlanetKitInitialMyVideoState enum 1-to-1 call
    • case resume
    • case pause
  • PlanetKitCallParam class 1-to-1 call
    • var initialMyVideoState: PlanetKitInitialMyVideoState { get set }
  • PlanetKitConferenceParam class Group call
    • var initialMyVideoState: PlanetKitInitialMyVideoState { get set }
변경
  • PlanetKitCall class 1-to-1 call

    이전 버전PlanetKit 5.5
    func acceptCall(startMessage: PlanetKitCallStartMessage?, useResponderPreparation: Bool, recordOnCloud: Bool = false)func acceptCall(startMessage: PlanetKitCallStartMessage?, useResponderPreparation: Bool, recordOnCloud: Bool = false, initialMyVideoState: PlanetKitInitialMyVideoState = .resume)
    func enableVideo(completion: @escaping (Bool)->Void)func enableVideo(initialMyVideoState: PlanetKitInitialMyVideoState = .resume, completion: @escaping (Bool)->Void)
    func disableVideo(reason: PlanetKitMediaDisableReason, stopCamera: Bool = true, completion: @escaping (Bool)->Void)func disableVideo(reason: PlanetKitMediaDisableReason, completion: @escaping (Bool)->Void)
  • PlanetKitConference class Group call

    이전 버전PlanetKit 5.5
    func enableVideo(completion: @escaping (Bool)->Void)func enableVideo(initialMyVideoState: PlanetKitInitialMyVideoState = .resume, completion: @escaping (Bool)->Void)
    func disableVideo(stopCamera: Bool = true, completion: @escaping (Bool)->Void)func disableVideo(completion: @escaping (Bool)->Void)

카메라 제어 개선

PlanetKit이 Planet Cloud에 데이터를 전송할 때만 카메라를 켜도록 개선했습니다.

API

추가
  • PlanetKitCameraManager class 1-to-1 callGroup call
    • func startPreview(delegate: PlanetKitVideoOutputDelegate)
    • func stopPreview(delegate: PlanetKitVideoOutputDelegate)
    • var previewModifier: PlanetKitVideoModifierDelegate? { get set }
    • func setCustomCamera(_ customCamera: PlanetKitCustomCamera)
    • func resetToDefaultCamera()
    • var currentDeviceInfo: PlanetKitVideoCaptureDeviceInfo? { get }
    • var isStarted: Bool { get }
    • var preset: PlanetKitCameraPreset? { get }
    • var position: PlanetKitCameraPosition { get }
    • var frameRate: PlanetKitFrameRate? { get }
    • func change(deviceInfo: PlanetKitVideoCaptureDeviceInfo)
    • func switchPosition()
    • func addInterruptReceiver(_ interruptReceiver: PlanetKitCameraInterruptDelegate)
    • func removeInterruptReceiver(_ interruptReceiver: PlanetKitCameraInterruptDelegate)
    • var virtualBackground: PlanetKitVirtualBackground? { get set }
    • var deviceInfos: [PlanetKitVideoCaptureDeviceInfo] { get }
    • static var isCameraAvailable: Bool { get }
    • static var shared: PlanetKitCameraManager { get }
    • weak var delegate: PlanetKitCameraDelegate? { get set }
    • func addDeviceChangeDelegate(_ delegate: PlanetKitCameraDeviceChangeDelegate)
    • func removeDeviceChangeDelegate(_ delegate: PlanetKitCameraDeviceChangeDelegate)
  • PlanetKitCameraDelegate protocol 1-to-1 callGroup call
    • func didStart()
    • func didStop(_ error: NSError?)
  • PlanetKitCustomCamera class 1-to-1 callGroup call
    • func sendVideo(videoBuffer: PlanetKitVideoBuffer)
    • func isVideoSendAvailable() -> Bool
  • PlanetKitCall class 1-to-1 call
    • var peerVideoStream: PlanetKitVideoStream
변경
  • PlanetKitCall class 1-to-1 call

    이전 버전PlanetKit 5.5
    weak var myVideoReceiver: PlanetKitVideoOutputDelegate? { get set }var myVideoStream: PlanetKitVideoStream { get }
    var myCameraStream: PlanetKitVideoStream { get }var myVideoStream: PlanetKitVideoStream { get }
  • PlanetKitConference class Group call

    이전 버전PlanetKit 5.5
    var myCameraStream: PlanetKitVideoStream { get }var myVideoStream: PlanetKitVideoStream { get }
  • Rename PlanetKitVideoCaptureDevice to PlanetKitVideoCaptureDeviceInfo 1-to-1 callGroup call

  • PlanetKitCameraManager class 1-to-1 callGroup call

    이전 버전PlanetKit 5.5
    PlanetKitCall.startPreview()func startPreview(delegate: PlanetKitVideoOutputDelegate)
    PlanetKitCall.stopPreview()func stopPreview(delegate: PlanetKitVideoOutputDelegate)
    PlanetKitMakeCallSettingBuilder.withCustomCameraKey(camera:) or PlanetKitVerifyCallSettingBuilder.withCustomCameraKey(camera:) or PlanetKitJoinConferenceSettingBuilder.withCustomCameraKey(camera:)func setCustomCamera(_ camera: PlanetKitCustomCamera)
    PlanetKitCamera.isStartedvar isStarted: Bool { get }
    PlanetKitCamera.currentDevicevar currentDeviceInfo: PlanetKitVideoCaptureDeviceInfo? { get }
    PlanetKitCamera.cameraPresetvar preset: PlanetKitCameraPreset? { get }
    PlanetKitCamera.cameraPositionvar position: PlanetKitCameraPosition { get }
    PlanetKitCamera.cameraFrameRatevar frameRate: PlanetKitFrameRate? { get }
    PlanetKitCamera.change(device:)func change(deviceInfo: PlanetKitVideoCaptureDeviceInfo)
    PlanetKitCamera.switchPosition()func switchPosition()
    PlanetKitCamera.addInterruptReceiver(_:)func addInterruptReceiver(_ interruptReceiver: PlanetKitCameraInterruptDelegate
    PlanetKitCamera.removeInterruptReceiver(_:)func removeInterruptReceiver(_ interruptReceiver: PlanetKitCameraInterruptDelegate)
    PlanetKitCamera.isCameraAvailablestatic var isCameraAvailable: Bool { get }
    PlanetKitCamera.devicesvar deviceInfos: [PlanetKitVideoCaptureDeviceInfo] { get }
    PlanetKitCamera.virtualBackgroundvar virtualBackground: PlanetKitVirtualBackground? { get set }
    PlanetKitCamera.addDeviceChangeDelegate(_:)func addDeviceChangeDelegate(_ delegate: PlanetKitCameraDeviceChangeDelegate)
    PlanetKitCamera.removeDeviceChangeDelegate(_:)func removeDeviceChangeDelegate(_ delegate: PlanetKitCameraDeviceChangeDelegate)
    PlanetKitCamera.didStartNotificationvar delegate: PlanetKitCameraDelegate? { get set }
    PlanetKitCamera.didStopNotificationvar delegate: PlanetKitCameraDelegate? { get set }
삭제
  • PlanetKitCamera class 1-to-1 callGroup call
  • PlanetKitCameraControllable protocol 1-to-1 callGroup call
  • PlanetKitCall class 1-to-1 call
    • var camera: PlanetKitCameraControllable? { get }
    • func startPreview()
    • func stopPreview()
  • PlanetKitConference class Group call
    • var camera: PlanetKitCameraControllable? { get }
    • func startPreview()
    • func stopPreview()
  • PlanetKitInitialSettingBuilder class 1-to-1 callGroup call
    • func withDisableKitCameraKey(disable: Bool) -> PlanetKitInitialSettingBuilder
  • PlanetKitMakeCallSettingBuilder class 1-to-1 call
    • func withCustomCameraKey(camera: PlanetKitCameraControllable) -> PlanetKitMakeCallSettingBuilder
    • func withCustomCameraStreamKey(videoStream: PlanetKitVideoStream) -> PlanetKitMakeCallSettingBuilder
  • PlanetKitVerifyCallSettingBuilder class 1-to-1 call
    • func withCustomCameraKey(camera: PlanetKitCameraControllable) -> PlanetKitVerifyCallSettingBuilder
    • func withCustomCameraStreamKey(videoStream: PlanetKitVideoStream) -> PlanetKitVerifyCallSettingBuilder
  • PlanetKitJoinConferenceSettingBuilder class Group call
    • func withCustomCameraKey(camera: PlanetKitCameraControllable) -> PlanetKitJoinConferenceSettingBuilder
    • func withCustomCameraStreamKey(videoStream: PlanetKitVideoStream) -> PlanetKitJoinConferenceSettingBuilder

마이그레이션

카메라 미리보기 시작
  • 이전 버전의 예제 코드
class PreviewVideoViewController: UIViewController {
....

var myVideoView: PlanetKitMTKView!

private func setupView() {
let videoStream = PlanetKitVideoStream()
videoStream.addReceiver(myVideoView!)
videoStream.modifier = self

PlanetKitCamera.shared.addReceiver(videoStream)
PlanetKitCamera.shared.open()
PlanetKitCamera.shared.start()
}
}

extension VideoViewController: PlanetKitVideoModifierDelegate {
func videoOutput(_ videoBuffer: PlanetKitVideoBuffer) {
....
}
}
  • 신규 버전의 예제 코드
class PreviewVideoViewController: UIViewController {
....

var myVideoView: PlanetKitMTKView!

private func setupView() {
PlanetKitCameraManager.shared.previewModifier = self
PlanetKitCameraManager.shared.startPreview(delegate: myVideoView)
}
}

extension VideoViewController: PlanetKitVideoModifierDelegate {
func videoOutput(_ videoBuffer: PlanetKitVideoBuffer) {
....
}
}
다른 카메라 장치로 전환
  • 이전 버전의 예제 코드
class CameraDeviceViewController: UIViewController {
....

private var devices: [PlanetKitVideoCaptureDevice] = []
private var deviceNames: [String] = []

private func refreshDevices() {
devices = PlanetKitCamera.shared.devices

deviceNames.removeAll()
for device in devices {
deviceNames.append(device.name)
}
}

private func change(device: PlanetKitVideoCaptureDevice) {
PlanetKitCamera.shared.change(device: device)
}
}
  • 신규 버전의 예제 코드
class CameraDeviceViewController: UIViewController {
....

private var deviceInfos: [PlanetKitVideoCaptureDeviceInfo] = []
private var deviceNames: [String] = []

private func refreshDevices() {
deviceInfos = PlanetKitCameraManager.shared.deviceInfos

var selectedIndex = -1
deviceNames.removeAll()
for (index, deviceInfo) in deviceInfos.enumerated() {
deviceNames.append(deviceInfo.name)
if PlanetKitCameraManager.shared.currentDeviceInfo?.uniqueID == deviceInfo.uniqueID {
selectedIndex = index
}
}
}

private func change(deviceInfo: PlanetKitVideoCaptureDeviceInfo) {
PlanetKitCameraManager.shared.change(deviceInfo: deviceInfo)
}
}
로컬 사용자 비디오 뷰에 대한 수신 모듈(receiver) 추가
  • 이전 버전의 예제 코드
class VideoViewController: UIViewController {
....

var call: PlanetKitCall!
var myVideoView: PlanetKitMTKView!

private func setMyVideo() {
call.myVideoReceiver = myVideoView
}
}
  • 신규 버전의 예제 코드
class VideoViewController: UIViewController {
....

var call: PlanetKitCall!
var myVideoView: PlanetKitMTKView!

private func setMyVideo() {
call.myVideoStream.addReceiver(myVideoView)
}
}
커스텀 카메라를 비디오 소스로 사용
import PlanetKit

class CustomCamera: PlanetKitCustomCamera {
static var shared = CustomCamera()

// Implement the abstract method to handle FPS limit updates
override func processFpsLimitUpdate(enabled: Bool, fps: Int32) {
// Handle the FPS limit update
// If `enabled` is true, adjust your frame generation logic to according to the `fps`
}

// Method to simulate video buffer processing
func processVideoBuffer(buffer: CMSampleBuffer) {
guard let targetBuffer = PlanetKitVideoBuffer.getPreferredSampleBuffer(buffer) else {
return
}

let timestamp = CMSampleBufferGetPresentationTimeStamp(targetBuffer)

// Check if video buffer can be sent. If false, drop the buffer.
guard isVideoSendAvailable(timestamp: timestamp) else { return }


let videoBuffer = PlanetKitVideoBuffer(sampleBuffer: targetBuffer,
timestamp: timestamp,
rotation: .rotation0,
position: .unknown,
sender: nil,
source: .camera)

sendVideo(videoBuffer: videoBuffer)
}
}

// Start using the custom camera.
PlanetKitCameraManager.shared.setCustomCamera(CustomCamera.shared)

// Reset to the default device.
PlanetKitCameraManager.shared.resetToDefaultCamera()

오디오 후킹 기능 추가

오디오 후킹(audio hooking) 기능을 이용하여 Planet Cloud가 상대방에게 오디오를 전송하기 전에 오디오 데이터를 가져올 수 있습니다. 이 기능은 로컬 사용자의 음성을 변조하거나 오디오 데이터를 음성 인식에 활용하는 용도로 사용할 수 있습니다.

API

추가
  • PlanetKitHookedAudio class 1-to-1 call
    • var sampleRate: UInt32 { get }
    • var channel: UInt32 { get }
    • var sampleType: PlanetKitAudioSampleType { get }
    • var sampleCount: UInt32 { get }
    • var seq: Int64 { get }
    • var data: Data { get set }
  • PlanetKitCallHookedAudioDelegate protocol 1-to-1 call
    • func didHook(_ call: PlanetKitCall, audio: PlanetKitHookedAudio)
  • PlanetKitCall class 1-to-1 call
    • var isHookMyAudioEnabled: Bool { get }
    • func enableHookMyAudio(delegate: PlanetKitCallHookedAudioDelegate, completion: @escaping (Bool)->Void)
    • func disableHookMyAudio(completion: @escaping (Bool)->Void)
    • func putHookedMyAudioBack(audio: PlanetKitHookedAudio) -> Bool

화면 잠금으로 인한 통화 종료 이유 추가

이 통화 종료 이유는 사용자의 요청이나 시스템 비활성화로 인해 화면이 잠겼을 때 데스크톱 시스템에서만 발생합니다(macOS에만 해당). 상대방이 데스크톱을 사용 중이고 상대방의 화면이 잠기는 경우 통화가 종료되며 이벤트를 통해 이 이유를 전달받습니다.

API

추가
  • PlanetKitDisconnectReason enum 1-to-1 callGroup call
    • case desktopScreenLocked = 1314

불필요한 declineCall() 제거

1대1 통화에서 불필요한 함수를 제거했습니다. 통화를 거부하여 종료하려면 declineCall() 대신 endCall()을 사용하세요.

API

삭제
  • PlanetKitCall class 1-to-1 callGroup call
    • func declineCall()