IVS Broadcast SDK: 혼합 디바이스
혼합 디바이스는 여러 개의 입력 소스로 단일 출력을 생성하는 오디오 및 비디오 디바이스입니다. 디바이스 혼합은 여러 화면(비디오) 요소와 오디오 트랙을 정의하고 관리할 수 있는 강력한 기능입니다. 카메라, 마이크, 화면 캡처, 앱에서 생성한 오디오 및 비디오와 같은 여러 소스의 비디오와 오디오를 결합할 수 있습니다. 전환을 사용하여 IVS로 스트리밍하는 비디오에서 이러한 소스를 이동하고 스트림 중간에 소스를 추가하거나 제거할 수 있습니다.
혼합 디바이스에는 이미지 버전과 오디오 버전이 있습니다. 혼합 이미지 디바이스를 생성하려면 다음을 직접적으로 호출합니다.
Android에서 DeviceDiscovery.createMixedImageDevice()
iOS에서 IVSDeviceDiscovery.createMixedImageDevice()
반환된 디바이스는 다른 디바이스와 마찬가지로 BroadcastSession
(저지연 스트리밍) 또는 Stage
(실시간 스트리밍)에 연결할 수 있습니다.
용어

Term | 설명 |
---|---|
장치 |
오디오 또는 이미지 입력을 생성하는 하드웨어 또는 소프트웨어 구성 요소입니다. 디바이스의 예로는 마이크, 카메라, Bluetooth 헤드셋 및 화면 캡처 또는 사용자 정의 이미지 입력과 같은 가상 디바이스가 있습니다. |
혼합 디바이스 |
다른 혼합 디바이스에는 이미지 버전 또는 오디오 버전이 있습니다. |
혼합 디바이스 구성 |
혼합 디바이스의 구성 객체입니다. 혼합 이미지 디바이스의 경우 차원과 프레임 속도 등 속성이 구성됩니다. 혼합 오디오 디바이스의 경우 채널 개수가 구성됩니다. |
소스 |
화면상의 시각적 요소의 위치와 오디오 믹스에서 오디오 트랙의 속성을 정의하는 컨테이너. 혼합 디바이스는 0개 이상의 소스로 구성할 수 있습니다. 소스에는 소스의 미디어 사용 방식에 영향을 미치는 구성이 주어집니다. 위 이미지에서는 네 가지 이미지 소스를 보여줍니다.
|
소스 구성 |
혼합 디바이스에 들어가는 소스의 구성 객체입니다. 아래에 전체 구성 객체가 설명되어 있습니다. |
Transition |
슬롯을 새 위치로 이동하거나 일부 속성을 변경하려면
|
혼합 오디오 디바이스
구성
Android에서 MixedAudioDeviceConfiguration
iOS에서 IVSMixedAudioDeviceConfiguration
명칭 | 유형 | 설명 |
---|---|---|
|
Integer |
오디오 믹서의 출력 채널 수 유효한 값: 1, 2. 1은 모노 오디오, 2는 스테레오 오디오입니다. 기본값: 2. |
소스 구성
Android에서 MixedAudioDeviceSourceConfiguration
iOS에서 IVSMixedAudioDeviceSourceConfiguration
명칭 | 유형 | 설명 |
---|---|---|
|
Float |
오디오 게인. 이 값은 승수이므로 1을 초과하는 모든 값은 게인을 증가시키고 1 미만의 값은 게인을 감소시킵니다. 유효한 값은 0~2입니다. 기본값: 1. |
혼합 이미지 디바이스
구성
Android에서 MixedImageDeviceConfiguration
iOS에서 IVSMixedImageDeviceConfiguration
명칭 | 유형 | 설명 |
---|---|---|
|
Vec2 |
비디오 캔버스 크기. |
|
Integer |
혼합 디바이스의 목표 초당 프레임 수입니다. 평균적으로 이 값을 충족해야 하지만, 특정 상황(예: 높은 CPU 또는 GPU 부하)에서는 시스템이 프레임을 떨어뜨릴 수 있습니다. |
|
불 |
그러면 이미지 소스 구성에서 |
소스 구성
Android에서 MixedImageDeviceSourceConfiguration
iOS에서 IVSMixedImageDeviceSourceConfiguration
명칭 | 유형 | 설명 |
---|---|---|
|
Float |
슬롯의 알파입니다. 이미지에 알파 값이 있는 배수입니다. 유효한 값: 0~1. 0은 완전히 투명하고, 1은 완전히 불투명합니다. 기본값: 1. |
|
AspectMode | 슬롯에 렌더링된 모든 이미지에 대한 종횡비 모드. 유효한 값:
기본값: |
|
Vec4 |
슬롯 및 이미지 종횡비가 일치하지 않을 때 |
|
Vec2 |
캔버스의 왼쪽 위 모서리를 기준으로 한 슬롯 위치(단위: 픽셀). 슬롯의 원점도 왼쪽 위입니다. |
|
Vec2 |
슬롯의 크기(픽셀) 이 값 설정도 |
|
Float |
슬롯의 상대적 순서. |
혼합 이미지 디바이스 생성 및 구성

다음은 가이드의 시작 부분에 있는 것과 비슷한 장면을 만들 때 사용하는 화면에 표시되는 3가지 요소입니다.
-
카메라용 왼쪽 하단 슬롯.
-
로고 오버레이용 오른쪽 하단 슬롯.
-
영화용 오른쪽 상단 슬롯.
캔버스의 원점은 왼쪽 상단 모서리이며 슬롯에 대해 동일합니다. 따라서 (0, 0)에 슬롯을 배치하면 전체 슬롯이 보이는 왼쪽 상단 모서리에 배치됩니다.
iOS
let deviceDiscovery = IVSDeviceDiscovery() let mixedImageConfig = IVSMixedImageDeviceConfiguration() mixedImageConfig.size = CGSize(width: 1280, height: 720) try mixedImageConfig.setTargetFramerate(60) mixedImageConfig.isTransparencyEnabled = true let mixedImageDevice = deviceDiscovery.createMixedImageDevice(with: mixedImageConfig) // Bottom Left let cameraConfig = IVSMixedImageDeviceSourceConfiguration() cameraConfig.size = CGSize(width: 320, height: 180) cameraConfig.position = CGPoint(x: 20, y: mixedImageConfig.size.height - cameraConfig.size.height - 20) cameraConfig.zIndex = 2 let camera = deviceDiscovery.listLocalDevices().first(where: { $0 is IVSCamera }) as? IVSCamera let cameraSource = IVSMixedImageDeviceSource(configuration: cameraConfig, device: camera) mixedImageDevice.add(cameraSource) // Top Right let streamConfig = IVSMixedImageDeviceSourceConfiguration() streamConfig.size = CGSize(width: 640, height: 320) streamConfig.position = CGPoint(x: mixedImageConfig.size.width - streamConfig.size.width - 20, y: 20) streamConfig.zIndex = 1 let streamDevice = deviceDiscovery.createImageSource(withName: "stream") let streamSource = IVSMixedImageDeviceSource(configuration: streamConfig, device: streamDevice) mixedImageDevice.add(streamSource) // Bottom Right let logoConfig = IVSMixedImageDeviceSourceConfiguration() logoConfig.size = CGSize(width: 320, height: 180) logoConfig.position = CGPoint(x: mixedImageConfig.size.width - logoConfig.size.width - 20, y: mixedImageConfig.size.height - logoConfig.size.height - 20) logoConfig.zIndex = 3 let logoDevice = deviceDiscovery.createImageSource(withName: "logo") let logoSource = IVSMixedImageDeviceSource(configuration: logoConfig, device: logoDevice) mixedImageDevice.add(logoSource)
Android
val deviceDiscovery = DeviceDiscovery(this /* context */) val mixedImageConfig = MixedImageDeviceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(1280f, 720f)) setTargetFramerate(60) setEnableTransparency(true) } val mixedImageDevice = deviceDiscovery.createMixedImageDevice(mixedImageConfig) // Bottom Left val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, 180f)) setPosition(BroadcastConfiguration.Vec2(20f, mixedImageConfig.size.y - size.y - 20)) setZIndex(2) } val camera = deviceDiscovery.listLocalDevices().firstNotNullOf { it as? CameraSource } val cameraSource = MixedImageDeviceSource(cameraConfig, camera) mixedImageDevice.addSource(cameraSource) // Top Right val streamConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(640f, 320f)) setPosition(BroadcastConfiguration.Vec2(mixedImageConfig.size.x - size.x - 20, 20f)) setZIndex(1) } val streamDevice = deviceDiscovery.createImageInputSource(streamConfig.size) val streamSource = MixedImageDeviceSource(streamConfig, streamDevice) mixedImageDevice.addSource(streamSource) // Bottom Right val logoConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, 180f)) setPosition(BroadcastConfiguration.Vec2(mixedImageConfig.size.x - size.x - 20, mixedImageConfig.size.y - size.y - 20)) setZIndex(1) } val logoDevice = deviceDiscovery.createImageInputSource(logoConfig.size) val logoSource = MixedImageDeviceSource(logoConfig, logoDevice) mixedImageDevice.addSource(logoSource)
소스 제거
소스를 제거하려면 제거하려는 Source
객체로 MixedDevice.remove
를 직접적으로 호출합니다.
애니메이션 전환
전환 메서드는 슬롯의 구성을 새 구성으로 대체합니다. 이 대체에 지속 시간을 0보다 높은 시간(초)을 설정하여 애니메이션을 적용할 수 있습니다.
애니메이션할 수 있는 속성은 무엇인가요?
슬롯 구조의 모든 속성에 애니메이션이 적용될 수 있는 것은 아닙니다. Float 유형을 기반으로 하는 모든 속성에 애니메이션을 적용할 수 있으며, 다른 속성은 애니메이션의 시작 또는 종료 시점에 적용됩니다.
명칭 | 애니메이션으로 만들 수 있나요? | 임팩트 포인트 |
---|---|---|
|
예 |
보간 |
|
예 |
보간 |
|
아니요 |
종료 |
|
예 |
보간 |
|
예 |
보간 |
|
예 |
보간 |
참고: |
예 |
알 수 없음 |
간단한 예제
아래는 혼합 이미지 디바이스 생성 및 구성의 위에서 정의된 구성을 사용하는 전체 화면 카메라 전환 예제입니다. 0.5초에 걸쳐 애니메이션이 표시됩니다.
iOS
// Continuing the example from above, modifying the existing cameraConfig object. cameraConfig.size = CGSize(width: 1280, height: 720) cameraConfig.position = CGPoint.zero cameraSource.transition(to: cameraConfig, duration: 0.5) { completed in if completed { print("Animation completed") } else { print("Animation interrupted") } }
Android
// Continuing the example from above, modifying the existing cameraConfig object. cameraConfig.setSize(BroadcastConfiguration.Vec2(1280f, 720f)) cameraConfig.setPosition(BroadcastConfiguration.Vec2(0f, 0f)) cameraSource.transitionToConfiguration(cameraConfig, 500) { completed -> if (completed) { print("Animation completed") } else { print("Animation interrupted") } }
브로드캐스트 미러링
다음 방향으로 브로드캐스트에 연결된 이미지 디바이스를 미러링하려면 | …에 음수 값 사용 |
---|---|
수평 |
슬롯의 너비 |
수직 |
슬롯의 높이 |
수평 및 수직 모두 |
슬롯의 너비 및 높이 모두 |
미러링 시 슬롯을 올바른 위치에 놓으려면 위치를 같은 값으로 조정해야 합니다.
다음은 브로드캐스트를 수평 및 수직으로 미러링하는 예입니다.
iOS
수평 미러링:
let cameraSource = IVSMixedImageDeviceSourceConfiguration() cameraSource.size = CGSize(width: -320, height: 720) // Add 320 to position x since our width is -320 cameraSource.position = CGPoint(x: 320, y: 0)
수직 미러링:
let cameraSource = IVSMixedImageDeviceSourceConfiguration() cameraSource.size = CGSize(width: 320, height: -720) // Add 720 to position y since our height is -720 cameraSource.position = CGPoint(x: 0, y: 720)
Android
수평 미러링:
val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(-320f, 180f)) // Add 320f to position x since our width is -320f setPosition(BroadcastConfiguration.Vec2(320f, 0f)) }
수직 미러링:
val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, -180f)) // Add 180f to position y since our height is -180f setPosition(BroadcastConfiguration.Vec2(0f, 180f)) }
참고: 이 미러링은 ImagePreviewView
(Android) 및 IVSImagePreviewView
(iOS)의 setMirrored
메서드와 다릅니다. 해당 메서드는 디바이스의 로컬 미리 보기에만 영향을 주며 브로드캐스트에는 영향을 주지 않습니다.