2011-12-12 9 views
21

Estoy desarrollando un servidor de medios para Play Station 3 en iPhone.Conversión de video de MOV a Mp4 iPhone Programmatically

Me enteré de que PS3 no es compatible con el archivo .MOV, así que tengo que convertirlo en Mp4 o algo más transcodificar que soporte para PS3.

Esto es lo que he hecho, pero se bloquea si establezco un tipo de archivo diferente de sus archivos fuente.

  AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil]; 

      NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset]; 

      if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality]) 

      { 

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

       exportSession.outputURL = [NSURL fileURLWithPath:videoPath]; 

       exportSession.outputFileType = AVFileTypeMPEG4; 

       CMTime start = CMTimeMakeWithSeconds(1.0, 600); 

       CMTime duration = CMTimeMakeWithSeconds(3.0, 600); 

       CMTimeRange range = CMTimeRangeMake(start, duration); 

       exportSession.timeRange = range; 

       [exportSession exportAsynchronouslyWithCompletionHandler:^{ 

        switch ([exportSession status]) { 

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

          break; 

         case AVAssetExportSessionStatusCancelled: 

          NSLog(@"Export canceled"); 

          break; 

         default: 

          break; 

        } 

        [exportSession release]; 

       }]; 

      } 

si fijo AVFileTypeMPEG4 aquí, entonces se bloquea, diciendo "tipo de archivo no válido". Así que tengo que configurarlo en AVFileTypeQuickTimeMovie y da el archivo MOV.

¿Es posible en iOS convertir video de MOV a Mp4 a través de AVAssetExportSession ... O sin ninguna biblioteca de Thirdparty?

+0

¿Alguna vez una solución para esto? – newenglander

+0

¿Tienes solución para esta conversión? – svmrajesh

+0

No se puede leer ningún códec aleatorio de .mov en iOS, solo el video h.264 codificado como .mov/.m4v puede ser leído por AVFoundation. – MoDJ

Respuesta

7

MOV es muy similar a MP4, es posible que solo pueda cambiar la extensión y hacer que funcione, Windows Phone no puede reproducir .MOVS pero puede reproducir mp4, todo lo que hice para que funcione es cambiar la extensión. mov a .mp4 y funciona bien, y esto es de videos grabados en el iphone ... y en todo caso puedes intentar exportar con AVAssetExporter y probar que hay un tipo de archivo para MP4 y M4A como puedes ver en el FileFormat infecciones urinarias here

creo que sirve

+0

Daniel ,, a continuación se muestra lo que hice, pero se bloquea si configuro un tipo de archivo diferente al de sus archivos fuente. –

+2

Cambiar la extensión a mp4 funciona para mí –

+7

No funciona en todas partes esa solución, por ejemplo, algunos dispositivos Android no reproducen estos videos – Kasas

10

presetName utilizar "AVAssetExportPresetPassthrough" en lugar "AVAssetExportPresetLowQuality"

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough]; 
2

sólo quería decir que la URL no puede ser como

[NSURL URLWithString: [@"~/Documents/movie.mov" stringByExpandingTildeInPath]] 

que debe ser como

[NSURL fileURLWithPath: [@"~/Documents/movie.mov" stringByExpandingTildeInPath]] 

Me tomó un tiempo para darse cuenta de eso :-)

+0

Muchas gracias –

3

Uso el siguiente código

