MOV в Mp4 видео конвертация iPhone программно - PullRequest
22 голосов
/ 12 декабря 2011

Я разрабатываю медиасервер для Play Station 3. в iPhone.

Я узнал, что PS3 не поддерживает файл .MOV, поэтому мне нужно преобразовать его в Mp4 или в другой транскод, который поддерживает PS3.

Это то, что я сделал, но происходит сбой, если я задаю тип файла, отличный от его исходных файлов.

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

Если я здесь установил AVFileTypeMPEG4, то происходит сбой, говоря «Неверный тип файла»,Поэтому я должен установить его в AVFileTypeQuickTimeMovie, и он дает файл MOV.

Можно ли в iOS конвертировать видео из MOV в Mp4 через AVAssetExportSession ... ИЛИ без каких-либо библиотек Thirdparty?

Ответы [ 7 ]

10 голосов
/ 12 января 2012

presetName, используйте «AVAssetExportPresetPassthrough» вместо «AVAssetExportPresetLowQuality»

 AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough];
7 голосов
/ 12 декабря 2011

MOV очень похож на MP4, вы можете просто изменить расширение и заставить его работать, Windows Phone не может воспроизводить .MOVS, но может воспроизводить mp4, все, что я сделал, чтобы заставить это работать, это измени расширение с .movв .mp4, и он работает нормально, и это из видео, снятых на iphone ... и если что-то вы можете определить, попробуйте экспортировать с AVAssetExporter и попробуйте там есть тип файла для MP4 и M4A, как вы можете видеть из формата файлаИМП здесь

надеюсь, что это поможет

5 голосов
/ 17 апреля 2015

Вы можете конвертировать видео в формате mp4 с помощью 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;
  }
 }];

Чтобы легко конвертировать видео в mp4, используйте эту ссылку .

Вы также можете найти пример проекта для конвертации видео в mp4.

5 голосов
/ 26 мая 2014

Вам нужно AVMutableComposition, чтобы сделать это. Потому что Asset нельзя перекодировать в MP4 напрямую под 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 голосов
/ 05 сентября 2016

Вот код

    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__).")
    }
}
4 голосов
/ 02 мая 2014

Используйте код ниже

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

    }];
2 голосов
/ 22 марта 2013

просто хотел сказать, что URL не может быть похож на

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

Это должно быть похоже на

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

Мне понадобилось время, чтобы понять это: -)

...