質問

Update: Curiously this code works fine on an iPad 2 but not an iPad 4th Gen.

Update #2: If I change presetName:AVAssetExportPresetHighestQuality to presetName:AVAssetExportPresetPassThrough the video successfully exports but I can't play it in the device. I can play it if I pull the application bundle off to my computer through xCode's organiser. Again, this problem only occurs on the iPad 4, not the iPad 2, the 64bit simulator, the retina simulator or the 1x simulator.

I'm mixing some audio and video using an AVExportSession. It works quite happily on the simulator, and iPad 2 but not an iPad 4th Gen. The export session gives a -11820 error (AVErrorExportFailed), but that's the extent of useful information I can get out of the process. The source files are present, and everything else is working swimmingly, but not the AVExportSession.

Could you help me get it working on the device as well?

Apologies for the verbosity of the method.

-(NSURL*)bindAudioAndVideo:(NSString*)audioFileName videoFileName:(NSString*)videoFileName
{

   //documents folder
   NSArray     *paths              = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
   NSString *documentsFolder       = [[NSString alloc] initWithString:[paths objectAtIndex:0]];    //Get the docs directory

    AVMutableComposition* mixComposition = [AVMutableComposition composition];

    NSString* audio_inputFileName   = audioFileName;
    NSString* audio_inputFilePath   = [documentsFolder stringByAppendingPathComponent:audio_inputFileName];
    NSURL*    audio_inputFileUrl    = [NSURL fileURLWithPath:audio_inputFilePath];

    NSString* video_inputFileName   = videoFileName;
    NSString* video_inputFilePath   = [documentsFolder stringByAppendingPathComponent:video_inputFileName];
    NSURL*    video_inputFileUrl    = [NSURL fileURLWithPath:video_inputFilePath];

    NSString* outputFileName        = @"outputFile.mp4";
    NSString* outputFilePath        = [documentsFolder stringByAppendingPathComponent:outputFileName];
    NSURL*    outputFileUrl         = [NSURL fileURLWithPath:outputFilePath];

    //Check files actually exist before beginning (they do)

    AVMutableComposition* mixComposition = [AVMutableComposition composition];
    CMTime nextClipStartTime = kCMTimeZero;

    AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:video_inputFileUrl options:nil];
    CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
    AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    [a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:nextClipStartTime error:nil];


    AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:audio_inputFileUrl options:nil];
    CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration);
    AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:nextClipStartTime error:nil];



    AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
    _assetExport.outputFileType = @"com.apple.quicktime-movie";
    _assetExport.outputURL = outputFileUrl;

    [_assetExport exportAsynchronouslyWithCompletionHandler:
     ^(void ) {
         [self addSkipBackupAttributeToItemAtURL:outputFileUrl];
         NSLog(@"Completed. Tidy time.");

         switch ([_assetExport status]) {
             case AVAssetExportSessionStatusCompleted:
                 NSLog(@"Export Completed");
                 break;
             case AVAssetExportSessionStatusFailed:
                 NSLog(@"Export failed: %@", [[_assetExport error] localizedDescription]);
                 NSLog (@"FAIL %@",_assetExport.error); //-11820! I AM A USELESS ERROR CODE
                 NSLog (@"supportedFileTypes: %@", _assetExport.supportedFileTypes);
                 break;
             case AVAssetExportSessionStatusCancelled:
                 NSLog(@"Export cancelled");
                 break;
             default:
                 break;
         }


            NSTimer *refreshTimer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(exportCompleteRefreshView) userInfo:Nil repeats:NO];

         //Throw back to main thread unuless you want really long delays for no reason.
         [[NSRunLoop mainRunLoop] addTimer:refreshTimer forMode:NSRunLoopCommonModes];
     }
     ];



    return outputFileUrl;
}
役に立ちましたか?

解決

If the problem is connected to the retina iPads - it's got something to do with device resolution, that for some reason the simulator isn't simulating.

Since I was creating the video on device, I was making a 2048x1536 video on the retina devices (and 1024x768 on the non-retina devices). Apparently this is just too many pixels for AVExportSession to handle, or the iPad to play properly, so it just threw a variety of vague error messages at me on play, or export. Recording at the point resolution, rather than the pixel resolution seems to have resolved the problem.

The simulator appears to be a red herring since it has the comparatively limitless resources of a healthy mac at its disposal, rather than an A6.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top