2012-10-03 18 views
11

Actualmente estoy trabajando en una aplicación que trata sobre los videos. En mi aplicación, el usuario puede recortar el video, tengo un control personalizado para seleccionar la hora de inicio y la hora de finalización. Necesito recortar el video con estos dos valores. Intenté con UIVideoEditorController como sigue.Recortar video sin mostrar UIVideoEditorController?

UIVideoEditorController* videoEditor = [[[UIVideoEditorController alloc] init] autorelease]; 
    videoEditor.delegate = self; 
    NSString* videoPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"MOV"]; 
    if ([UIVideoEditorController canEditVideoAtPath:videoPath]) 
    { 
     videoEditor.videoPath = videoPath; 
     [self presentModalViewController:videoEditor animated:YES]; 
    } 
    else 
    { 
     NSLog(@"can't edit video at %@", videoPath); 
    } 

Pero el problema es que el código anterior mostrará el control de edición de vídeo de Apple y el usuario puede realizar algunas operaciones en ese punto de vista. No quiero mostrar esta vista, porque ya he mostrado el video en MPMoviePlayer y recibí la entrada del usuario (hora de inicio y hora de finalización) para recortar el video en un control personalizado. ¿Cómo puedo recortar un video sin mostrar UIVideoEditorController?

+1

me puedes dar ur código para el recorte de vídeo, donde el usuario puede elegir de inicio y fin? –

Respuesta

17

Finalmente encontré la solución.

Podemos usar AVAssetExportSession para recortar el video sin mostrar UIVideoEditorController.

Mi código es como:

- (void)splitVideo:(NSString *)outputURL 
{ 

    @try 
    { 
     NSString *videoBundleURL = [[NSBundle mainBundle] pathForResource:@"Video_Album" ofType:@"mp4"]; 

     AVAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:videoBundleURL] options:nil]; 

     NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset]; 

     if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality]) 
     { 

      [self trimVideo:outputURL assetObject:asset]; 

     } 
     videoBundleURL = nil; 

     [asset release]; 
     asset = nil; 

     compatiblePresets = nil; 
    } 
    @catch (NSException * e) 
    { 
     NSLog(@"Exception Name:%@ Reason:%@",[e name],[e reason]); 
    } 
} 

Este método recorta el vídeo

- (void)trimVideo:(NSString *)outputURL assetObject:(AVAsset *)asset 
    { 

    @try 
    { 

     AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:asset presetName:AVAssetExportPresetLowQuality]; 

     exportSession.outputURL = [NSURL fileURLWithPath:outputURL]; 

     exportSession.outputFileType = AVFileTypeQuickTimeMovie; 

     CMTime start = CMTimeMakeWithSeconds(splitedDetails.startTime, 1); 

     CMTime duration = CMTimeMakeWithSeconds((splitedDetails.stopTime - splitedDetails.startTime), 1); 

     CMTimeRange range = CMTimeRangeMake(start, duration); 

     exportSession.timeRange = range; 

     exportSession.outputFileType = AVFileTypeQuickTimeMovie; 

     [self checkExportSessionStatus:exportSession]; 

     [exportSession release]; 
     exportSession = nil; 

    } 
    @catch (NSException * e) 
    { 
     NSLog(@"Exception Name:%@ Reason:%@",[e name],[e reason]); 
    } 
} 

Este método comprueba el estado del recorte:

- (void)checkExportSessionStatus:(AVAssetExportSession *)exportSession 
    { 

    [exportSession exportAsynchronouslyWithCompletionHandler:^(void) 
    { 

     switch ([exportSession status]) 
      { 

      case AVAssetExportSessionStatusCompleted: 

       NSLog(@"Export Completed"); 
       break; 

      case AVAssetExportSessionStatusFailed: 

       NSLog(@"Error in exporting"); 
       break; 

      default: 
       break; 

     } 
    }]; 
} 

Voy a llamar al método splitVideo desde el método de acción de botón de exportación y pasa la salida UR L como argumento.

+0

cuál es la url de salida – Warewolf

+1

@Khoool: outputUrl se proporciona para escribir el video recortado. Es una ruta de archivo en el directorio de documentos –

+0

estoy usando el mismo código pero recibo el error: Error al exportar NSString * path = [NSSearchPathForDirectoriesInDomains (NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex: 0]; path = [path stringByAppendingPathComponent: @ "new.mov"]; NSLog (@ "ruta para guardar video es% @", ruta); [self splitVideo: path]; – Warewolf

2

Podemos importar AVFoundation/AVFoundation.h

-(BOOL)trimVideofile 
{ 

    float videoStartTime;//define start time of video 
    float videoEndTime;//define end time of video 
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
    [dateFormatter setDateFormat:@"yyyy-MM-dd_HH-mm-ss"]; 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); 
    NSString *libraryCachesDirectory = [paths objectAtIndex:0]; 
    libraryCachesDirectory = [libraryCachesDirectory stringByAppendingPathComponent:@"Caches"]; 
    NSString *OutputFilePath = [libraryCachesDirectory stringByAppendingFormat:@"/output_%@.mov", [dateFormatter stringFromDate:[NSDate date]]]; 
    NSURL *videoFileOutput = [NSURL fileURLWithPath:OutputFilePath]; 
    NSURL *videoFileInput;//<Path of orignal Video file> 

    if (!videoFileInput || !videoFileOutput) 
    { 
     return NO; 
    } 

    [[NSFileManager defaultManager] removeItemAtURL:videoFileOutput error:NULL]; 
    AVAsset *asset = [AVAsset assetWithURL:videoFileInput]; 

    AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset 
                      presetName:AVAssetExportPresetLowQuality]; 
    if (exportSession == nil) 
    { 
     return NO; 
    } 
    CMTime startTime = CMTimeMake((int)(floor(videoStartTime * 100)), 100); 
    CMTime stopTime = CMTimeMake((int)(ceil(videoEndTime * 100)), 100); 
    CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime); 

    exportSession.outputURL = videoFileOutput; 
    exportSession.timeRange = exportTimeRange; 
    exportSession.outputFileType = AVFileTypeQuickTimeMovie; 

    [exportSession exportAsynchronouslyWithCompletionHandler:^ 
    { 
     if (AVAssetExportSessionStatusCompleted == exportSession.status) 
     { 
      NSLog(@"Export OK"); 
     } 
     else if (AVAssetExportSessionStatusFailed == exportSession.status) 
     { 
      NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]); 
     } 
    }]; 
    return YES; 
} 
+0

Esta respuesta es la misma que la anterior, ¿cuál es la ventaja de duplicar la respuesta? –

+0

No es la respuesta de duplicación. En este caso, estamos usando otra solución diferente. –

+0

En la respuesta anterior, también está usando 'AVAssetExportSession'. Aquí también lo mismo, ¿entonces cuál es la diferencia? –

Cuestiones relacionadas