Flip the video recorded with front facing camera along horizontal axis in IOS

4.8k views Asked by At

I am trying to un-mirror the mirror effect created by iPhone’s front facing camera while recording video. Basically, I want to flip the video captured by front facing camera along the horizontal axis, so that the final edited video doesn’t not have the mirror effect like the inbuilt camera app does. I am using AVCaptureSession for recording videos.

// 3.1 - Create AVMutableVideoCompositionInstruction
    AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, self.videoAsset.duration);

// 3.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation.
AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
AVAssetTrack *videoAssetTrack = [[self.videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

UIImageOrientation videoAssetOrientation_  = UIImageOrientationUp;
BOOL isVideoAssetPortrait_  = NO;
CGAffineTransform videoTransform = videoAssetTrack.preferredTransform;
if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0)
{
    videoAssetOrientation_ = UIImageOrientationRight;
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0)
{
    videoAssetOrientation_ =  UIImageOrientationLeft;
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0)
{
    videoAssetOrientation_ =  UIImageOrientationUp;
}
if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0)
{
    videoAssetOrientation_ = UIImageOrientationDown;
}

//*********below are the transforms I am applying in which you might be interested in**********

CGAffineTransform t = CGAffineTransformMakeTranslation(videoAssetTrack.naturalSize.height, 0.0);
t = CGAffineTransformMakeRotation(degreesToRadians(90.0));
t = CGAffineTransformMakeScale(-1, 1);  //this line is where I am having problem

[videolayerInstruction setTransform:t atTime:kCMTimeZero];
[videolayerInstruction setOpacity:1.0 atTime:self.videoAsset.duration];


// 3.3 - Add instructions
mainInstruction.layerInstructions = [NSArray arrayWithObjects:videolayerInstruction,nil];

AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];


CGSize naturalSize;
if(isVideoAssetPortrait_)
{
    naturalSize = CGSizeMake(videoAssetTrack.naturalSize.height, videoAssetTrack.naturalSize.width);
}
else
{
    naturalSize = videoAssetTrack.naturalSize;
}

float renderWidth, renderHeight;
renderWidth = naturalSize.width;
renderHeight = naturalSize.height;
mainCompositionInst.renderSize = CGSizeMake(renderWidth, renderHeight);
mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
mainCompositionInst.frameDuration = CMTimeMake(1, 30);

In the above code when I remove the scaling transform t = CGAffineTransformMakeScale(-1, 1);

I get video frames with proper orientation but they are not flipped. When I apply the scaling transform I get blank video frames. Currently, I am doing this only for portrait mode videos.

If anyone has any knowledge regarding this please share. Thank you in advance.

4

There are 4 answers

1
gvuksic On BEST ANSWER

You made a small mistake with affine transformations.

Replace the code:

CGAffineTransform t = CGAffineTransformMakeTranslation(videoAssetTrack.naturalSize.height, 0.0);
t = CGAffineTransformMakeRotation(degreesToRadians(90.0));
t = CGAffineTransformMakeScale(-1, 1);  //this line is where I am having problem

With corrected code:

CGAffineTransform t = CGAffineTransformMakeScale(-1.0f, 1.0f);
t = CGAffineTransformTranslate(t, -videoAssetTrack.naturalSize.width, 0);
t = CGAffineTransformRotate(t, (degreesToRadians(90.0)));
t = CGAffineTransformTranslate(t, 0.0f, -videoAssetTrack.naturalSize.width);
1
Yalcin Ozdemir On

Swift 3 version

        let instruction = AVMutableVideoCompositionInstruction()
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30))
    var transform:CGAffineTransform = CGAffineTransform(scaleX: -1.0, y: 1.0)
    transform = transform.translatedBy(x: -clipVideoTrack.naturalSize.width, y: 0.0)
    transform = transform.rotated(by: CGFloat(Double.pi/2))
    transform = transform.translatedBy(x: 0.0, y: -clipVideoTrack.naturalSize.width)
0
Girish On
var size = videotrackatfirst.naturalSize
var transform = videotrackatfirst.preferredTransform

if (size.width == transform.tx && size.height == transform.ty) {          
                println("UIInterfaceOrientationLandscapeRight")
                var invert = CGAffineTransformInvert(videotrackatfirst.preferredTransform)
                layerInstruction.setTransform(invert, atTime: insertTime)
    }
0
Speedy99 On

In Swift (2.0)

    var transform:CGAffineTransform = CGAffineTransformMakeScale(-1.0, 1.0)
    transform = CGAffineTransformTranslate(transform, -videoInput.naturalSize.width, 0.0)
    transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
    transform = CGAffineTransformTranslate(transform, 0.0, -videoInput.naturalSize.width)
    videoInput.transform = transform