scourGINHO
scourGINHO

Reputation: 699

Record, save and/or convert video in mp4 format?

I have the following problem - I am trying to create an app that records video, then save it to the camera roll and after that I am uploading that video to the web. The problem is that the only supported format is "mp4", but my videos are "mov".

So my question is how to save video from camera in "mp4" format, or save it in "mov" and then convert it to "mp4".

Here's my code:

Thanks in advance!

Upvotes: 17

Views: 31246

Answers (4)

Amjad Khan
Amjad Khan

Reputation: 1317

Swift 5 code to convert video into mp4 in Swift

First you need to import this

import AVFoundation

then you can write this code and pass the URL into it.

func videoConvert(videoURL: URL)  {
    let avAsset = AVURLAsset(url: videoURL as URL, options: nil)
    let startDate = NSDate()
    //Create Export session

    let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)
    // exportSession = AVAssetExportSession(asset: composition, presetName: mp4Quality)

    //Creating temp path to save the converted video
    let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let myDocumentPath = NSURL(fileURLWithPath: documentsDirectory).appendingPathComponent("temp.mp4")?.absoluteString
    let url = NSURL(fileURLWithPath: myDocumentPath!)

    let documentsDirectory2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL
    let filePath = documentsDirectory2.appendingPathComponent("VideoConvert.mp4")
    deleteFile(filePath: filePath!)

    //Check if the file already exists then remove the previous file
    if FileManager.default.fileExists(atPath: myDocumentPath!) {
        do {
            try FileManager.default.removeItem(atPath: myDocumentPath!)
        }
        catch let error {
            print(error)
        }
    }
    //URL
    print(filePath!.absoluteString)
    exportSession!.outputURL = filePath
    exportSession!.outputFileType = AVFileType.mp4
    exportSession!.shouldOptimizeForNetworkUse = true
    let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
    let range = CMTimeRangeMake(start: start, duration: avAsset.duration)
    exportSession!.timeRange = range
    exportSession!.exportAsynchronously(completionHandler: {() -> Void in
        switch exportSession!.status {
            case .failed:
                print("%@",exportSession!.error ?? "Failed to get error")
            case .cancelled:
                print("Export canceled")
            case .completed:
                //Video conversion finished
                let endDate = NSDate()
                let time = endDate.timeIntervalSince(startDate as Date)
                print(time)
                print("Successful!")
                print(exportSession!.outputURL)
            default:
                break
        }
    })
}

For calling the function you can go with

videoConvert(videoURL: fileUrl!)

or

self.videoConvert(videoURL: fileUrl!)

then you will get the video converted and stored into the document directory with name VideoConvert.mp4

Thanks for the @Jigar Thakkar answer.

Upvotes: 1

Jigar Thakkar
Jigar Thakkar

Reputation: 7582

Here is the code to convert mov video into mp4 for swift

func encodeVideo(videoURL: NSURL)  {
let avAsset = AVURLAsset(URL: videoURL, options: nil)

var startDate = NSDate()

//Create Export session
exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)

// exportSession = AVAssetExportSession(asset: composition, presetName: mp4Quality)
//Creating temp path to save the converted video


let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let myDocumentPath = NSURL(fileURLWithPath: documentsDirectory).URLByAppendingPathComponent("temp.mp4").absoluteString
let url = NSURL(fileURLWithPath: myDocumentPath)

let documentsDirectory2 = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL

let filePath = documentsDirectory2.URLByAppendingPathComponent("rendered-Video.mp4")
deleteFile(filePath)

//Check if the file already exists then remove the previous file
if NSFileManager.defaultManager().fileExistsAtPath(myDocumentPath) {
    do {
        try NSFileManager.defaultManager().removeItemAtPath(myDocumentPath)
    }
    catch let error {
        print(error)
    }
}

 url

exportSession!.outputURL = filePath
exportSession!.outputFileType = AVFileTypeMPEG4
exportSession!.shouldOptimizeForNetworkUse = true
var start = CMTimeMakeWithSeconds(0.0, 0)
var range = CMTimeRangeMake(start, avAsset.duration)
exportSession.timeRange = range

exportSession!.exportAsynchronouslyWithCompletionHandler({() -> Void in
    switch self.exportSession!.status {
    case .Failed:
        print("%@",self.exportSession?.error)
    case .Cancelled:
        print("Export canceled")
    case .Completed:
        //Video conversion finished
        var endDate = NSDate()

        var time = endDate.timeIntervalSinceDate(startDate)
        print(time)
        print("Successful!")
        print(self.exportSession.outputURL)

    default:
        break
    }

})


}

func deleteFile(filePath:NSURL) {
guard NSFileManager.defaultManager().fileExistsAtPath(filePath.path!) else {
    return
}

do {
    try NSFileManager.defaultManager().removeItemAtPath(filePath.path!)
}catch{
    fatalError("Unable to delete file: \(error) : \(__FUNCTION__).")
}
}

Swift 3

