Search code examples
iosobjective-cavfoundationavassetexportsessionavkit

AVAssetExportSession exportAsynchronouslyWithCompletionHandler returns failed


I'm implementing AVAssetExportSession to trim a video online but always returns failed.

Here is my implementation:

NSString *url = @"http://www.ebookfrenzy.com/ios_book/movie/movie.mov";
NSURL *fileURL = [NSURL URLWithString:url];
AVAsset *asset = [AVAsset assetWithURL:fileURL];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
NSURL *exportUrl = [NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:@"export.m4a"]];

exportSession.outputURL = exportUrl;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
CMTime time = CMTimeMake(1, 10);
exportSession.timeRange = CMTimeRangeMake(kCMTimeZero, time);
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {

    switch (exportSession.status)
    {
        case AVAssetExportSessionStatusCompleted:
            /*expor is completed*/
            NSLog(@"Completed!!");
            break;
            case AVAssetExportSessionStatusFailed:
            NSLog(@"failed!!");
            /*failed*/
            break;
        default:
            break;
    }
}];

Any of you knows why this happening or what I'm doing wrong?


Solution

  • You are attempting to create an AVAsset with a remote URL and you need to know that the asset has loaded before you can begin your export.

    AVAsset conforms to the AVAsynchronousKeyValueLoading protocol, which means you can observe the tracks key and start your export once the value changes:

    NSURL *myURL = [NSURL URLWithString:myMovieURLString];
    AVAsset *asset = [AVAsset assetWithURL:myURL];
    
    __weak typeof(self) weakSelf = self;
    
    [asset loadValuesAsynchronouslyForKeys:@[@"tracks"] completionHandler:^{
    
        //Error checking here - make sure there are tracks
    
        [weakSelf exportAsset:asset];
    
    }];
    

    Then you can have your export code in a separate method:

    - (void)exportAsset:(AVAsset *)asset {
    
        //Your export code here
    }