본문 바로가기

ios

6. ios videoLab에 대한 문서 공부

내용이 잘못 되었다면 댓글 남겨주세요.

깃허브 videoLab에 관한 글입니다.

AVFoundation video editing workflow

AVFoundation video editing workflow

 

  1. 하나 이상의 AVAsset을 만든다.
  2. AVComposition, AVVideoComposition 및 AVAudioMix를 만듬
  3. 이 세가지 객체를 사용하여 AVPlayerItem을 생성할 수 있고
  4. 이로 부터 AVPlayer를 생성하여 편집 효과를 재생할 수 있다.
  5. 또한 이 세가지 객체를 이용하여 AVAssetExportSession을 생성하여 편집 결과를 파일에 쓸 수 도 있다.

AVComposition

 

  1. AVComposition
    1. 소스 트랙의 시간적 정렬을 지정
      1. 원본 미디어 자료에서 가져온 미디어를 담고 있는 트랙
    2. 트랙이란
      1. 미디어 자료의 시간적인 구조를 설명하는 요소
    3. AVCompostion Track 오디오 및 비디오 컬렉션인 AVCompostion
    4. AVComposition Track은 여러 AVAsset의 AVAssetTrack을 포함할 수 있다.
    5. 그림은 두 AVAsset의 오디오/비디오 AVAsset Track이 AVCompsition의 오디오/비디오 AVComposition Track으로 결합된다.
    6. 여러 asset에서 가져온 미디어를 단일로 통합된 asset으로 결합하고 정렬하는 객체입니다.
    7. Compostion은 하나 이상의 미디어 트랙을 포함하는 컨테이너이다.

AVVideoComposition

  1. AVVideoCompostion
    1. 특정 시점에서 비디오 프레임을 어떻게 합성할지 설명하는 객체입니다.
    2. 내장된 비디오 합성기를 사용하는 경우, 비디오 합성의 지침에는 각 비디오 소스에 대한 공간 변환, 불투명도 값, 자르기 사각형을 지정할 수 있습니다. 
    3. 이러한 값들은 시간에 따라 linear ramping functions(선형 램프 함수)를 적용하여 변할 수 있습니다.
      1. 선형 램프 함수 : 시간에 따라 값이 일정하게 변화함
      2. 비디오 합성에서 선형 램핑 함수를 사용하면, 각 프레임엣 적용되는 변환, 불투명도, 크롭 등의 값이 시간에 따라 부드럽게 변경될 수 있어 자연스러운 비디오 효과를 만들 수 있다.
    4. AVVideoCompositing 프로토콜을 구현함으로써 사용자 정의 비디오 합성기를 만들 수 있다.
    5. 시스템은 사용자 정의 비디오 합성기에게 재생 중에 비디오 소스에 대한 픽셀 버퍼를 제공하며 이를 사용하여 임의의 그래픽 작업을 수행하여 시각적 출력물을 생성할 수 있다.
    6. 아래 그림은 AVComposition에 두 개의 AVComposition Track이 포함되었다. 시점 T1에서 두 AVComposition Track의 이미지를 혼합해야한다. 이를 위해서 AVVideoComposition을 사용해아한다.
    7. AVVideoComposition을 사용하여 렌더링 크기, 렌더링 크기 조정, 프레임 속도를 지정할 수 있다.
    8. 또한 AVVideoCompositionInstructionProtocol 프로토콜을 구현하는 명령어 배열이 저장되며 이러한 명령어는 혼합 매개 변수를 저장합니다.
    9. 이러한 혼합 매개변수를 사용하면 AVVideoComposition은 해당이미지 프레임을 AVVideoCompositing 프로토콜을 구현하는 합성기와 혼합할 수 있습니다.

AVVideoComposition
AVVideoComposition

  1. Compositor에 중점을 두어 여러 개의 원본 프레임을 처리하고 새로운 하나의 출력물을 만들어야 하는 작업에 초점을 맞추고 있습니위의 다이어그램에서 해당 작업의 흐름이 나와있습니다.
  2. AVAsynchronousVideoCompositionRequest는 현재 시간에 대한 일련의 원본 프레임과 해당 시간이 위치한 instruction을 묶는다.
    1. AVAsynchronousVideoCompositionRequest
      1. 비디오 합성기가(AVVideoCompositing 프로토콜을 채택해야함) 출력 픽셀 버퍼를 렌더링하는 데 필요한 정보를 담고 있는 객체입니다.
      2. 이 객체는 비동기적으로 처리되는 비디오 합성 요청에 대한 정보를 제공하며, 비디오 합성기는 이 정보를 활용하여 각 프레임에 대한 렌더링을 수행한다.
  3. startVideoCompositionsRequest : 콜백을 받아 Request를 처리한다.
  4. Instruction, Your Mixing Parameters, Source Frame 들을 기반으로 합성 프레임을 렌더링한다.
  5. 렌더링된 프레임을 전달하기 위해 finishWithComposedVideoFrame을 호출

 