func encodeVideo(_ videoURL: URL)  {

    let avAsset = AVURLAsset(url: videoURL, options: nil)

    let startDate = Foundation.Date()

    //Create Export session
    exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)

    // exportSession = AVAssetExportSession(asset: composition, presetName: mp4Quality)
    //Creating temp path to save the converted video


    let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let myDocumentPath = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("temp.mp4").absoluteString
    let url = URL(fileURLWithPath: myDocumentPath)

    let documentsDirectory2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL

    let filePath = documentsDirectory2.appendingPathComponent("rendered-Video.mp4")
    deleteFile(filePath)

    //Check if the file already exists then remove the previous file
    if FileManager.default.fileExists(atPath: myDocumentPath) {
        do {
            try FileManager.default.removeItem(atPath: myDocumentPath)
        }
        catch let error {
            print(error)
        }
    }



    exportSession!.outputURL = filePath
    exportSession!.outputFileType = AVFileTypeMPEG4
    exportSession!.shouldOptimizeForNetworkUse = true
    let start = CMTimeMakeWithSeconds(0.0, 0)
    let range = CMTimeRangeMake(start, avAsset.duration)
    exportSession.timeRange = range

    exportSession!.exportAsynchronously(completionHandler: {() -> Void in
        switch self.exportSession!.status {
        case .failed:
            print("%@",self.exportSession?.error)
        case .cancelled:
            print("Export canceled")
        case .completed:
            //Video conversion finished
            let endDate = Foundation.Date()

            let time = endDate.timeIntervalSince(startDate)
            print(time)
            print("Successful!")
            print(self.exportSession.outputURL)
            self.mediaPath = self.exportSession.outputURL?.path as NSString!
            //self.mediaPath = String(self.exportSession.outputURL!)
        // self.mediaPath = self.mediaPath.substringFromIndex(7)
        default:
            break
        }

    })


}

func deleteFile(_ filePath:URL) {
    guard FileManager.default.fileExists(atPath: filePath.path) else {
        return
    }

    do {
        try FileManager.default.removeItem(atPath: filePath.path)
    }catch{
        fatalError("Unable to delete file: \(error) : \(#function).")
    }
}

Upvotes: 16

Meet Doshi
Meet Doshi

Reputation: 4259

Here you can specify video type, quality and output url for compress video.

See below methods:

- (void) saveVideoToLocal:(NSURL *)videoURL {

    @try {
        NSArray *documentsDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *docPath = [documentsDirectory objectAtIndex:0];

        NSString *videoName = [NSString stringWithFormat:@"sampleVideo.mp4"];
        NSString *videoPath = [docPath stringByAppendingPathComponent:videoName];

        NSURL *outputURL = [NSURL fileURLWithPath:videoPath];
        NSLog(@"Loading video");

        [self convertVideoToLowQuailtyWithInputURL:videoURL outputURL:outputURL handler:^(AVAssetExportSession *exportSession) {

             if (exportSession.status == AVAssetExportSessionStatusCompleted) {
                 NSLog(@"Compression is done");
             }
         }];
    }
    @catch (NSException *exception) {
        NSLog(@"Exception :%@",exception.description);
    }
}


//---------------------------------------------------------------

- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL handler:(void (^)(AVAssetExportSession*))handler {
    [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
    exportSession.outputURL = outputURL;
    exportSession.outputFileType = AVFileTypeMPEG4;
    [exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
        handler(exportSession);
    }];
}

Yes, you can compress video using AVAssetExportSession. Here, I saved compress video to document directory of application. You can check detail working of this in this code.

If you have still issues, then refer this and this.

Upvotes: 1

Rahul Patel
Rahul Patel

Reputation: 5886

You are doing right thing.. Now you need to convert this mov file to mp4 as below.

NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
NSString *videoPath1 = @"";
if (CFStringCompare ((__bridge_retained CFStringRef) mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo)
 {
   if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath))
   {
         NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
         NSString *moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path];
         videoPath1 =[NSString stringWithFormat:@"%@/xyz.mov",docDir];
         NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
         NSData *videoData = [NSData dataWithContentsOfURL:videoURL];
         [videoData writeToFile:videoPath1 atomically:NO];
       //  UISaveVideoAtPathToSavedPhotosAlbum(moviePath, self, nil, nil);
   }
 }

    AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:videoPath1] options:nil];
    NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];

    if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality])
    {
        AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough];
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        videoPath = [NSString stringWithFormat:@"%@/xyz.mp4", [paths objectAtIndex:0]];
        exportSession.outputURL = [NSURL fileURLWithPath:videoPath];
        NSLog(@"videopath of your mp4 file = %@",videoPath);  // PATH OF YOUR .mp4 FILE
        exportSession.outputFileType = AVFileTypeMPEG4;

      //  CMTime start = CMTimeMakeWithSeconds(1.0, 600);
      //  CMTime duration = CMTimeMakeWithSeconds(3.0, 600);           
      //  CMTimeRange range = CMTimeRangeMake(start, duration);            
      //   exportSession.timeRange = range;        
      //  UNCOMMENT ABOVE LINES FOR CROP VIDEO   
        [exportSession exportAsynchronouslyWithCompletionHandler:^{

            switch ([exportSession status]) {

                case AVAssetExportSessionStatusFailed:
                    NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]);

                    break;

                case AVAssetExportSessionStatusCancelled:

                    NSLog(@"Export canceled");

                    break;

                default:

                    break;

            }
             UISaveVideoAtPathToSavedPhotosAlbum(videoPath, self, nil, nil);
            [exportSession release];

        }];

    }
[nextScreenButton setTitle:@"ПРОДЪЛЖИ" forState:UIControlStateNormal];
[self dismissViewControllerAnimated:YES completion:nil];

Upvotes: 34

Related Questions