스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
AirPlay 오디오 경험 개선하기
앱의 AirPlay 오디오 경험을 더욱 강력하고 반응성이 높게 업그레이드하는 방법을 알아보세요. AVQueuePlayer를 이용하여 개선된 오디오 버퍼링을 채택하는 방법과 앱에 커스텀 플레이어를 구축할 때의 대안을 살펴보고, 모범 사례를 공유합니다.
챕터
- 0:42 - AirPlay Overview
- 1:43 - Enhanced audio buffering
- 3:54 - Add support to your app
리소스
관련 비디오
WWDC23
-
다운로드
♪ ♪
안녕하세요, 저는 Kelly입니다 AirPlay 팀의 엔지니어죠 세션에 오신 걸 환영해요 오늘은 AirPlay 최신 버전의 기능을 다루고 몇 가지 비법을 전수하여 앱에서 멋진 AirPlay 경험을 선사할 수 있게 도와드리죠 오늘 다룰 주제를 살펴볼게요 먼저 AirPlay의 개요로 시작해서 AirPlay의 개선된 오디오 버퍼링이 제공하는 기능을 살펴보도록 하죠 끝으로 개선된 오디오 버퍼링을 앱에 적용하는 방법을 다뤄요 AirPlay는 Apple 기기에 있는 비디오, 사진, 음악 등을 주변에 있는 스피커와 화면에 전달하는 가장 쉬운 방법이죠 가정에 AirPlay와 호환되는 기기가 많아지면서 그 어느 때보다 AirPlay의 인기가 높아졌어요 AirPlay는 다음과 같이 사용할 수 있죠 AirPlay 오디오를 통해 좋아하는 음악이나 팟캐스트를 여러 개의 HomePod으로 스트리밍하거나 AirPlay 호환 스피커와 완벽하게 동기화할 수 있죠 AirPlay 비디오로 좋아하는 영화와 TV 시리즈를 Apple 기기에서 Apple TV나 AirPlay 호환 스마트 TV로 고화질 스트리밍이 가능하며 4K HDR까지 지원해요 미러링을 통해 Apple 기기에 있는 사진, 개인 영상, 게임, 웹 페이지 스프레드시트를 Apple TV나 AirPlay 호환 스마트 TV로 공유할 수 있죠 친구와 가족도 Apple 기기에 있는 걸 쉽게 공유할 수 있어요 오늘 영상에서는 AirPlay의 오디오 스트리밍에 집중할게요 AirPlay는 매끄러운 오디오 스트리밍 경험을 1개 이상의 기기로 지원하죠 AirPlay 오디오를 지원하는 완벽한 기기 생태계가 마련돼 있어 HomePod, Mac, Apple TV와 같은 Apple 기기부터 세계 최고 브랜드의 오디오, 영상 제품은 물론 수많은 모델의 스마트 TV를 포함해요 AirPlay는 정말 편리해서 저도 개인적으로 매일 사용해요
AirPlay가 성장할수록 개발자와 고객의 기대도 높아지죠 AirPlay를 다음 단계로 끌어올릴 새롭게 개선된 프로토콜인 AirPlay의 개선된 오디오 버퍼링은 더 나은 홈 시어터와 멀티채널 경험을 선사해요 개선된 오디오 버퍼링은 홈 오디오 전체를 고려하여 처음부터 설계했죠 성능이 대단합니다 오디오는 실시간 재생보다 빠른 속도로 스트리밍하여 재생 중단을 최소화했죠 반응성이 좋아서 HomePod을 탭하면 바로 반응하고 iPhone을 리모컨으로 사용할 때도 마찬가지예요 Apple TV의 Dolby ATMOS 같은 멀티채널 오디오 포맷도 지원하고 올해는 iOS를 위한 무손실 재생을 활용하죠 개선된 오디오 버퍼링을 통해 HLS 인터스티셜 광고에 대한 최고의 지원을 제공해요 HLS 인터스티셜에 관해 더 알고 싶으면 동료 Amit의 영상인 '인터스티셜로 AirPlay 탐구하기'를 시청하세요 보는 것처럼 개선된 오디오 버퍼링을 통해 미래를 위한 훌륭한 기반을 다졌어요 이를 통합하면 여러분 앱에서 멋진 AirPlay 경험을 만들 수 있죠 개선된 오디오 버퍼링으로 어떻게 도움이 될지 알아볼게요 지금 핸드폰에서 HomePod으로 오디오를 스트리밍 중이에요
제가 쓰레기를 버리러 나갔다가 Wi-Fi 범위에서 벗어났다고 하죠 ♪ ♪ HomePod이 계속 음악을 재생해요 다시 네트워크에 연결해도 음악이 전혀 끊기지 않고 핸드폰이 매끄럽게 HomePod과 다시 연결되죠 ♪ ♪ 다시 핸드폰으로 음악 재생을 제어할 수 있어요 HomePod과 같은 AirPlay 호환 기기를 이용해 AirPlay로 음악을 재생할 때 사람들이 기대하는 성능이죠 이제 개선된 오디오 버퍼링의 놀라운 기능을 여러분의 앱에 적용할게요 AirPlay 지원을 앱에 추가하는 방법을 되짚어보죠
중요한 것은 audioSession을 적절하게 설정하여 여러분 앱의 믹싱과 중단 동작에 맞추는 거죠 미디어 재생이 앱의 중심 기능이라면 audioSession의 카테고리를 playback으로 설정하세요 이렇게 하면 앱이 백그라운드에 있을 때도 앱의 미디어를 계속 재생하죠
일반적으로 모드는 기본값으로 설정할 수 있지만 팟캐스트나 오디오북과 같은 음성 오디오는 모드를 spokenAudio로 설정하는 걸 권장해요 오디오 세션의 라우팅 정책은 longFormAudio로 설정하세요 롱폼 오디오는 음악이나 팟캐스트 같은 시스템 사운드를 제외한 모든 것이죠 올해부터 AirPlay가 어느 때보다 매끄러워졌어요 여러분의 iPhone과 iPad는 기기의 정보를 이용하여 여러분의 AirPlay 설정을 배우죠 여러분이 주로 저녁을 요리할 때 음악을 들으면 주방의 HomePod이 자동으로 나타나서 여러분 앱의 콘텐츠를 쉽게 이용하고 어디서든 재생할 수 있죠 롱폼 오디오 콘텐츠를 제공한다면 이 기능을 지원하는 게 좋아요 지능적인 AirPlay 제안을 여러분의 앱에서 간단하게 지원할 수 있죠 이미 다뤘던 AVAudioSession 설정에 추가하여 유일한 추가 단계는 앱의 Info.plist로 가서 AVInitialRouteSharingPolicy 키를 LongFormAudio로 설정하는 거예요
Xcode에서는 이 키가 'AirPlay 최적화 정책'이라는 드롭다운 메뉴에 있죠 그게 전부예요 iOS가 나머지를 처리하고 기기에서 배운 내용으로 여러분의 앱을 열 때 지능적으로 주변 스피커 사용을 제안하죠
다음은 뷰 계층 구조에 AVRoutePickerView를 추가하여 앱에 AirPlay 피커를 포함하세요 앱이 사용할 수 있는 AirPlay 기기 목록을 피커가 제공하죠
끝으로 MPNowPlayingInfoCenter로 시스템에 현재 재생 항목의 정보를 전달하고 MPRemoteCommandCenter로 재생, 일시 정지, 건너뛰기 같은 원격 명령을 수신해요 앱에 대한 AirPlay 설정을 다뤘어요 이제 개선된 오디오 버퍼링을 지원하기 위해 API 세트 2개 중 하나를 채택해야 하죠 AVPlayer와 AVQueuePlayer AVSampleBufferAudioRenderer와 AVSampleBufferRenderSynchronizer
두 API 모두 AirPlay가 아닌 재생에도 작동하며 로컬이나 Bluetooth를 포함해요 하지만 일부 개발자는 AirPlay와 AirPlay가 아닌 재생에 다른 API를 사용하고 싶을 수도 있죠 그럼 routeChangeNotification을 앱이 등록하여 현재 라우트에 맞게 행동할 수 있어요
AVPlayer와 AVQueuePlayer는 가장 간단한 방법으로 앱에 개선된 오디오 버퍼링을 지원하죠
대부분의 앱 개발자에게는 AVQueuePlayer 채택을 권장해요
AVQueuePlayer가 재생에 필요한 대부분을 처리하며 항목 관리, 재생 제어 미디어 검색을 포함하죠
Apple의 자체 미디어 앱 대부분이 AVQueuePlayer를 사용하죠 시작하려면 AVQueuePlayer를 생성하세요 재생하려는 로컬 또는 클라우드 콘텐츠의 URL을 식별하시고
URL을 넣은 AVAsset 인스턴스를 생성한 뒤 해당 애셋을 포함한 AVPlayerItem 인스턴스를 생성해요
끝으로 AVPlayerItem을 player로 가져가서 재생을 시작하세요 이렇게 간단하죠 단순히 재생 항목을 플레이어 큐에 등록했다고 생각할 거예요 AirPlay의 역할이 궁금하겠죠 맞아요 AVPlayer와 AVQueuePlayer를 이용하여 AirPlay로 라우팅했을 때 자동으로 개선된 오디오 버퍼링이 적용돼요 AVPlayer의 다른 기능이 궁금하면 설명의 링크를 참조하세요 미디어 데이터에 사전 프로세싱을 수행해야 하는 독특한 앱이거나 AVPlayer가 지원하지 않는 DRM 모델이 있다면 AVSampleBufferAudioRenderer와 AVSampleBufferRenderSynchronizer 사용이 가능하죠 API를 이용하여 다수의 큐가 있는 샘플 버퍼들을 하나의 타임라인으로 동기화하세요 오디오 데이터를 인큐하는 기본을 다룰게요 먼저 모든 재생 작업을 수행할 연속 큐를 생성해야 하죠 audioRenderer와 renderSynchronizer를 생성하세요 renderSynchronizer를 이용하여 미디어 타임라인을 확립하죠 그리고 renderSynchronizer에 audioRenderer를 추가하세요 이렇게 하면 오디오 렌더러가 미디어 타임라인을 따라가죠 데이터가 필요하다는 콜백 설치로 오디오 데이터를 인큐하세요
오디오 데이터를 해당 콜백에 인큐하세요
오디오 데이터가 없으면 렌더러에 데이터 요청을 그만하라고 전달하세요 이건 인터페이스의 기본일 뿐이죠 자세한 내용은 설명에 링크된 문서에 있으며 이 API를 사용하는 방법을 깊게 다루며 커스텀 플레이어를 만드는 샘플 프로젝트도 있어요 여러분이 사용할 수 있는 2개의 API를 통해 AirPlay 호환 기기에서 개선된 오디오 버퍼링을 사용할 수 있죠 그게 전부가 아니죠 이제 자동차 제조사에서도 CarPlay에서 개선된 오디오 버퍼링을 지원해요 이게 왜 중요하냐고요? 갈수록 많은 차량이 무선 CarPlay를 지원하죠 풍성한 재생과 반응성이 좋은 컨트롤이 있어야 주행 중에도 최고의 오디오 경험을 할 수 있어요 좋은 소식은 여러분의 앱에 개선된 오디오 버퍼링을 앞에서 다룬 2개의 API 중 하나를 이용해 추가하면 CarPlay에서도 작동한다는 거죠 여러분의 앱을 사용하는 사람들이 최고의 오디오 스트리밍 경험을 어디에서든 즐길 수 있을 거예요 정리하면, 오디오 세션 설정으로 AirPlay 지원이 가능하며 앱에 AirPlay 피커를 추가하고 앱에 Media Player를 통합하고 AVQueuePlayer나 커스텀 렌더링 및 동기화 API로 개선된 오디오 버퍼링을 채택할 수 있어요 이것은 시작에 불과하죠 지속된 개선과 작업을 통해 더 많은 기능을 제공할 거예요 즐거운 세션이 됐길 바라요 감사합니다 ♪ ♪
-
-
4:00 - Set the audio type
let audioSession = AVAudioSession.sharedInstance() try audioSession.setCategory(. playback ,xmode: . default , policy:.longFormAudio )
-
7:23 - AVQueuePlayer
let player = AVQueuePlayer() let url = URL(string: "http://www.examplecontenturl.com") let asset = AVAsset(url: url) let item = AVPlayItem(asset: asset) player.insert(item, after: nil) player.play()
-
8:28 - Add the audio renderer to the render synchronizer
let serializationQueue = DispatchQueue(label: "sample.buffer.player.serialization.queue") let audioRenderer = AVSampleBufferAudioRenderer() let renderSynchronizer = AVSampleBufferRenderSynchronizer() renderSynchronizer.addRenderer(audioRenderer)
-
8:50 - Enqueue audio data
serializationQueue.async { [weak self] in guard let self = self else { return } // Start processing audio data and stop when there's no more data. self.audioRenderer.requestMediaDataWhenReady(on: serializationQueue) { [weak self] in guard let self = self else { return } while self.audioRenderer.isReadyForMoreMediaData { let sampleBuffer = self.nextSampleBuffer() // Returns nil at end of data. if let sampleBuffer = sampleBuffer { self.audioRenderer.enqueue(sampleBuffer) } else { // Tell the renderer to stop requesting audio data. audioRenderer.stopRequestingMediaData() } } } // Start playback at the natural rate of the media. self.renderSynchronizer.rate = 1.0 }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.