NSURL * mediaURL = [info objectForKey:UIImagePickerControllerMediaURL]; 
    AVAsset *video = [AVAsset assetWithURL:mediaURL]; 
    AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPresetMediumQuality]; 
    exportSession.shouldOptimizeForNetworkUse = YES; 
    exportSession.outputFileType = AVFileTypeMPEG4; 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; 
    basePath = [basePath stringByAppendingPathComponent:@"videos"]; 
    if (![[NSFileManager defaultManager] fileExistsAtPath:basePath]) 
     [[NSFileManager defaultManager] createDirectoryAtPath:basePath withIntermediateDirectories:YES attributes:nil error:nil]; 

    compressedVideoUrl=nil; 
    compressedVideoUrl = [NSURL fileURLWithPath:basePath]; 
    long CurrentTime = [[NSDate date] timeIntervalSince1970]; 
    NSString *strImageName = [NSString stringWithFormat:@"%ld",CurrentTime]; 
    compressedVideoUrl=[compressedVideoUrl URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4",strImageName]]; 

    exportSession.outputURL = compressedVideoUrl; 

    [exportSession exportAsynchronouslyWithCompletionHandler:^{ 

     NSLog(@"done processing video!"); 
     NSLog(@"%@",compressedVideoUrl); 

     if(!dataMovie) 
      dataMovie = [[NSMutableData alloc] init]; 
     dataMovie = [NSData dataWithContentsOfURL:compressedVideoUrl]; 

    }]; 
5

Necesita AVMutableComposition para hacer esto. Porque Asset no se puede transcodificar a MP4 directamente en iOS 5.0.

- (BOOL)encodeVideo:(NSURL *)videoURL 
{ 
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil]; 

    // Create the composition and tracks 
    AVMutableComposition *composition = [AVMutableComposition composition]; 
    AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
    AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
    NSArray *assetVideoTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; 
    if (assetVideoTracks.count <= 0) 
    { 
      NSLog(@"Error reading the transformed video track"); 
      return NO; 
    } 

    // Insert the tracks in the composition's tracks 
    AVAssetTrack *assetVideoTrack = [assetVideoTracks firstObject]; 
    [videoTrack insertTimeRange:assetVideoTrack.timeRange ofTrack:assetVideoTrack atTime:CMTimeMake(0, 1) error:nil]; 
    [videoTrack setPreferredTransform:assetVideoTrack.preferredTransform]; 

    AVAssetTrack *assetAudioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 
    [audioTrack insertTimeRange:assetAudioTrack.timeRange ofTrack:assetAudioTrack atTime:CMTimeMake(0, 1) error:nil]; 

    // Export to mp4 
    NSString *mp4Quality = [MGPublic isIOSAbove:@"6.0"] ? AVAssetExportPresetMediumQuality : AVAssetExportPresetPassthrough; 
    NSString *exportPath = [NSString stringWithFormat:@"%@/%@.mp4", 
            [NSHomeDirectory() stringByAppendingString:@"/tmp"], 
            [BSCommon uuidString]]; 

    NSURL *exportUrl = [NSURL fileURLWithPath:exportPath]; 
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:mp4Quality]; 
    exportSession.outputURL = exportUrl; 
    CMTime start = CMTimeMakeWithSeconds(0.0, 0); 
    CMTimeRange range = CMTimeRangeMake(start, [asset duration]); 
    exportSession.timeRange = range; 
    exportSession.outputFileType = AVFileTypeMPEG4; 
    [exportSession exportAsynchronouslyWithCompletionHandler:^{ 
      switch ([exportSession status]) 
      { 
       case AVAssetExportSessionStatusCompleted: 
         NSLog(@"MP4 Successful!"); 
         break; 
       case AVAssetExportSessionStatusFailed: 
         NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]); 
         break; 
       case AVAssetExportSessionStatusCancelled: 
         NSLog(@"Export canceled"); 
         break; 
       default: 
         break; 
      } 
    }]; 

    return YES; 
} 
+0

¿Esto funciona para todos los formatos o solo .mov? – yazh

5

Puede convertir video en mp4 con AVAssets.

AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil]; 
NSArray *compatiblePresets = [AVAssetExportSession  
exportPresetsCompatibleWithAsset:avAsset]; 
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetLowQuality]; 

NSString* documentsDirectory=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    exportSession.outputURL = url; 
//set the output file format if you want to make it in other file format (ex .3gp) 
exportSession.outputFileType = AVFileTypeMPEG4; 
exportSession.shouldOptimizeForNetworkUse = YES; 

[exportSession exportAsynchronouslyWithCompletionHandler:^{ 
switch ([exportSession status]) 
{ 
     case AVAssetExportSessionStatusFailed: 
      NSLog(@"Export session failed"); 
      break; 
     case AVAssetExportSessionStatusCancelled: 
      NSLog(@"Export canceled"); 
      break; 
     case AVAssetExportSessionStatusCompleted: 
     { 
      //Video conversion finished 
      NSLog(@"Successful!"); 
     } 
      break; 
     default: 
      break; 
    } 
}]; 

Para convertir el vídeo a MP4 uso de este link.

También puede encontrar un proyecto de ejemplo para convertir video a mp4.

+0

¿Podría el archivo de salida ser un objeto temporal '' 'NSData''' en lugar de' '' outputURL'''? No entiendo dónde se supone que debo guardar el archivo convertido ... y más al punto que no quiero guardarlo, solo quiero subirlo a un servidor, así que no necesito '' 'outputURL''', solo necesito enviarlo a un objeto. – Supertecnoboff

4

Este es el código

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__).") 
    } 
} 
Cuestiones relacionadas