내용이 잘못 되었다면 댓글 남겨주세요.
깃허브 videoLab에 관한 글입니다.
AVFoundation video editing workflow
- 하나 이상의 AVAsset을 만든다.
- AVComposition, AVVideoComposition 및 AVAudioMix를 만듬
- 이 세가지 객체를 사용하여 AVPlayerItem을 생성할 수 있고
- 이로 부터 AVPlayer를 생성하여 편집 효과를 재생할 수 있다.
- 또한 이 세가지 객체를 이용하여 AVAssetExportSession을 생성하여 편집 결과를 파일에 쓸 수 도 있다.
- AVComposition
- 소스 트랙의 시간적 정렬을 지정
- 원본 미디어 자료에서 가져온 미디어를 담고 있는 트랙
- 트랙이란
- 미디어 자료의 시간적인 구조를 설명하는 요소
- AVCompostion Track 오디오 및 비디오 컬렉션인 AVCompostion
- AVComposition Track은 여러 AVAsset의 AVAssetTrack을 포함할 수 있다.
- 그림은 두 AVAsset의 오디오/비디오 AVAsset Track이 AVCompsition의 오디오/비디오 AVComposition Track으로 결합된다.
- 여러 asset에서 가져온 미디어를 단일로 통합된 asset으로 결합하고 정렬하는 객체입니다.
- Compostion은 하나 이상의 미디어 트랙을 포함하는 컨테이너이다.
- 소스 트랙의 시간적 정렬을 지정
- AVVideoCompostion
- 특정 시점에서 비디오 프레임을 어떻게 합성할지 설명하는 객체입니다.
- 내장된 비디오 합성기를 사용하는 경우, 비디오 합성의 지침에는 각 비디오 소스에 대한 공간 변환, 불투명도 값, 자르기 사각형을 지정할 수 있습니다.
- 이러한 값들은 시간에 따라 linear ramping functions(선형 램프 함수)를 적용하여 변할 수 있습니다.
- 선형 램프 함수 : 시간에 따라 값이 일정하게 변화함
- 비디오 합성에서 선형 램핑 함수를 사용하면, 각 프레임엣 적용되는 변환, 불투명도, 크롭 등의 값이 시간에 따라 부드럽게 변경될 수 있어 자연스러운 비디오 효과를 만들 수 있다.
- AVVideoCompositing 프로토콜을 구현함으로써 사용자 정의 비디오 합성기를 만들 수 있다.
- 시스템은 사용자 정의 비디오 합성기에게 재생 중에 비디오 소스에 대한 픽셀 버퍼를 제공하며 이를 사용하여 임의의 그래픽 작업을 수행하여 시각적 출력물을 생성할 수 있다.
- 아래 그림은 AVComposition에 두 개의 AVComposition Track이 포함되었다. 시점 T1에서 두 AVComposition Track의 이미지를 혼합해야한다. 이를 위해서 AVVideoComposition을 사용해아한다.
- AVVideoComposition을 사용하여 렌더링 크기, 렌더링 크기 조정, 프레임 속도를 지정할 수 있다.
- 또한 AVVideoCompositionInstructionProtocol 프로토콜을 구현하는 명령어 배열이 저장되며 이러한 명령어는 혼합 매개 변수를 저장합니다.
- 이러한 혼합 매개변수를 사용하면 AVVideoComposition은 해당이미지 프레임을 AVVideoCompositing 프로토콜을 구현하는 합성기와 혼합할 수 있습니다.
- Compositor에 중점을 두어 여러 개의 원본 프레임을 처리하고 새로운 하나의 출력물을 만들어야 하는 작업에 초점을 맞추고 있습니위의 다이어그램에서 해당 작업의 흐름이 나와있습니다.
- AVAsynchronousVideoCompositionRequest는 현재 시간에 대한 일련의 원본 프레임과 해당 시간이 위치한 instruction을 묶는다.
- AVAsynchronousVideoCompositionRequest
- 비디오 합성기가(AVVideoCompositing 프로토콜을 채택해야함) 출력 픽셀 버퍼를 렌더링하는 데 필요한 정보를 담고 있는 객체입니다.
- 이 객체는 비동기적으로 처리되는 비디오 합성 요청에 대한 정보를 제공하며, 비디오 합성기는 이 정보를 활용하여 각 프레임에 대한 렌더링을 수행한다.
- AVAsynchronousVideoCompositionRequest
- startVideoCompositionsRequest : 콜백을 받아 Request를 처리한다.
- Instruction, Your Mixing Parameters, Source Frame 들을 기반으로 합성 프레임을 렌더링한다.
- 렌더링된 프레임을 전달하기 위해 finishWithComposedVideoFrame을 호출
- AVAudioMix를 사용하여 AVCompostion의 오디오 트랙에서 오디오를 처리할 수 있습니다.
- AVAudioMix에는 AVAudioMixInputParameters 세트가 포함되어 있으며 각 AVAudioMixInputParameters는 오디오 AVComposition Track에 해당합니다.
- AVAudioMixInputParameters는 오디오를 실시간으로 처리하는 데 사용할 수 있는 MTAudioProcessingTap을 포함하고 있습니다.
- 물론 선형 볼륨 변경에 대해서는 setVolumeRampFromStartVolume:toEndVolume:timeRange: 인터페이스를 직접 사용할 수 있습니다.
- 또한 AVAudioMixInputParameters는 피치를 설정하는 데 사용할 수 있는 AVAudioTimePitchAlgorithm도 포함하고 있습니다.
- RenderCompostion은 AE의 합성물에 해당하며, 여러 RenderLayer를 포함합니다.
- 또한 RenderComposition에는 backgroundColor, frameDuration, renderSize도 포함 되어 있다.
- 이는 각각 배경색, 프레임 속도, 그리고 렌더 크기 매개변수에 해당합니다.
- RenderLayer는 AE의 레이어에 해당합니다.
- 여기에는 Source(소재의 원본), timeRange(타임라인에서의 시간간격), Transform(변형{위치, 회전. 크기}), AudioConfiguration(오디오 설정), Operations(효과 작업 그룹)가 포함되어 있습니다.
- RenderLayerGroup은 AE의 사전 합성에 해당합니다. RenderLayoutGroup은 RenderLayer를 상속하며, 여러 RenderLayer를 그룹화합니다.
- KeyframeAnimation은 AE의 키프레임 애니메이션에 해당합니다.
- 여기에는 KeyPath(키프레임 경로), Values(값 배열), KeyTimes(키 프레임 시간 배열), TimingFunctions(이징 함수 배열:움직임 부드럽게 하기 위한 함수)가 포함되어 있습니다.
- 앞 서 소개한 AVFoundation에서 알 수 있듯이, 재생 및 내보내기를 위해 AVPlayerItem과 AVAssetExportSession을 생성해야 합니다.
- 따라서 이러한 설명 객체를 파싱하고 AVFoundation의 메서드를 사용하여 AVPlayerItem과 AVAssetExportSession을 생성할 수 있는 객체가 필요합니다.
- 이 프레임 워크에서는 이러한 객체를 VideoLab이라고 명명한다.
- 하나 이상의 RenderLayer 생성
- 하나 이상의 레이어를 생성합니다.
- 이는 AE에서의 레이어에 해당하며, 각 레이어는 물체의 소스, 타임라인에서의 시간 간격, 변형, 오디오 설정, 효과 연산 그룹등을 정의합니다.
- RenderComposition 생성 및 설정
- RenderComposition을 생성하고 해당 Composition의 속성들을 설정합니다.
- BackgroundColor, FrameDuration, RenderSize등을 설정합니다.
- RenderLayer 배열을 구성하여 이를 Compostion에 추가합니다.
- 생성한 RenderComposition으로 VideoLab 생성
- 이전에 생성한 RenderComposition을 사용하여 VideoLab을 생성합니다.
- VideoLab은 프레임 워크에서 AVPlayerItem 또는 AVAssetExportSession을 생성하는데 사용되는 객체입니다.
- VideoLab을 사용하여 AVPlayerItem또는 AVAssetExportSession을 생성
- VideoLab을 활용하여 AVPlayerItem 또는 AVAssetExportSession을 생성합니다.
- 이 단계에서 실제로 비디오를 재생하거나 내보내기 위한 미디어 항목을 생성합니다.
프레임워크 구현
source
public protocol Source {
var selectedTimeRange: CMTimeRange { get set }
func tracks(for type: AVMediaType) -> [AVAssetTrack]
func texture(at time: CMTime) -> Texture?
}
- RenderLayer에는 물질의 소스가 포함될 수 있다.
- 소스는 오디오, 비디오, 정지 이미지 등이 될 수 있다.
- 프레임 워크에서는 이러한 미디어 소스를 추상화 하기 위해 Source 프로토콜을 도입했다.
- 소스 해석
- selectedTimeRange
- 클립 자체의 선택된 시간의 범위
- 예를 들어, 2분짜리 비디오에서 60초에서 70초의 범위를 선택하여 편집하는 경우
- selectedTimeRange는 60-70초이다.
- 코드에서는 CMTime을 사용
- tracks(for:)
- 메서드 AVMediaType에 따라 AVAssetTrack을 가져오기 위한 메서드이다.
- 이 메서드를 사용하면 특정 미디어 타입에 해당하는 트랙을 가져올수 있다.
- texture(at:)
- 시간을 기반으로 텍스쳐를 가져오기 위한 메서드입니다.
- 시간에 따라 텍스쳐를 가져와서 활용할 수 있습니다.
- selectedTimeRange
- 프레임 워크가 제공하는 4가지 소스
- AVAssetSource : AVAsset에 기반한 소스로, 주로 동영상에 사용된다.
- ImageSource : 정지 이미지에 대한 소스로 사용된다.
- PHAssetVideoSource : 앨범 비디오에 대한 소스로 사용된다.
- PHAssetImageSource : 앨범 이미지에 대한 소스로 사용된다.
- 사용자 정의 소스를 정의하기 위해 Source프로토콜을 구현할 수도 있습니다.
- videoLab 클래스가 RenderComposition, RenderLayer, RenderLayerGroup, KeyframeAnimation, Source를 사용하여 AVComposition, AVVideoComposition, AVAudioMix를 생성하는 방법을 소개한다.
AVComposition
- AVComposition에 비디오 트랙과 오디오 트랙을 추가해야한다.
- 아래 예시를 통해 이 과정을 설명하겠다.
- 이 RenderComposition에는 RenderLayer1(비디오/오디오 포함), RenderLayer2(비디오만), RenderLayer3(이미지), RenderLayer4(효과 연산 그룹만), RenderLayerGroup(RenderLayer5, RenderLayer6을 포함, 둘 다 비디오/오디오를 포함)이 있습니다.
1단계 - RenderLayer를 VideoRenderLayer로 변환
- 비디오 트랙을 추가하는 과정은 여러 단계로 이루어지며, 첫번째 단계는 RenderLayer를 VideoRenderLayer로 변환하는 것입니다.
- VideoRenderLayer는 비디오 트랙을 AVComposition에 추가하는 주된 역할을 하는 내부 프레임 워크 객체입니다.
- VideoRenderLayer로 변환할 수 있는 RenderLayer에는 다음과 같은 유형이 포함됩니다.
- 소스에 비디오 트랙이 포함된 경우
- 소스가 이미지 유형인 경우
- 효과 연산 그룹이 비어있지 않은 경우(Operations)
- 또한 VideoRenderLayerGroup은 내부 프레임 워크 객체로 RenderLayerGroup을 포함합니다.
- VideoRenderLayerGroup으로 변환할 수 있는 RenderLayerGroup은 단 하나의 조건을 충족하면 됩니다.
- 포함된 RenderLayer 그룹 중 하나가 VideoRenderLayer로 변환할 수 있는 것이어야한다.
- VideoRenderLayer로 변환한 후의 결과는 다음과 같습니다.
2단계 - AVComposition에 VideoRenderLayer 비디오 트랙 추가
- 두번째 단계는 AVComposition에 VideoRenderLayer 비디오 트랙 추가
- RenderLayer의 Source가 비디오 트랙을 포함하는 VideoRenderLayer의 경우, 해당 Source에서 비디오 AVAssetTrack을 가져와 AVCompposition에 추가합니다.
- 이미지 유형인 RenderLayer의 소스가 이미지 유형인 VideoRenderLayer 또는 효과 작업만 있는 VideoRenderLayer(Source가 비어 있음)의 경우 빈 비디오를 사용하여 새 비디오 트랙을 추가합니다.
- 빈 비디오는 비디오 트랙이 검은색 프레임이고 오디오 트랙이 포함되어 있지 않은 비디오
- 추가되면 AVComposition의 비디오 트랙이 다음과 같이 표시됨
- 위의 그림에서 보듯이 VideoRenderLayer1과 VideoRenderLayer5는 하나의 비디오 트랙을 공유합니다.
- 이는 Apple이 비디오 트랙 수에 제한을 두고 있기 때문에 가능한 한 많은 비디오 트랙을 재사용해야하는 필요성이 있습니다.
- 각 비디오 트랙은 하나의 디코더에 해당하며, 디코더 수가 시스템 제한을 초과하면 디코딩 오류가 발생할 수 있습니다.
- 비디오 트랙 재사용의 원리는 추가하려는 VideoRenderLayer가 이전 비디오 트랙의 VideoRenderLayer와 시간적으로 겹치지 않는 경우 해당 비디오 트랙을 재사용 할 수 있다는 것이다.
- 기존의 비디오 트랙을 모두 재사용할 수 없다면 새로운 비디오 트랙을 추가한다.
1단계 - RenderLayer를 AudioRenderLayer로 변환
- 오디오 트랙 추가하는 단계로 넘어가겠다.
- RenderLayer를 AudioRenderLayer로 변환
- AudioRenderLayer는 RenderLayer를 포함하는 내부 프레임워크 객체로, 주로 RenderLayer의 오디오 트랙을 AVComposition에 추가하는 역할을 한다.
- AudioRenderLayer로 변환할 수 있는 RenderLayer는 하나의 조건만 충족하면 된다.
- Source에 오디오 트랙이 포함되어 있어야한다.
- AudioRenderLayerGroup로 변환
- AudioRenderLayerGroup은 RenderLayerGroup을 포함하는 내부 프레임 객체로
- 변환가능한 RenderLayerGroup은 하나의 조건만 충족하면 된다.
- 포함된 RenderLayer 그룹 중 하나가 AudioRenderLayer로 변환가능해야한다.
- RenderLayer를 AudioRenderLayer로 변환
- AudioRenderLayer로 변환한 후의 결과는 다음과 같다.
2단계 - AVComposition에 AudioRenderLayer 오디오 트랙 추가
- RenderLayer의 Source에 오디오 트랙이 포함된 AudioRenderLayer의 경우, Source에서 오디오 AVAssetTrack을 가져와 AVComposition에 추가합니다.
- 한 번 추가되면 AVComposition의 오디오 트랙은 다음과 같이 나타난다.
- 그림에서 볼 수 있듯이 비디오 트랙의 재사용과는 달리 각 AudioRenderLayer는 하나의 오디오 트랙에 대응됩니다.
- 이는 하나의 AVAudioMixInputParameters가 하나의 오디오 트랙에 대응하며, 그 피치 설정(audioTimePitchAlgorithm)이 전체 오디오 트랙에 영향을 미침을 의미한다.
- 재사용하면 하나의 오디오 트랙에 여러 AudioRenderLayer가 생성될 수 있으며, 모든 AudioRenderLayer를 동일한 피치로 구성해야하므로 합리적이지 않습니다.
AVVideoCompostion
- AVVideoComposition
- 이전 AVFoundation 소개에서 알 수 있듯이. AVVideoCompostion을 사용하여 렌더 크기, 렌더 스케일링, 그리고 프레임 속도를 지정할 수 있습니다.
- 또한, 블렌딩 매개변수를 저장하는 Instruction 세트가 있다.
- 이러한 블렌딩 매개변수를 사용하여 AVVideoComposition은 사용자 정의 Compositor로 해당 이미지 프레임을 혼합할 수 있다.
- 이 섹션에서는 이러한 Instuction 세트를 생성하고 AVVideoComposition을 만드는 방법에 중점을 둘 것입니다.
- 앞 섹션에서는 생성한 VideoRenderLayer를 사용하여 이 Instruction 세트를 생성합니다.
- 다음은 간단한 예제로 이 프로세스를 설명하겠습니다.
- 아래 그림에서 볼 수 있듯이, 이 AVComposition에는 VideoRenderLayer1, VideoRenderLayer2, VideoRenderLayer3d이 있습니다.
- 변환 프로세스는 다음과 같은 단계로 이루어집니다.
- 각 VideoRenderLayer의 타임라인 상의 시작 및 종료 시간 지점을 기록합니다.(아래의 T1-T6)
- 각 시간 간격에 대한 Instuction을 생성하고, 해당 시간 간격과 교차하는 모든 VideoRenderLayer를 Instruction의 블렌딩 매개변수로 사용합니다.(아래의 Instruction1-Instruction5)
- 그런 다음 AVVideoComposition을 생성하고 프레임 속도, 렌더 크기, Insruction 세트 및 사용자 정의 Compositor를 설정합니다.
- 아래는 코드 입니다.
let videoComposition = AVMutableVideoComposition()
videoComposition.frameDuration = renderComposition.frameDuration
videoComposition.renderSize = renderComposition.renderSize
videoComposition.instructions = instructions
videoComposition.customVideoCompositorClass = VideoCompositor.self
- 지금까지 렌더링에 필요한 Instruction 세트와 블렌딩 매개변수를 갖추었고, 계속해서 Compositor에서 이를 사용하여 프레임을 그리는 방법에 대해 알아보겠습니다.
- Instruction과 교차하는 VideoRenderLayer 그룹에 대한 블렌딩 매개 변수를 업데이트하여 이전의 Compositor 워크 플로우를 업데이트 합니다.
- 예제를 통해 비디오 블렌딩 규칙을 설명하겠습니다.
- 아래 그림에서 보듯이, 우리는 이러한 VideoRenderLayer 프레임들을 T1 시점에서 블렌딩하고자 합니다.
- 우리의 렌더링 블렌딩 규칙은 다음과 같다.
- RenderLayer가 포함하는 VideoRenderLayer 그룹을 RenderLayer의 leyerLevel에 따라 정렬합니다. 위에 보이는 것처럼
- VideoRenderLayer 그룹을 반복하며 다음 세가지 블렌딩에 대해 VideoRenderLayer에 적용합니다.
- 현재 VideoRenderLayer는 VideoRenderLayerGroup이며, 이는 사전 합성된 방식입니다.
- 자체 내부의 VideoRenderLayer 그룹을 반복한 후에 텍스처를 생성하고 이전 텍스처에 블렌딩합니다.
- 현재 VideoRenderLayer의 Source에 비디오 트랙이 포함되어 있거나 Source가 이미지 유형인 경우, 자체의 효과연산 그룹(Operations)을 처리하기 위해 해당 텍스처를 가져온 후 이전 텍스처에 블렌딩합니다.
- 현재 VideoRenderLayer에는 효과 연산이 그룹만 있으며, 모든 작업이 이전에 블렌딩된 텍스처에 적용됩니다.
- 렌더링 블렌딩 규칙 요약
- 레이어 별로 bottom-up으로 렌더링합니다.
- 현재 레이어에 텍스쳐가 있다면 먼저 자체 텍스처를 처리한 다음 이전 텍스처에 블렌딩합니다.
- 현재 레벨에서 텍스처가 없으면 작업이 직접 이전 텍스처에 적용됩니다.
- 이러한 규칙을 위의 예제에 적용해보겠습니다. 최종 출력 텍스처를 Output Texture로 가정합니다.
- bottom VideoRenderLayerGroup를 처리하여 Texture1을 생성하고, Texture1을 Output Texture에 블렌딩합니다
- VideoRenderLayer2를 처리하여 Texture2를 생성하고, Texture2를 Output Texture에 블렌딩합니다.
- VideoRenderLayer3를 처리하여 Texture3을 생성하고, Texture3을 Output Texture에 블렌딩합니다.
- VideoRenderLayer4의 효과 연산 그룹을 처리하고, 이것을 Output Texture에 적용합니다.
'ios' 카테고리의 다른 글
8. Xcode button의 Sent Events에 대해서 알아보자 (0) | 2023.12.04 |
---|---|
7. iOS UIApplication 공부하기 (0) | 2023.11.21 |
5. Swift Concurrency (0) | 2023.10.09 |
4. iOS13 AppDelegate, SceneDelegate의 역할 (0) | 2023.09.14 |
3. WKWebView 공식문서 공부 2편 (0) | 2023.09.12 |