AVAudioMix

  1. AVAudioMix를 사용하여 AVCompostion의 오디오 트랙에서 오디오를 처리할 수 있습니다.
  2. AVAudioMix에는 AVAudioMixInputParameters 세트가 포함되어 있으며 각 AVAudioMixInputParameters는 오디오 AVComposition Track에 해당합니다.
  3. AVAudioMixInputParameters는 오디오를 실시간으로 처리하는 데 사용할 수 있는 MTAudioProcessingTap을 포함하고 있습니다.
  4. 물론 선형 볼륨 변경에 대해서는 setVolumeRampFromStartVolume:toEndVolume:timeRange: 인터페이스를 직접 사용할 수 있습니다.
  5. 또한 AVAudioMixInputParameters는 피치를 설정하는 데 사용할 수 있는 AVAudioTimePitchAlgorithm도 포함하고 있습니다.

디자인 설명

  1. RenderCompostion은 AE의 합성물에 해당하며, 여러 RenderLayer를 포함합니다.
  2. 또한 RenderComposition에는 backgroundColor, frameDuration, renderSize도 포함 되어 있다.
  3. 이는 각각 배경색, 프레임 속도, 그리고 렌더 크기 매개변수에 해당합니다.
  4. RenderLayer는 AE의 레이어에 해당합니다.
  5. 여기에는 Source(소재의 원본), timeRange(타임라인에서의 시간간격), Transform(변형{위치, 회전. 크기}), AudioConfiguration(오디오 설정), Operations(효과 작업 그룹)가 포함되어 있습니다.
  6. RenderLayerGroup은 AE의 사전 합성에 해당합니다. RenderLayoutGroup은 RenderLayer를 상속하며, 여러 RenderLayer를 그룹화합니다.
  7. KeyframeAnimation은 AE의 키프레임 애니메이션에 해당합니다.
  8. 여기에는 KeyPath(키프레임 경로), Values(값 배열), KeyTimes(키 프레임 시간 배열), TimingFunctions(이징 함수 배열:움직임 부드럽게 하기 위한 함수)가 포함되어 있습니다.
  9. 앞 서 소개한 AVFoundation에서 알 수 있듯이, 재생 및 내보내기를 위해 AVPlayerItem과 AVAssetExportSession을 생성해야 합니다.
  10. 따라서 이러한 설명 객체를 파싱하고 AVFoundation의 메서드를 사용하여 AVPlayerItem과 AVAssetExportSession을 생성할 수 있는 객체가 필요합니다.
  11. 이 프레임 워크에서는 이러한 객체를 VideoLab이라고 명명한다.

 

  1. 하나 이상의 RenderLayer 생성
    1. 하나 이상의 레이어를 생성합니다.
    2. 이는 AE에서의 레이어에 해당하며, 각 레이어는 물체의 소스, 타임라인에서의 시간 간격, 변형, 오디오 설정, 효과 연산 그룹등을 정의합니다.
  2. RenderComposition 생성 및 설정
    1. RenderComposition을 생성하고 해당 Composition의 속성들을 설정합니다.
    2. BackgroundColor, FrameDuration, RenderSize등을 설정합니다.
    3. RenderLayer 배열을 구성하여 이를 Compostion에 추가합니다.
  3. 생성한 RenderComposition으로 VideoLab 생성
    1. 이전에 생성한 RenderComposition을 사용하여 VideoLab을 생성합니다.
    2. VideoLab은 프레임 워크에서 AVPlayerItem 또는 AVAssetExportSession을 생성하는데 사용되는 객체입니다.
  4. VideoLab을 사용하여 AVPlayerItem또는 AVAssetExportSession을 생성
    1. VideoLab을 활용하여 AVPlayerItem 또는 AVAssetExportSession을 생성합니다.
    2. 이 단계에서 실제로 비디오를 재생하거나 내보내기 위한 미디어 항목을 생성합니다.

 

