Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Adding a watermark is quite more simple. You just need to use a CALayer and AVVideoCompositionCoreAnimationTool. The code can be just copied and assembled in the same order. I have just tried to insert some comments in between for better understanding.</p> <p>Let's assume you recorded the video already so we are going to create the AVURLAsset first:</p> <pre><code>AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:outputFileURL options:nil]; AVMutableComposition* mixComposition = [AVMutableComposition composition]; AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:clipVideoTrack atTime:kCMTimeZero error:nil]; [compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] preferredTransform]]; </code></pre> <p>With just this code you would be able to export the video but we want to add the layer with the watermark first. Please note that some code may seem redundant but it is necessary for everything to work. </p> <p>First we create the layer with the watermark image:</p> <pre><code>UIImage *myImage = [UIImage imageNamed:@"icon.png"]; CALayer *aLayer = [CALayer layer]; aLayer.contents = (id)myImage.CGImage; aLayer.frame = CGRectMake(5, 25, 57, 57); //Needed for proper display. We are using the app icon (57x57). If you use 0,0 you will not see it aLayer.opacity = 0.65; //Feel free to alter the alpha here </code></pre> <p>If we don't want an image and want text instead:</p> <pre><code>CATextLayer *titleLayer = [CATextLayer layer]; titleLayer.string = @"Text goes here"; titleLayer.font = @"Helvetica"; titleLayer.fontSize = videoSize.height / 6; //?? titleLayer.shadowOpacity = 0.5; titleLayer.alignmentMode = kCAAlignmentCenter; titleLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height / 6); //You may need to adjust this for proper display </code></pre> <p>The following code sorts the layer in proper order:</p> <pre><code>CGSize videoSize = [videoAsset naturalSize]; CALayer *parentLayer = [CALayer layer]; CALayer *videoLayer = [CALayer layer]; parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height); videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height); [parentLayer addSublayer:videoLayer]; [parentLayer addSublayer:aLayer]; [parentLayer addSublayer:titleLayer]; //ONLY IF WE ADDED TEXT </code></pre> <p>Now we are creating the composition and add the instructions to insert the layer:</p> <pre><code>AVMutableVideoComposition* videoComp = [[AVMutableVideoComposition videoComposition] retain]; videoComp.renderSize = videoSize; videoComp.frameDuration = CMTimeMake(1, 30); videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; /// instruction 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]; videoComp.instructions = [NSArray arrayWithObject: instruction]; </code></pre> <p>And now we are ready to export:</p> <pre><code>_assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];//AVAssetExportPresetPassthrough _assetExport.videoComposition = videoComp; NSString* videoName = @"mynewwatermarkedvideo.mov"; NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName]; NSURL *exportUrl = [NSURL fileURLWithPath:exportPath]; if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) { [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil]; } _assetExport.outputFileType = AVFileTypeQuickTimeMovie; _assetExport.outputURL = exportUrl; _assetExport.shouldOptimizeForNetworkUse = YES; [strRecordedFilename setString: exportPath]; [_assetExport exportAsynchronouslyWithCompletionHandler: ^(void ) { [_assetExport release]; //YOUR FINALIZATION CODE HERE } ]; [audioAsset release]; [videoAsset release]; </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload