iOS - 带有透明视频的水印视频

时间:2016-08-29 17:34:01

标签: ios video avfoundation avmutablecomposition

我正在使用AVFoundation为视频添加水印,并使用另一个具有透明度的视频。我已设法使用以下代码将一个视频叠加在另一个视频之上,但只要我开始使用具有透明度的资产,导出就会失败而没有任何有用的错误。

This link谈到PreRes 4444是AVFoundation在alpha通道方面唯一支持的编解码器,但我找不到任何官方文档。我目前尝试添加为叠加层的文件是H.264编码的mp4,在阅读Learning AVFoundation之后,它似乎是最佳选择,其中声明

  

ProRes编解码器仅在OS X上可用。如果您正在开发   仅适用于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 个答案:

答案 0 :(得分:1)

我是通过做一个这样做的   1. H264内的自定义透明格式和一个
  2.自定义透明度格式的自定义(perforce)合成器

自定义格式是一个“高”视频,每个颜色框架都在黑色和白色蒙版的正上方。

合成器从水印中获取帧并将文件加水印,组合它们,并将结果写入第3个文件。 每帧的每个像素被解释为YUV值,一个用作颜色,另一个用作遮罩,并与背景帧组合。

为了加快速度,合成器是OpenGL像素着色器+ TextureCaches,虽然今天你使用的是MetalCVMetalTextureCache