프레임워크 구현

 

source

public protocol Source {
    var selectedTimeRange: CMTimeRange { get set }
    
    func tracks(for type: AVMediaType) -> [AVAssetTrack]
    func texture(at time: CMTime) -> Texture?
}

 

  1. RenderLayer에는 물질의 소스가 포함될 수 있다. 
  2. 소스는 오디오, 비디오, 정지 이미지 등이 될 수 있다.
  3. 프레임 워크에서는 이러한 미디어 소스를 추상화 하기 위해 Source 프로토콜을 도입했다.
  4. 소스 해석
    1. selectedTimeRange 
      1. 클립 자체의 선택된 시간의 범위
      2. 예를 들어, 2분짜리 비디오에서 60초에서 70초의 범위를 선택하여 편집하는 경우 
      3. selectedTimeRange는 60-70초이다.
      4. 코드에서는 CMTime을 사용
    2. tracks(for:)
      1. 메서드 AVMediaType에 따라 AVAssetTrack을 가져오기 위한 메서드이다.
      2. 이 메서드를 사용하면 특정 미디어 타입에 해당하는 트랙을 가져올수 있다.
    3. texture(at:)
      1. 시간을 기반으로 텍스쳐를 가져오기 위한 메서드입니다.
      2. 시간에 따라 텍스쳐를 가져와서 활용할 수 있습니다.
  5. 프레임 워크가 제공하는 4가지 소스
    1. AVAssetSource : AVAsset에 기반한 소스로, 주로 동영상에 사용된다.
    2. ImageSource : 정지 이미지에 대한 소스로 사용된다.
    3. PHAssetVideoSource : 앨범 비디오에 대한 소스로 사용된다.
    4. PHAssetImageSource : 앨범 이미지에 대한 소스로 사용된다.
  6. 사용자 정의 소스를 정의하기 위해 Source프로토콜을 구현할 수도 있습니다.
  7. videoLab 클래스가 RenderComposition, RenderLayer, RenderLayerGroup, KeyframeAnimation, Source를 사용하여 AVComposition, AVVideoComposition, AVAudioMix를 생성하는 방법을 소개한다.

 

AVComposition

 

  1. AVComposition에 비디오 트랙과 오디오 트랙을 추가해야한다.
  2. 아래 예시를 통해 이 과정을 설명하겠다.
  3. 이 RenderComposition에는 RenderLayer1(비디오/오디오 포함), RenderLayer2(비디오만), RenderLayer3(이미지), RenderLayer4(효과 연산 그룹만), RenderLayerGroup(RenderLayer5, RenderLayer6을 포함, 둘 다 비디오/오디오를 포함)이 있습니다.

renderLayer

 

1단계 - RenderLayer를  VideoRenderLayer로 변환

  1. 비디오 트랙을 추가하는 과정은 여러 단계로 이루어지며, 첫번째 단계는 RenderLayer를 VideoRenderLayer로 변환하는 것입니다.
  2. VideoRenderLayer는 비디오 트랙을 AVComposition에 추가하는 주된 역할을 하는 내부 프레임 워크 객체입니다.
  3. VideoRenderLayer로 변환할 수 있는 RenderLayer에는 다음과 같은 유형이 포함됩니다.
    1. 소스에 비디오 트랙이 포함된 경우
    2. 소스가 이미지 유형인 경우
    3. 효과 연산 그룹이 비어있지 않은 경우(Operations)
  4. 또한 VideoRenderLayerGroup은 내부 프레임 워크 객체로 RenderLayerGroup을 포함합니다.
  5. VideoRenderLayerGroup으로 변환할 수 있는 RenderLayerGroup은 단 하나의 조건을 충족하면 됩니다.
    1. 포함된 RenderLayer 그룹 중 하나가 VideoRenderLayer로 변환할 수 있는 것이어야한다.
  6. VideoRenderLayer로 변환한 후의 결과는 다음과 같습니다.

VideoRenderLayer

2단계 - AVComposition에 VideoRenderLayer 비디오 트랙 추가

  1. 두번째 단계는 AVComposition에 VideoRenderLayer 비디오 트랙 추가
    1. RenderLayer의 Source가 비디오 트랙을 포함하는 VideoRenderLayer의 경우, 해당 Source에서 비디오 AVAssetTrack을 가져와 AVCompposition에 추가합니다.
    2. 이미지 유형인 RenderLayer의 소스가 이미지 유형인 VideoRenderLayer 또는 효과 작업만 있는 VideoRenderLayer(Source가 비어 있음)의 경우 빈 비디오를 사용하여 새 비디오 트랙을 추가합니다.
    3. 빈 비디오는 비디오 트랙이 검은색 프레임이고 오디오 트랙이 포함되어 있지 않은 비디오
    4. 추가되면 AVComposition의 비디오 트랙이 다음과 같이 표시됨
     

AVComposition의 비디오 트랙

  1. 위의 그림에서 보듯이 VideoRenderLayer1과 VideoRenderLayer5는 하나의 비디오 트랙을 공유합니다.
  2. 이는 Apple이 비디오 트랙 수에 제한을 두고 있기 때문에 가능한 한 많은 비디오 트랙을 재사용해야하는 필요성이 있습니다.
  3. 각 비디오 트랙은 하나의 디코더에 해당하며, 디코더 수가 시스템 제한을 초과하면 디코딩 오류가 발생할 수 있습니다.
  4. 비디오 트랙 재사용의 원리는 추가하려는 VideoRenderLayer가 이전 비디오 트랙의 VideoRenderLayer와 시간적으로 겹치지 않는 경우 해당 비디오 트랙을 재사용 할 수 있다는 것이다.
  5. 기존의 비디오 트랙을 모두 재사용할 수 없다면 새로운 비디오 트랙을 추가한다.

 

 

1단계 - RenderLayer를  AudioRenderLayer로 변환

  1. 오디오 트랙 추가하는 단계로 넘어가겠다.
    1. RenderLayer를 AudioRenderLayer로 변환
      1. AudioRenderLayer는 RenderLayer를 포함하는 내부 프레임워크 객체로, 주로 RenderLayer의 오디오 트랙을 AVComposition에 추가하는 역할을 한다.
      2. AudioRenderLayer로 변환할 수 있는 RenderLayer는 하나의 조건만 충족하면 된다.
      3. Source에 오디오 트랙이 포함되어 있어야한다.
    2. AudioRenderLayerGroup로 변환
      1. AudioRenderLayerGroup은 RenderLayerGroup을 포함하는 내부 프레임 객체로
      2. 변환가능한 RenderLayerGroup은 하나의 조건만 충족하면 된다.
      3. 포함된 RenderLayer 그룹 중 하나가 AudioRenderLayer로 변환가능해야한다.
  2. AudioRenderLayer로 변환한 후의 결과는 다음과 같다.

2단계 - AVComposition에 AudioRenderLayer 오디오 트랙 추가

  1. RenderLayer의 Source에 오디오 트랙이 포함된 AudioRenderLayer의 경우, Source에서 오디오 AVAssetTrack을 가져와 AVComposition에 추가합니다.
  2. 한 번 추가되면 AVComposition의 오디오 트랙은 다음과 같이 나타난다.

 

  1. 그림에서 볼 수 있듯이 비디오 트랙의 재사용과는 달리 각 AudioRenderLayer는 하나의 오디오 트랙에 대응됩니다.
  2. 이는 하나의 AVAudioMixInputParameters가 하나의 오디오 트랙에 대응하며, 그 피치 설정(audioTimePitchAlgorithm)이 전체 오디오 트랙에 영향을 미침을 의미한다.
  3. 재사용하면 하나의 오디오 트랙에 여러 AudioRenderLayer가 생성될 수 있으며, 모든 AudioRenderLayer를 동일한 피치로 구성해야하므로 합리적이지 않습니다.

 

 

