我正在使用Xamarin.iOS裁剪从移动摄像头拍摄的视频。我已经成功实现了下面的代码,它正在完美地用于风景视频,但是在裁剪了肖像视频之后,它返回了右侧的黑色区域。它。以下是修剪代码和结果图像。任何建议都会有所帮助,我们将不胜感激。
void CropVideo()
{
var cropWidth=(cropperView.CropRect.Width/cropperView.Frame.Width)*videoAsset.NaturalSize.Width;
var cropHeight=(cropperView.CropRect.Height/cropperView.Frame.Height)*videoAsset.NaturalSize.Height;
AVMutableComposition videoComposition = AVMutableComposition.Create();
AVMutableCompositionTrack compositionTrack = videoComposition.AddMutableTrack (AVMediaType.Video, 0);
AVAssetTrack clipVideoToTrack = videoAsset.TracksWithMediaType (AVMediaType.Video)[0];
AVMutableVideoComposition VideoComposition= AVMutableVideoComposition.Create();
VideoComposition.RenderSize = new CGSize (cropWidth,cropHeight);
VideoComposition.FrameDuration = new CMTime (1,videoAsset.Duration.TimeScale);
AVMutableVideoCompositionInstruction instruction = new AVMutableVideoCompositionInstruction ();
var timeRange = new CMTimeRange ();
timeRange.Start = new CMTime (0, videoAsset.Duration.TimeScale);
timeRange.Duration = new CMTime (videoAsset.Duration.Value,videoAsset.Duration.TimeScale);
instruction.TimeRange = timeRange;
AVMutableVideoCompositionLayerInstruction transform = AVMutableVideoCompositionLayerInstruction.FromAssetTrack (clipVideoToTrack);
var orientation = GetVideoOrientationFromAsset (clipVideoToTrack);
var cropY=(cropperView.CropRect.Y/cropperView.Frame.Height)*videoAsset.NaturalSize.Height;
var cropX=(cropperView.CropRect.X/cropperView.Frame.Width)*videoAsset.NaturalSize.Width;
var translationTransform = CGAffineTransform.MakeIdentity ();
var rotationTransform = CGAffineTransform.MakeIdentity ();
switch (orientation)
{
case UIImageOrientation.Up:
translationTransform=CGAffineTransform.MakeTranslation (videoAsset.NaturalSize.Height-cropX,0- cropY);
rotationTransform = CGAffineTransform.Rotate (translationTransform,(nfloat)Math.PI/2);
break;
case UIImageOrientation.Down:
translationTransform=CGAffineTransform.MakeTranslation (0-cropX,videoAsset.NaturalSize.Width- cropY);
rotationTransform = CGAffineTransform.Rotate (translationTransform,(nfloat)(-Math.PI/2));
break;
case UIImageOrientation.Right:
translationTransform=CGAffineTransform.MakeTranslation (0-cropX,0- cropY);
rotationTransform = CGAffineTransform.Rotate (translationTransform,(nfloat)0);
break;
case UIImageOrientation.Left:
translationTransform=CGAffineTransform.MakeTranslation (videoAsset.NaturalSize.Width-cropX,videoAsset.NaturalSize.Height- cropY);
rotationTransform = CGAffineTransform.Rotate (translationTransform,(nfloat)Math.PI);
break;
}
transform.SetTransform (rotationTransform, new CMTime (0, videoAsset.Duration.TimeScale));
instruction.LayerInstructions = new AVVideoCompositionLayerInstruction[]{ transform};
VideoComposition.Instructions = new AVVideoCompositionInstruction[]{ instruction};
var compatiblePresets= AVAssetExportSession.ExportPresetsCompatibleWithAsset(videoAsset).ToList();
var preset="";
if(compatiblePresets.Contains("AVAssetExportPresetLowQuality"))
{
preset="AVAssetExportPresetLowQuality";
}
else
{
preset=compatiblePresets.FirstOrDefault();
}
AVAssetExportSession export= new AVAssetExportSession(videoAsset,preset);
export.VideoComposition = VideoComposition;
int SystemVersion = Convert.ToInt16(UIDevice.CurrentDevice.SystemVersion.Split('.')[0]);
string filename;
if (SystemVersion >= 8)
{
var documents = NSFileManager.DefaultManager.GetUrls(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User)[0].Path;
filename = Path.Combine(documents, "cropped.mov");
}
else
{
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // iOS 7 and earlier
filename = Path.Combine(documents, "cropped.mov");
}
var url = NSUrl.FromFilename (filename);
NSError error;
var manager =NSFileManager.DefaultManager;
manager.Remove(url,out error);
export.OutputUrl = url;
export.OutputFileType = AVFileType.QuickTimeMovie;
var bounds = UIScreen.MainScreen.Bounds; // portrait bounds
if (UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft || UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight) {
bounds.Size = new CGSize(bounds.Size.Height, bounds.Size.Width);
}
// show the loading overlay on the UI thread using the correct orientation sizing
var overlay = new LoadingOverlay (bounds,"Cropping Video");
this.View.Add ( overlay );
export.ExportAsynchronously (() => {
InvokeOnMainThread(()=>{
overlay.Hide();
});
if(export.Status==AVAssetExportSessionStatus.Completed)
{
ALAssetsLibrary library = new ALAssetsLibrary();
library.WriteVideoToSavedPhotosAlbumAsync(url);
page.VideoCroppped(filename);
}
else
{
InvokeOnMainThread(()=>{
new UIAlertView("Not Awesome",export.Error.Description,null,"O K").Show();
});
}
});
}
UIImageOrientation GetVideoOrientationFromAsset (AVAssetTrack videoTrack)
{
CGSize size = videoTrack.NaturalSize;
CGAffineTransform txf = videoTrack.PreferredTransform;
if (size.Width == txf.x0 && size.Height == txf.y0)
return UIImageOrientation.Left; //return UIInterfaceOrientationLandscapeLeft;
else if (txf.x0 == 0 && txf.y0 == 0)
return UIImageOrientation.Right; //return UIInterfaceOrientationLandscapeRight;
else if (txf.x0 == 0 && txf.y0 == size.Width)
return UIImageOrientation.Down; //return UIInterfaceOrientationPortraitUpsideDown;
else
return UIImageOrientation.Up; //return UIInterfaceOrientationPortrait;
}