0

내가 mp4 비디오에 추가하는 오버레이 이미지에 적용하려는 애니메이션과 관련하여 도움이 필요합니다. 비디오에 오버레이를 추가하려면 여기에서 Ray Wenderlich 자습서 (https://www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos)를 따랐습니다. 해당 링크가 끝나면 오버레이에서 애니메이션이 만들어집니다.Xamarin.ios에서 AVAssetExportSession을 사용할 때 어떻게 CALayer에 애니메이션을 추가 할 수 있습니까?

Ray Wenderlich는 C#으로 코딩하지 않지만 Xamarin을 사용하여 내 응용 프로그램을 만든 이후로 사용합니다. 애니메이션을 사용하면 오버레이가 비디오 초반부에 사라집니다. 그러나 아무 일도 일어나지 않습니다. 동영상을 제외하고는 애니메이션이 적용되지 않습니다. 오버레이는 동영상 상단에 잘 표시되지만 사라지지 않습니다.

내가 애니메이션과 CALayer에 대해 읽은 대부분의 게시물은 UIView 내에서 애니메이션을 만듭니다.

나는 스스로에게 묻습니다. 애니메이션을 사용하고 있지 않기 때문에 C#을 사용했거나 잘못된 것을 작성 했습니까?

누군가 제발 도와 줄 수 있습니까?

public static void addFadeOverlayAtTheBeginning (NSUrl source, String overlay, long secondsToFade, NSUrl destination) 
    { 


     AVUrlAsset videoAsset = new AVUrlAsset(source); 

     if (secondsToFade > videoAsset.Duration.Seconds) 
      secondsToFade = (long)videoAsset.Duration.Seconds; 

     CALayer overlayLayer = CALayer.Create(); 
     UIImage image = new UIImage(overlay); 
     image.CreateResizableImage(new UIEdgeInsets(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height)); 
     overlayLayer.Contents = image.CGImage; 
     overlayLayer.Frame = new CGRect(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height); 
     overlayLayer.MasksToBounds = true; 

     CABasicAnimation animation = CABasicAnimation.FromKeyPath(@"opacity"); 
     animation.BeginTime = 0; // GetSeconds(image.CGImage.StartTime); 
     animation.Duration = secondsToFade; 
     animation.SetFrom (NSNumber.FromFloat (1)); 
     animation.SetTo (NSNumber.FromFloat(0)); 

     overlayLayer.AddAnimation(animation, @"opacity"); 

     AVMutableComposition videoComposition = AVMutableComposition.Create(); 

     AVMutableCompositionTrack track = videoComposition.AddMutableTrack(AVMediaType.Video, 0); 
     AVAssetTrack sourceVideoTrack = videoAsset.TracksWithMediaType(AVMediaType.Video)[0]; 

     CMTimeRange timeRangeInAsset = new CMTimeRange(); 
     timeRangeInAsset.Start = CMTime.Zero; 
     timeRangeInAsset.Duration = videoAsset.Duration; 
     NSError videoInsertError = null; 
     track.InsertTimeRange(timeRangeInAsset, sourceVideoTrack, CMTime.Zero, out videoInsertError); 
     track.PreferredTransform = sourceVideoTrack.PreferredTransform; 

     CALayer parentLayer = CALayer.Create(); 
     CALayer videoLayer = CALayer.Create(); 
     parentLayer.Frame = new CGRect(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height); 
     videoLayer.Frame = new CGRect(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height); 

     parentLayer.AddSublayer(videoLayer); 
     parentLayer.AddSublayer(overlayLayer); 

     //parentLayer.AddAnimation(animation, "opacity"); 

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

     AVMutableVideoCompositionInstruction instruction = AVMutableVideoCompositionInstruction.Create() as AVMutableVideoCompositionInstruction; 
     CMTimeRange timeRangeInstruction = new CMTimeRange(); 
     timeRangeInstruction.Start = CMTime.Zero; 
     timeRangeInstruction.Duration = videoComposition.Duration; 
     instruction.TimeRange = timeRangeInstruction; 


     AVMutableVideoCompositionLayerInstruction layerInstruction = AVMutableVideoCompositionLayerInstruction.FromAssetTrack(track); 
     CMTimeRange timeRangeFading = new CMTimeRange(); 
     timeRangeFading.Start = CMTime.Zero; 
     timeRangeFading.Duration = new CMTime(secondsToFade, 1); 
     //layerInstruction.SetOpacityRamp(1, 0, timeRangeFading); 
     instruction.LayerInstructions = new AVVideoCompositionLayerInstruction[] { layerInstruction }; 
     List<AVVideoCompositionInstruction> instructions = new List<AVVideoCompositionInstruction>(); 
     instructions.Add(instruction); 
     animationComposition.Instructions = instructions.ToArray(); 

     if (File.Exists(destination.Path)) 
      File.Delete(destination.Path); 

     AVAssetExportSession exporter = new AVAssetExportSession(videoComposition, AVAssetExportSession.PresetHighestQuality); 
     exporter.OutputUrl = destination; 
     exporter.VideoComposition = animationComposition; 
     exporter.OutputFileType = AVFileType.Mpeg4; 

     exporter.ExportAsynchronously(() => { 
      VideoManagement.state ++; 
      AVAssetExportSessionStatus status = exporter.Status; 
      Console.WriteLine("addFadeOverlayAtTheBeginning Done. Status: " + status.ToString()); 
      switch (status) 
      { 
       case AVAssetExportSessionStatus.Completed: 
        Console.WriteLine("Sucessfully Completed"); 
        if (File.Exists(destination.Path)) 
        { 
         Console.WriteLine(String.Format("Saved to {0}", destination.Path)); 
        } 
        else 
         Console.WriteLine("Failed"); 
        break; 
       case AVAssetExportSessionStatus.Cancelled: 
        break; 
       case AVAssetExportSessionStatus.Exporting: 
        break; 
       case AVAssetExportSessionStatus.Failed: 
        Console.WriteLine("Task failed => {0}", exporter.Error); 
        Console.WriteLine(exporter.Error.Description); 
        break; 
       case AVAssetExportSessionStatus.Unknown: 
        break; 
       case AVAssetExportSessionStatus.Waiting: 
        break; 
       default: 
        break; 
      } 
     }); 

    } 

답변

0

OK :

이 내가 쓴 기능입니다. 그것을 발견. 분명히 animation.BeginTime = 0;은 지원되지 않습니다. 나는 그것을 0.01로 바꿨고 모든 것이 잘 작동한다.

double Epsilon = 0.01; 

     if (secondsToFade > videoAsset.Duration.Seconds - Epsilon) 
      secondsToFade = videoAsset.Duration.Seconds - Epsilon; 

     CALayer overlayLayer = CALayer.Create(); 
     UIImage image = new UIImage(overlay); 
     image.CreateResizableImage(new UIEdgeInsets(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height)); 
     overlayLayer.Contents = image.CGImage; 
     overlayLayer.Frame = new CGRect(0, 0, videoAsset.NaturalSize.Width, videoAsset.NaturalSize.Height); 
     overlayLayer.MasksToBounds = true; 

     //On crée l'animation pour le CAlayer 
     CABasicAnimation animation = CABasicAnimation.FromKeyPath(@"opacity"); 
     animation.BeginTime = Epsilon; 
     animation.Duration = secondsToFade; 
     animation.SetFrom (NSNumber.FromFloat (1)); 
     animation.SetTo (NSNumber.FromFloat(0)); 
     animation.FillMode = CAFillMode.Forwards; 
     animation.RemovedOnCompletion = false;