AVVideoCompostion

  1. AVVideoComposition
    1. 이전 AVFoundation 소개에서 알 수 있듯이. AVVideoCompostion을 사용하여 렌더 크기, 렌더 스케일링, 그리고 프레임 속도를  지정할 수 있습니다. 
    2. 또한, 블렌딩 매개변수를 저장하는 Instruction 세트가 있다.
    3. 이러한 블렌딩 매개변수를 사용하여 AVVideoComposition은 사용자 정의 Compositor로 해당 이미지 프레임을 혼합할 수 있다.
    4. 이 섹션에서는 이러한 Instuction 세트를 생성하고 AVVideoComposition을 만드는 방법에 중점을 둘 것입니다.
    5. 앞 섹션에서는 생성한 VideoRenderLayer를 사용하여 이 Instruction 세트를 생성합니다.
    6. 다음은 간단한 예제로 이 프로세스를 설명하겠습니다. 
    7. 아래 그림에서 볼 수 있듯이, 이 AVComposition에는 VideoRenderLayer1, VideoRenderLayer2, VideoRenderLayer3d이 있습니다. 
    8. 변환 프로세스는 다음과 같은 단계로 이루어집니다.
      1. 각 VideoRenderLayer의 타임라인 상의 시작 및 종료 시간 지점을 기록합니다.(아래의 T1-T6)
      2. 각 시간 간격에 대한 Instuction을 생성하고, 해당 시간 간격과 교차하는 모든 VideoRenderLayer를 Instruction의 블렌딩 매개변수로 사용합니다.(아래의 Instruction1-Instruction5)

 

 

  1. 그런 다음 AVVideoComposition을 생성하고 프레임 속도, 렌더 크기, Insruction 세트 및 사용자 정의 Compositor를 설정합니다.
  2. 아래는 코드 입니다.
let videoComposition = AVMutableVideoComposition()
videoComposition.frameDuration = renderComposition.frameDuration
videoComposition.renderSize = renderComposition.renderSize
videoComposition.instructions = instructions
videoComposition.customVideoCompositorClass = VideoCompositor.self

 

  1. 지금까지 렌더링에 필요한 Instruction 세트와 블렌딩 매개변수를 갖추었고, 계속해서 Compositor에서 이를 사용하여 프레임을 그리는 방법에 대해 알아보겠습니다.
  2. Instruction과 교차하는 VideoRenderLayer 그룹에 대한 블렌딩 매개 변수를 업데이트하여 이전의 Compositor 워크 플로우를 업데이트 합니다.

 

  1. 예제를 통해 비디오 블렌딩 규칙을 설명하겠습니다.
  2. 아래 그림에서 보듯이, 우리는 이러한 VideoRenderLayer 프레임들을 T1 시점에서 블렌딩하고자 합니다.

 

 

  1. 우리의 렌더링 블렌딩 규칙은 다음과 같다.
    1. RenderLayer가 포함하는 VideoRenderLayer 그룹을 RenderLayer의 leyerLevel에 따라 정렬합니다. 위에 보이는 것처럼
    2. VideoRenderLayer 그룹을 반복하며 다음 세가지 블렌딩에 대해 VideoRenderLayer에 적용합니다.
      1. 현재 VideoRenderLayer는 VideoRenderLayerGroup이며, 이는 사전 합성된 방식입니다.
      2. 자체 내부의 VideoRenderLayer 그룹을 반복한 후에 텍스처를 생성하고 이전 텍스처에 블렌딩합니다.
      3. 현재 VideoRenderLayer의 Source에 비디오 트랙이 포함되어 있거나 Source가 이미지 유형인 경우, 자체의 효과연산 그룹(Operations)을 처리하기 위해 해당 텍스처를 가져온 후 이전 텍스처에 블렌딩합니다.
      4. 현재 VideoRenderLayer에는 효과 연산이 그룹만 있으며, 모든 작업이 이전에 블렌딩된 텍스처에 적용됩니다.
    3. 렌더링 블렌딩 규칙 요약
      1. 레이어 별로 bottom-up으로 렌더링합니다.
      2. 현재 레이어에 텍스쳐가 있다면 먼저 자체 텍스처를 처리한 다음 이전 텍스처에 블렌딩합니다.
      3. 현재 레벨에서 텍스처가 없으면 작업이 직접 이전 텍스처에 적용됩니다.
    4. 이러한 규칙을 위의 예제에 적용해보겠습니다. 최종 출력 텍스처를 Output Texture로 가정합니다. 
      1. bottom VideoRenderLayerGroup를 처리하여 Texture1을 생성하고, Texture1을 Output Texture에 블렌딩합니다
      2. VideoRenderLayer2를 처리하여 Texture2를 생성하고, Texture2를 Output Texture에 블렌딩합니다.
      3. VideoRenderLayer3를 처리하여 Texture3을 생성하고, Texture3을 Output Texture에 블렌딩합니다.
      4. VideoRenderLayer4의 효과 연산 그룹을 처리하고, 이것을 Output Texture에 적용합니다.