Question

I got video URL from ALASSET thenconvertVideoToLowQuailtyWithInputURL function to compress video but it can not work. I saw after compress, size of video always is 0.

This is function to get video URL from ALASSET:

ALAsset *alasset = [allVideos objectAtIndex:i];
            ALAssetRepresentation *rep = [alasset defaultRepresentation];
            NSString * videoName = [rep filename];

            //compress video data before uploading
            NSURL  *videoURL = [rep url];
            NSLog(@"videoURL is %@",videoURL);


            NSURL *uploadURL = [NSURL fileURLWithPath:[[NSTemporaryDirectory() stringByAppendingPathComponent:videoName] stringByAppendingString:@".mov"]];
            NSLog(@"uploadURL temp is %@",uploadURL);

            // Compress movie first
            [self convertVideoToLowQuailtyWithInputURL:videoURL outputURL:uploadURL handler:^(AVAssetExportSession *session)
             {
                 if (session.status == AVAssetExportSessionStatusCompleted)
                 {
                     // Success
                 }
                 else
                 {
                     // Error Handing

                 }
             }];

            NSString *path = [uploadURL path];
            NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
            NSLog(@"size after compress video is %d",data.length);
        }

Function compress video :

- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL
                                   outputURL:(NSURL*)outputURL
                                     handler:(void (^)(AVAssetExportSession*))handler
{
    [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
    AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
    AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset: urlAsset presetName:AVAssetExportPresetLowQuality];
    session.outputURL = outputURL;
    session.outputFileType = AVFileTypeQuickTimeMovie;
    [session exportAsynchronouslyWithCompletionHandler:^(void)
     {
         handler(session);

     }];
}

When I called convertVideoToLowQuailtyWithInputURL function, i didn't see it trigger to handler(session); .

And NSLog(@"size after compress video is %d",data.length); always print "size is 0". Where i went wrong? Please give me some advice. Thanks in advance.

Was it helpful?

Solution

convertVideoToLowQuailtyWithInputURL is an asynchronous method, that is why it takes a completion handler block. Your current logging code is not in the completion handler block, but is after the call to convertVideoToLowQuailtyWithInputURL - this will run before convertVideoToLowQuailtyWithInputURL completes so you will never have a result then.

Move your logging (and usage) of the compressed video into the completion block.

OTHER TIPS

ALAssetRepresentation* representation = [asset defaultRepresentation];
NSString *fileName =  [NSString stringWithFormat:@"VGA_%@",representation.filename]; //prepend with _VGA to avoid overwriting original.
NSURL *TempLowerQualityFileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:fileName] ];
NSURL *gallery_url = representation.url;
NSLog(@" \r\n PRE-CONVERSION FILE %@ Size =%lld ; URL=%@\r\n",fileName,  representation.size,representation.url );
[self convertVideoToLowQuailtyWithInputURL:representation.url outputURL:TempLowerQualityFileURL handler:^(AVAssetExportSession *session)
{
      if (session.status == AVAssetExportSessionStatusCompleted)
      {
           NSLog(@"\r\n CONVERSION SUCCESS \r\n");
           NSString *path = [TempLowerQualityFileURL path];
           NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
           NSLog(@" \r\n POST-CONVERSION TEMP FILE %@ Size =%d ; URL=%@\r\n",fileName,  data.length, path );

           ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
             [library writeVideoAtPathToSavedPhotosAlbum:TempLowerQualityFileURL completionBlock:^(NSURL *assetURL, NSError *error)
            {
                 if (error)
                 {
                     NSLog(@"Error Saving low quality video to Camera Roll%@", error);
                 }

                 NSLog(@"\r\n temp low quality file exists before = %d", [self fileExistsAtPath:path] );
                 [[NSFileManager defaultManager] removeItemAtURL:TempLowerQualityFileURL error:nil];
                 NSLog(@"\r\n temp low quality file exists after = %d", [self fileExistsAtPath:path] );

                 NSURL *NewAssetUrlInCameraRoll = assetURL;
                 [[VideoThumbManager sharedInstance] replaceLink:representation.url withNewLink:NewAssetUrlInCameraRoll];


              }];//end writeVideoAtPathToSavedPhotosAlbum completion block.

      }
      else
      {
           // Error Handing
           NSLog(@"\r\n CONVERSION ERROR \r\n");

      }
}];//end convert completion block

SWIFT 3 MP4 Video Compression

100 % Worked For Me

This code compress the video with URL(Document Directory) of 12 MB to 2 MB. I have captured video with .mp4 format and compressed code returns video in same format.

Function where compress held

func compressVideo(inputURL: URL, outputURL: URL, handler:@escaping (_ exportSession: AVAssetExportSession?)-> Void) {
        let urlAsset = AVURLAsset(url: inputURL, options: nil)
        guard let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality) else {
            handler(nil)
            return
        }

        exportSession.outputURL = outputURL
        exportSession.outputFileType = AVFileTypeQuickTimeMovie // Don't change it to .mp4 format
        exportSession.shouldOptimizeForNetworkUse = false
        exportSession.exportAsynchronously { () -> Void in
            handler(exportSession)
        }
    }

Code for Destination URL for Compressed Video

let filePath = URL(fileURLWithPath: strVideoPath)
        var compressedURL : URL!
        let fileManager = FileManager.default
        do {
            let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:true)
            compressedURL = documentDirectory.appendingPathComponent("Video.mp4")
        } catch {
            print(error)
        }
    //It is compulsory to remove previous item at same URL. Otherwise it is unable to save file at same URL.    
        do {
            try   fileManager.removeItem(at: compressedURL)
            print("Removed")
        } catch {
            print(error)
        }

Code For Calling

  compressVideo(inputURL: filePath , outputURL: compressedURL) { (exportSession) in
                guard let session = exportSession else {
                    return
                }

                switch session.status {
                case .unknown:
                    break
                case .waiting:
                    break
                case .exporting:
                    break
                case .completed:
                    print(compressedURL)
                    let newData : Data!
                    do {
                        newData = try Data(contentsOf: compressedURL) as Data?
                        print("File size after compression: \(Double((newData?.count)! / 1048576)) mb")
                    } catch {
                        return
                    }

                case .failed:
                    print(exportSession?.error.debugDescription)
                    break
                case .cancelled:
                    break
                }
            }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top