以Mp4格式捕获视频

时间:2014-12-26 10:47:02

标签: ios objective-c

我正在使用UIImagePickerController来录制视频,问题是它以mov格式录制视频以便于Android兼容。

我需要使用以下代码将视频转换为mp4格式,问题是它需要一段时间才能拍摄6秒钟的视频,大约需要30到35秒。 我可以用mp4格式或更快的方法直接录制视频的任何解决方案都会有很大的帮助。在此先感谢

   -(void)movToMp4:(NSURL *)videoURL{ // method for mov to mp4 conversion

    AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:videoURL 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);
        NSString* videoPath = [NSString stringWithFormat:@"%@/xyz.mp4", [paths objectAtIndex:0]];
        exportSession.outputURL = [NSURL fileURLWithPath:videoPath];
        exportSession.outputFileType = AVFileTypeMPEG4;
        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            switch ([exportSession status]) {  // switch case to get completion case where i put my delegate
                    return;
                    break;
                case AVAssetExportSessionStatusCompleted: {
                     [self.delegate mp4Response:videoPath];
                        break;

                    }

                }

            }
        }];
    }

}

2 个答案:

答案 0 :(得分:3)

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    NSLog(@"file info = %@", info);
    NSString *pickedType = [info objectForKey:@"UIImagePickerControllerMediaType"];
   NSData *videoData;
    if ([pickedType isEqualToString:@"public.movie"]){

        NSURL *videoUrl=(NSURL*)[info objectForKey:UIImagePickerControllerMediaURL];
        videoData = [NSData dataWithContentsOfURL:videoUrl];

    }

    [self dismissViewControllerAnimated:YES completion:^{

        // 
        [self writeFileData:videoData];
    }];

}

// to get path of document directory
- (NSString *)applicationDocumentsDirectory
{
    //    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return documentsDirectory;
}

- (void) writeFileData:(NSData *)fileData{



    float size = fileData.length / (1024 * 1024);

    NSString *fileName = nil;
    NSString *strPath =  nil;

    NSString *documentsDirectory = [self applicationDocumentsDirectory];

    double CurrentTime = CACurrentMediaTime();


        fileName = [NSString stringWithFormat:@"%d.mp4",(int)CurrentTime];


    strPath =  [documentsDirectory stringByAppendingPathComponent:fileName];
    NSFileManager *filemanager=[[NSFileManager alloc] init];
    NSError *er;

    if (![filemanager fileExistsAtPath:documentsDirectory]) {
        [filemanager createDirectoryAtPath:documentsDirectory withIntermediateDirectories:YES attributes:nil error:&er];
        NSLog(@"error in folder creation = %@", er);

    }

    NSLog(@"size of data = %lu", (unsigned long)[fileData length]);
    BOOL saved = [fileData writeToFile:strPath atomically:YES];
    if (saved) {
        NSURL *videoURL = [NSURL URLWithString:strPath];
        // now u can handle mp4 video from videoURL
        }
    else
        return;


}

答案 1 :(得分:3)

是的,因为使用AVURLAsset从库/相册加载视频需要一些时间。

所以你需要在这里使用block来加载来自库的视频。

也行

[self.delegate mp4Response:videoPath];

在完成块中 - 它应该在主线程上。

遵循这种方法:

UIImagePickerController委托方法从图书馆获取视频。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    NSURL *localUrl = (NSURL *)[info valueForKey:UIImagePickerControllerMediaURL];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString* videoPath = [NSString stringWithFormat:@"%@/xyz.mp4", [paths objectAtIndex:0]];
    NSURL *outputURL = [NSURL fileURLWithPath:videoPath];

    [self convertVideoToLowQuailtyWithInputURL:localUrl outputURL:outputURL handler:^(AVAssetExportSession *exportSession)
     {
         if (exportSession.status == AVAssetExportSessionStatusCompleted) {
             NSLog(@"Capture video complete");
             [self performSelectorOnMainThread:@selector(doneCompressing) withObject:nil waitUntilDone:YES];
         }
     }];
    [self dismissViewControllerAnimated:YES completion:nil];
}


- (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);
     }];
}

didFinishPickingMediaWithInfo方法中观察到这一行:

[self performSelectorOnMainThread:@selector(doneCompressing) withObject:nil waitUntilDone:YES];

它将在主线程(前台)中再调用一个方法doneCompressing。这样您就可以在doneCompressing中调用委托方法。这会减少时间。

- (void) doneCompressing {
      [self.delegate mp4Response:videoPath];
}