2016-08-29 1 views
2

투명도가있는 다른 비디오로 비디오를 워터 마크하려면 AVFoundation을 사용하고 있습니다. 다음 코드를 사용하여 하나의 비디오를 다른 비디오 위에 겹쳐 넣을 수 있었지만 투명도가있는 에셋을 사용하자마자 유용한 오류없이 내보내기가 실패합니다.iOS - 투명한 비디오가있는 워터 마크 비디오

This link 알파 채널에 관해서 AVFoundation이 지원하는 유일한 코덱 인 PreRes 4444가 있지만, 이에 대한 공식 문서는 찾을 수 없습니다. 나는 현재 오버레이로 추가하려고 파일은

ProRes를 코덱은 OS X에서 사용할 수있는 것을 말한다 곳, Learning AVFoundation을 읽은 후에 최선의 선택이 될 것 같은 H.264 인코딩 된 MP4입니다 iOS 전용으로 을 개발하는 경우 H264가 유일한 게임입니다.

비디오 오버레이 대신 항상 애니메이션 레이어를 추가 할 수는 있지만, 이에 대한 해결책이없는 경우에는 놀랄 것입니다.

- (void)addWatermarkToAsset:(NSURL *)assetURL completionHandler:(void (^)(NSURL *videoURL))handler 
{ 
    AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil]; 

    // This asset contains an alpha channel, and has a shorter duration than videoAsset 
    NSURL *animationUrl = [[NSBundle mainBundle] URLForResource:@"InstagramAnimation" withExtension:@"mp4"]; 
    AVURLAsset *animationAsset = [AVURLAsset URLAssetWithURL:animationUrl options:nil]; 

    AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init]; 
    AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo 
                     preferredTrackID:kCMPersistentTrackID_Invalid]; 
    [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) 
         ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] 
         atTime:kCMTimeZero error:nil]; 

    AVMutableCompositionTrack *animationTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo 
                      preferredTrackID:kCMPersistentTrackID_Invalid]; 

    [animationTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, animationAsset.duration) 
          ofTrack:[[animationAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] 
          atTime:kCMTimeZero error:nil]; 

    AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration); 

    AVMutableVideoCompositionLayerInstruction *videoLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack]; 
    CGAffineTransform scale = CGAffineTransformMakeScale(0.7f,0.7f); 
    CGAffineTransform move = CGAffineTransformMakeTranslation(230,230); 
    [videoLayerInstruction setTransform:CGAffineTransformConcat(scale, move) atTime:kCMTimeZero]; 

    AVMutableVideoCompositionLayerInstruction *animationLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:animationTrack]; 
    CGAffineTransform secondScale = CGAffineTransformMakeScale(1.2f,1.5f); 
    CGAffineTransform secondMove = CGAffineTransformMakeTranslation(0,0); 

    [animationLayerInstruction setTransform:CGAffineTransformConcat(secondScale, secondMove) atTime:kCMTimeZero]; 

    mainInstruction.layerInstructions = [NSArray arrayWithObjects:videoLayerInstruction, animationLayerInstruction, nil]; 

    AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition]; 
    mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction]; 
    mainCompositionInst.frameDuration = CMTimeMake(1, 30); 
    mainCompositionInst.renderSize = videoTrack.naturalSize; 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent: 
          [NSString stringWithFormat:@"FinalVideo-%d.mov",arc4random() % 1000]]; 
    NSURL *url = [NSURL fileURLWithPath:myPathDocs]; 

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition 
                     presetName:AVAssetExportPresetHighestQuality]; 
    exporter.outputURL = url; 
    exporter.outputFileType = AVFileTypeQuickTimeMovie; 
    exporter.shouldOptimizeForNetworkUse = YES; 
    exporter.videoComposition = mainCompositionInst; 
    [exporter exportAsynchronouslyWithCompletionHandler:^{ 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self exportDidFinish:exporter]; 
     }); 
    }]; 
} 

답변

1

나는 H264 내부
1. 사용자 정의 투명성 형식을 수행하여이 일을했습니다, 그리고 사용자 정의 투명성 형식의
2. 사용자 정의 (억지로) 컴포 지터는

사용자 정의 형식이었다 각 색상 프레임이 흑백 마스크 바로 위에있는 "키가 큰"비디오.

컴포 지터는 워터 마크와 워터 마크가있는 파일로부터 프레임을 가져 와서 구성하고 결과를 세 번째 파일에 기록했습니다. 각 프레임의 각 픽셀은 YUV 값으로 해석되고, 하나는 색상으로 사용되고 다른 하나는 마스크로 사용되며 배경 프레임과 결합됩니다.

작곡가는 OpenGL 픽셀 쉐이더 + TextureCaches 였지만 오늘은 MetalCVMetalTextureCache을 사용하고 있습니다.

+1

큰 감사입니다. OpenGL 쉐이더를 사용한 솔루션이 너무 많은 시간을 소비하는 것처럼 보였으므로 AfterEffects 애니메이션을 코드의 사용자 지정 애니메이션으로 변환하는 결과를 낳았습니다. 그러나 확실히 당신의 솔루션을 시험해 볼 것입니다. –