JavaEar 专注于收集分享传播有价值的技术资料

MOV to Mp4 video conversion iPhone Programmatically

I am developing media server for Play station 3 in iPhone.

I came to know that PS3 doesn't support .MOV file so I have to convert it into Mp4 or something other transcode which PS3 support.

This is what I have done but it crashes if I set different file type than its source files.

            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];

                }];

            }

If I set AVFileTypeMPEG4 here then it crashes, saying "Invalid file type". So I have to set it to AVFileTypeQuickTimeMovie and it gives MOV file.

Is it possible in iOS to convert video from MOV to Mp4 through AVAssetExportSession...OR without any Thirdparty libraryies?

7个回答

    最佳答案
  1. MOV is very similar to MP4, you might be able to just change the extension and have it work, Windows Phone cant play .MOVS but can play mp4, all i did to get that to work is change the extension from .mov to .mp4 and it works fine, and this is from videos shot on the iphone...and if anything you can def try exporting with AVAssetExporter and try there is a file type in there for MP4 and M4A as you can see from the fileformat UTIs here

    hope it helps

  2. 参考答案2
  3. You need AVMutableComposition to do this. Because Asset can't be transcode to MP4 directly under 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;
    }
    
  4. 参考答案3
  5. You can convert video in mp4 by 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;
      }
     }];
    

    To easily convert video to mp4 use this link.

    You can also find sample project to convert video to mp4.

  6. 参考答案4
  7. Use the below code

        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];
    
        }];
    
  8. 参考答案5
  9. Here is the code

        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__).")
        }
    }
    
  10. 参考答案6
  11. just wanted to say that the URL can not be like

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

    It must be like

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

    Took me a while to figure that out :-)

  12. 参考答案7
  13. presetName use "AVAssetExportPresetPassthrough" instead "AVAssetExportPresetLowQuality"

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