尝试使用AVFoundation为视频上的图像添加水印

时间:2017-06-16 10:21:39

标签: ios objective-c avfoundation

我拍了一张png图像和一个水印视频,两者都是肖像。我已经把它作为水印成像了一个视频图像。

水印后,在横向模式下获得合并视频,并在反时钟方向上翻转90度。 我无法找到视频从纵向模式转换为横向模式的确切原因。而图像显示拉伸肖像。 请帮忙。提前谢谢。

在代码下面使用: -

- (void)addWatermarkAtVideoFile:(NSURL *)videoURL image:(UIImage *)image withConvertedVideoUUID:(NSString *)convertedVideoUUID response:(void(^)(BOOL success, NSString *videoUUID, NSURL *videoPath))responseBlock {

    AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:videoURL options:nil];
    AVMutableComposition* mixComposition = [AVMutableComposition composition];


    AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    if(clipVideoTrack) {
        AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
        [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:clipVideoTrack atTime:kCMTimeZero error:nil];
        [compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] preferredTransform]];
    }

    AVAssetTrack *clipAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    if(clipAudioTrack) {
        AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
        [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
    }

    CGSize sizeOfVideo=[videoAsset naturalSize];

    //Image of watermark
    UIImage *myImage = image;
    CALayer *layerCa = [CALayer layer];
    layerCa.contents = (id)myImage.CGImage;
    layerCa.frame = CGRectMake(0, 0, sizeOfVideo.width, sizeOfVideo.height);
    layerCa.opacity = 1.0;

    CALayer *parentLayer=[CALayer layer];
    CALayer *videoLayer=[CALayer layer];
    parentLayer.frame=CGRectMake(0, 0, sizeOfVideo.width, sizeOfVideo.height);
    videoLayer.frame=CGRectMake(0, 0, sizeOfVideo.width, sizeOfVideo.height);
    [parentLayer addSublayer:videoLayer];
    [parentLayer addSublayer:layerCa];

    AVMutableVideoComposition *videoComposition=[AVMutableVideoComposition videoComposition] ;
    videoComposition.frameDuration=CMTimeMake(1, 30);
    videoComposition.renderSize=sizeOfVideo;
    videoComposition.animationTool=[AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [mixComposition duration]);
    AVAssetTrack *videoTrack = [[mixComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    AVMutableVideoCompositionLayerInstruction* layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
    instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
    videoComposition.instructions = [NSArray arrayWithObject: instruction];

    //Creating temp path to save the converted video
    NSString* myDocumentPath = [self getDocumentDirectoryPathWithFileName:convertedVideoUUID];
    NSURL *outputFileURL = [[NSURL alloc] initFileURLWithPath:myDocumentPath];

    //Check if the file already exists then remove the previous file
    [self removeFileIfExistAtPAth:myDocumentPath];

    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
    exportSession.videoComposition=videoComposition;

    exportSession.outputURL = outputFileURL;
    exportSession.outputFileType = AVFileTypeQuickTimeMovie;
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        switch (exportSession.status)
        {
            case AVAssetExportSessionStatusCompleted:

                NSLog(@"Export OK");
                [self saveInPhotoAlbum:myDocumentPath];

                break;
            case AVAssetExportSessionStatusFailed:
                NSLog (@"AVAssetExportSessionStatusFailed: %@", exportSession.error);
                break;
            case AVAssetExportSessionStatusCancelled:
                NSLog(@"Export Cancelled");
                break;
        }

        BOOL statusSuccess = [exportSession status] == AVAssetExportSessionStatusCompleted;
        responseBlock(statusSuccess ? YES : NO, statusSuccess ? convertedVideoUUID : nil, statusSuccess ? outputFileURL : nil);
    }];
}

2 个答案:

答案 0 :(得分:0)

我认为它是AVFoundation的默认行为,它可能与水印功能无关。

您可以使用CGAffineTransform:

if(height > width) {
    CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(M_PI_2);
    [layerInstruction setTransform:rotationTransform atTime:kCMTimeZero];
}

答案 1 :(得分:0)

AVAsset的naturalSize并不考虑视频的最终轮播。
如果要正确放置游览水印,请考虑使用renderSize的{​​{1}}或应用某些转换。 此代码段为您提供资产的实际方向:

AVMutableVideoComposition

使用这个,你可以考虑旋转来获得实际尺寸。

    func orientationForAsset(_ asset: AVAsset) -> (orientation: UIImageOrientation, isPortrait: Bool) {
        let videoTrack = asset.tracks(withMediaType: AVMediaTypeVideo).first!
        let transformMatrix = videoTrack.preferredTransform
        return orientationFromTransform(transformMatrix)
    }

    func orientationFromTransform(_ transform: CGAffineTransform) -> (orientation: UIImageOrientation, isPortrait: Bool) {
        var assetOrientation = UIImageOrientation.up
        var isPortrait = false
        if transform.a == 0 && transform.b == 1.0 && transform.c == -1.0 && transform.d == 0 {
            assetOrientation = .right
            isPortrait = true
        } else if transform.a == 0 && transform.b == -1.0 && transform.c == 1.0 && transform.d == 0 {
            assetOrientation = .left
            isPortrait = true
        } else if transform.a == 1.0 && transform.b == 0 && transform.c == 0 && transform.d == 1.0 {
            assetOrientation = .up
        } else if transform.a == -1.0 && transform.b == 0 && transform.c == 0 && transform.d == -1.0 {
            assetOrientation = .down
        }
        return (assetOrientation, isPortrait)
    }