2

I am already including a CATextLayer in an existing video on an iPhone and save it into another mp4 file (as suggested here: How can I add a watermark in a captured video on iOS).

AVAsset videoAsset = AVAsset.FromUrl(NSUrl.CreateFileUrl(urlpath, false, null));
AVMutableComposition mixComposition = AVMutableComposition.Create();
AVMutableCompositionTrack compositionVideoTrack = mixComposition.AddMutableTrack(AVMediaType.Video, 0);
AVAssetTrack clipVideoTrack = videoAsset.TracksWithMediaType(AVMediaType.Video).First();

CMTimeRange timeRange = new CMTimeRange(){
    Start = CMTime.Zero,
    Duration = videoAsset.Duration
};

NSError error;
compositionVideoTrack.InsertTimeRange(timeRange, clipVideoTrack, CMTime.Zero, out error);
compositionVideoTrack.PreferredTransform = videoAsset.TracksWithMediaType(AVMediaType.Video).First().PreferredTransform;


// Create overlay layer
CGSize naturalSize = videoAsset.NaturalSize;

CATextLayer overLayer = new CATextLayer(){
    Frame = new CGRect(new CGPoint(0, 0), naturalSize),
    String = "text layer on my video",
    ForegroundColor = UIColor.White.CGColor
};

// Sort the layers
CALayer parentLayer = new CALayer() {
    Frame = new CGRect(new CGPoint(0, 0), naturalSize)
};
CALayer videoLayer = new CALayer(){
    Frame = new CGRect(new CGPoint(0,0), naturalSize)
};

parentLayer.AddSublayer(videoLayer);
parentLayer.AddSublayer(overLayer);

// Create composition
AVMutableVideoComposition videoComposition = AVMutableVideoComposition.Create();
videoComposition.RenderSize = naturalSize;
videoComposition.FrameDuration = new CMTime(1, 30);
videoComposition.AnimationTool = AVVideoCompositionCoreAnimationTool.FromLayer(videoLayer, parentLayer);

// Instruction
AVMutableVideoCompositionInstruction instruction = new AVMutableVideoCompositionInstruction();

CMTimeRange timeRangeMixComposition = new CMTimeRange(){
    Start = CMTime.Zero,
    Duration = mixComposition.Duration
};

instruction.TimeRange = timeRangeMixComposition;
AVAssetTrack videoTrack = mixComposition.TracksWithMediaType(AVMediaType.Video).First();
AVMutableVideoCompositionLayerInstruction layerInstruction = AVMutableVideoCompositionLayerInstruction.FromAssetTrack(videoTrack);
instruction.LayerInstructions = new AVVideoCompositionLayerInstruction[] {layerInstruction};
videoComposition.Instructions = new AVVideoCompositionInstruction[] {instruction};

// Export
AVAssetExportSession exporterSession = new AVAssetExportSession(mixComposition, AVAssetExportSession.PresetHighestQuality){
    OutputUrl = m_outputUrl,
    OutputFileType = AVFileType.QuickTimeMovie,
    ShouldOptimizeForNetworkUse = true,
    VideoComposition = videoComposition
};

exporterSession.ExportAsynchronously((() => {
    if (exporterSession.Status == AVAssetExportSessionStatus.Completed){
        NSUrl outputUrl = exporterSession.OutputUrl;
        ALAssetsLibrary library = new ALAssetsLibrary();
        if (library.VideoAtPathIsIsCompatibleWithSavedPhotosAlbum(outputUrl)){
            library.WriteVideoToSavedPhotosAlbumAsync(outputUrl);
        }
    })
    );
}

This creates another video file with my text visible on the video for its entire duration. However, I need to change the String property of the overLayer several times per second.

overLayer.String

should show the current playback time.


I looked into several different options but could not achieve to change the text in the middle of the video:

  • I tried adding different instructions but did not find a way to connect the instruction directly with my layer (it is linked to the whole composition)
  • I looked into CATransaction: this allowed me to change the String property but it simply overwrote the initial value

    CATransaction.Begin();
    CATransaction.AnimationDuration = 2;
    overLayer.String = "Changed string on my video";
    CATransaction.AnimationTimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
    CATransaction.Commit();
    
  • I tried to register my custom Selector directly to overLayer but could not get that running either.

I would appreciate any help, Objective-C or Swift solutions would help as well.

EDIT: The code above is in C# - Xamarin.iOS

Community
  • 1
  • 1
Barbara
  • 21
  • 3
  • This doesn't look like swift or objective-c code. Are you just asking how to code this is swift or objective-c? – Asdrubal Jul 26 '16 at 13:18
  • No, sorry this is c# (Xamarin.IOS) code. Would it help if I would translate it to Swift? – Barbara Jul 26 '16 at 14:27
  • Just to clarify: I wonder how to solve the problem of dynamically changing the text on the overlay depending on playback time. I dont mind having solution in either Swift, objective-C or C#. If it helps, I am happy to translate the code above to Swift... – Barbara Jul 26 '16 at 14:38

0 Answers0