JPEG 이미지 실시간 스트리밍
기기의 JPEG 실시간 스트리밍 모드를 시작하고 SDK가 전달하는 각각의 완전한 JPEG 이미지를 표시합니다. 호환되는 level-2 스트림은 Opus 오디오와 선택적 디코딩 PCM 데이터도 전달할 수 있습니다.
사전 요구 사항
- 기기가 연결되어 사용할 수 있으며
LiveStreamingAPI를 준수합니다. supportsJPEGImageLiveStreaming이true입니다.- 스트림을 차단하지 않고 이미지와 선택적 오디오 콜백을 처리할 수 있어야 합니다.
API 참고
프레임워크
AIBuds.xcframework
가져오기
- Swift
- Objective-C
import AIBuds
import UIKit#import <AIBuds/AIBuds-Swift.h>
#import <AIBuds/AIBuds.h>
#import <UIKit/UIKit.h>속성
- Swift
- Objective-C
/// Whether JPEG image live streaming is supported
var supportsJPEGImageLiveStreaming: Bool { get }/// Whether JPEG image live streaming is supported.
@property(nonatomic, readonly) BOOL supportsJPEGImageLiveStreaming;인스턴스 메서드
- Swift
- Objective-C
/// Start JPEG image live streaming
/// - Parameters:
/// - sessionStartCompletionHandler: Session start completion handler
/// - jpegDataReceivedHandler: JPEG data received handler
/// - opusDataReceivedHandler: Opus audio data received handler (only called for level-2 Ogg/MJPEG+Opus streams)
/// - sessionFinishHandler: Session finish handler
func startJPEGImageLiveStreaming(
withSessionStartCompletionHandler sessionStartCompletionHandler: AIBudsLiveStreamingSessionStartCompletionHandler?,
jpegDataReceivedHandler: AIBudsLiveStreamingJpegDataReceivedHandler?,
opusDataReceivedHandler: AIBudsLiveStreamingOpusAudioDataReceivedHandler?,
sessionFinishHandler: AIBudsLiveStreamingSessionFinishHandler?
)/// Start JPEG image live streaming
/// - Parameters:
/// - sessionStartCompletionHandler: Session start completion handler
/// - jpegDataReceivedHandler: JPEG data received handler
/// - opusDataReceivedHandler: Opus audio data received handler (only called for level-2 Ogg/MJPEG+Opus streams)
/// - sessionFinishHandler: Session finish handler
- (void) startJPEGImageLiveStreamingWithSessionStartCompletionHandler:(AIBudsLiveStreamingSessionStartCompletionHandler _Nullable)sessionStartCompletionHandler
jpegDataReceivedHandler:(AIBudsLiveStreamingJpegDataReceivedHandler _Nullable)jpegDataReceivedHandler
opusDataReceivedHandler:(AIBudsLiveStreamingOpusAudioDataReceivedHandler _Nullable)opusDataReceivedHandler
sessionFinishHandler:(AIBudsLiveStreamingSessionFinishHandler _Nullable)sessionFinishHandler;startJPEGImageLiveStreaming을 참고하세요.
콜백 값
| Handler | 값 | 의미 |
|---|---|---|
sessionStartCompletionHandler | success, error | 실시간 스트리밍 세션의 시작 여부를 보고합니다. |
jpegDataReceivedHandler | jpegData | 완전한 JPEG 이미지 하나를 Data / NSData로 전달합니다. |
opusDataReceivedHandler | opusData, decodedPcmAudioData | 호환되는 level-2 스트림에서 원본 Opus 데이터와 사용 가능한 경우 디코딩된 PCM 오디오를 전달합니다. |
sessionFinishHandler | isUserInitiatedStop, error | 최종 세션 결과와 사용자가 중지를 요청했는지 여부를 보고합니다. |
반환 값
메서드는 값을 직접 반환하지 않습니다. 미디어와 수명 주기 결과는 handler를 통해 전달됩니다.
사용 예제
- Swift
- Objective-C
guard let streamingDevice = device as? LiveStreamingAPI,
streamingDevice.supportsJPEGImageLiveStreaming
else { return }
streamingDevice.startJPEGImageLiveStreaming(
withSessionStartCompletionHandler: { success, error in
DispatchQueue.main.async {
self.setStreamingActive(success)
if let error { self.show(error) }
}
},
jpegDataReceivedHandler: { jpegData in
// Decode away from the UI update, then assign the image on the main queue.
guard let image = UIImage(data: jpegData) else { return }
DispatchQueue.main.async {
self.imageView.image = image
}
},
opusDataReceivedHandler: { opusData, decodedPcmAudioData in
guard let decodedPcmAudioData, !decodedPcmAudioData.isEmpty else { return }
self.consumePCM(decodedPcmAudioData)
},
sessionFinishHandler: { userStopped, error in
DispatchQueue.main.async {
self.setStreamingActive(false)
self.handleFinish(userStopped: userStopped, error: error)
}
}
)id<AIBudsLiveStreamingAPI> streamingDevice = (id<AIBudsLiveStreamingAPI>)self.device;
if (![streamingDevice conformsToProtocol:@protocol(AIBudsLiveStreamingAPI)] ||
!streamingDevice.supportsJPEGImageLiveStreaming) {
return;
}
__weak typeof(self) weakSelf = self;
[streamingDevice
startJPEGImageLiveStreamingWithSessionStartCompletionHandler:^(BOOL success, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf setStreamingActive:success];
if (error)
[weakSelf showError:error];
});
}
jpegDataReceivedHandler:^(NSData *jpegData) {
UIImage *image = [UIImage imageWithData:jpegData];
if (!image)
return;
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.imageView.image = image;
});
}
opusDataReceivedHandler:^(NSData *opusData, NSData *decodedPcmAudioData) {
if (decodedPcmAudioData.length > 0)
[weakSelf consumePCM:decodedPcmAudioData];
}
sessionFinishHandler:^(BOOL userStopped, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf setStreamingActive:NO];
[weakSelf handleFinishUserStopped:userStopped error:error];
});
}];오류 처리
- 유효하지 않은 JPEG 데이터는 거부하고 마지막 유효 이미지를 유지하세요.
- 오디오 데이터는 선택 사항입니다. 오디오 핸들러는 호환 스트림에서만 호출되며 디코딩된 PCM은
nil일 수 있습니다. sessionStartCompletionHandler실패는 세션 시작 실패로 처리하세요.sessionFinishHandler에서 사용자 중지와 예기치 않은 중단을 구분하고error가 있으면 처리하세요.- SDK가 제공하는 콜백 순서 외에 프레임 손실, 프레임률 또는 순서 보장을 임의로 가정하지 마세요.
권장 사항
- 모든 JPEG 프레임을 보관하지 마세요. 표시 이미지를 교체하거나 크기가 제한된 buffer를 사용하세요.
- 콜백이 밀리지 않도록 이미지 디코딩과 UI 반영 작업을 가볍게 유지하세요.
- 새 세션을 시작할 때 프레임 카운터와 표시 상태를 초기화하세요.
- 기능을 종료할 때 이미지 뷰만 숨기지 말고
stopLiveStreaming()을 호출하세요. - 오디오가 필요하지 않으면
nil을opusDataReceivedHandler에 전달하세요.
참고
- 공개 SDK는 고정 JPEG 해상도나 프레임률을 정의하지 않습니다.
- JPEG 모드에는
AIBudsLiveStream재생 클래스가 필요하지 않습니다. jpegDataReceivedHandler는 raw pixel buffer가 아니라 압축된 JPEG 데이터를 제공합니다.- RTMP 송출은 별도의
AIBudsLiveStream.LiveStreamer수명 주기로 관리합니다.configure(outputURL:config:)로 직접 입력 모드를 구성한 다음 스트리밍이 시작된 후에만 JPEG 프레임을pushJpegFrame(_:)으로, 비어 있지 않은 디코딩 PCM을pushPcmAudio(_:)로 전달하세요.