Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVAssetExportSession stops progressing

I'm having a problem with AVAssetExportSession where the progress stops increasing but the status still says that it is exporting. This is actually a pretty rare occurrence, it works flawlessly about 99.99% of the time, but I want to fix the problem anyway.

So I start the exporting:

    exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
    exportSession.videoComposition = videoComposition; 
    exportSession.outputFileType = @"com.apple.quicktime-movie";
    exportSession.outputURL = outputURL;
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        ...
    }];

Then have a timer checking the progress:

    AVAssetExportSessionStatus status = [exportSession status];
    float progress = 0;
    if (status == AVAssetExportSessionStatusExporting) {
        progress = [exportSession progress];
    } else if (status == AVAssetExportSessionStatusCompleted) {
        progress = 1;
    }
    NSLog(@"%d %f", status, progress);
    [delegate processor:self didProgress:progress];

And the output ends up looking like:

2012-05-23 14:28:59.494 **********[1899:707] 2 0.125991
2012-05-23 14:28:59.994 **********[1899:707] 2 0.185280
2012-05-23 14:29:00.494 **********[1899:707] 2 0.259393
2012-05-23 14:29:00.994 **********[1899:707] 2 0.326093
2012-05-23 14:29:01.494 **********[1899:707] 2 0.400206
2012-05-23 14:29:01.995 **********[1899:707] 2 0.481729
2012-05-23 14:29:02.495 **********[1899:707] 2 0.541019
2012-05-23 14:29:02.997 **********[1899:707] 2 0.622542
2012-05-23 14:29:03.493 **********[1899:707] 2 0.681832
2012-05-23 14:29:03.995 **********[1899:707] 2 0.763355
2012-05-23 14:29:04.494 **********[1899:707] 2 0.822645
2012-05-23 14:29:04.994 **********[1899:707] 2 0.880082
2012-05-23 14:29:05.493 **********[1899:707] 2 0.880082
2012-05-23 14:29:05.994 **********[1899:707] 2 0.880082
...
2012-05-23 14:43:22.994 **********[1899:707] 2 0.880082
2012-05-23 14:43:23.493 **********[1899:707] 2 0.880082
2012-05-23 14:43:23.994 **********[1899:707] 2 0.880082
2012-05-23 14:43:24.494 **********[1899:707] 2 0.880082

(Note: It doesn't stop at the same percentage every time, its totally random)

As you can see from the timestamps it took 5 seconds to do the first 88%, and then I let it run for another 13 minutes (full video processing usually doesn't take more then 10 seconds) with no change in the progress.

Currently my only option is to check if the progress hasn't changed in the last X seconds and just tell the user it failed and to try again.

Anyone have any ideas?

like image 285
poiuy_qwert Avatar asked May 23 '12 20:05

poiuy_qwert


1 Answers

In my case this problem stemmed from mp4s that were encoded with unusual configurations. But ultimately a bug in Apple's code causes the issue.

Specifically I was working with mp4s on Facebook. It seems that when facebook encodes videos it drops or shifts the first frame of the video track. Examining the video with ffprobe showed:

        "r_frame_rate": "722/25",
        "avg_frame_rate": "722/25",
        "time_base": "1/28880",
        "start_pts": 1000,
        "start_time": "0.034626",

0.034626 is exactly the time for frame 2. The audio track, however, started at 0.

Unfortunately Apple's APIs don't correctly report this start time for the track. After getting the AVAssetTrack from the AVAsset and checking its timeRange it reported the start time as 0. It's possible I'm misunderstanding the nature of track and asset timing, but this seems like a bug.

Of course, when building the video composition for the export session I used the track time range which was incorrect. I suspect that when the export session looks for data in the track at time 0 and finds nothing it gets confused, and then as we've seen, just hangs and doesn't even report an error - another bug. Even creating the composition with videoCompositionWithPropertiesOfAsset: doesn't help.

I have not yet tried to use AVAssetReader and AVAssetWriter instead of AVAssetExportSession so I don't know if you would encounter the same situation there. Until I have more time to explore that I've come up with this hack as a solution:

Reset the time range used for track insertion and video instructions to start at 1 or 2 frames in:

CMTimeRange videoTimeRange = videoTrack.timeRange;
videoTimeRange.start = CMTimeMake(1, ceil(videoTrack.nominalFrameRate));

Obviously this hack only applies to the particular situation where the video track start time is not 0. I would guess that in general this bug arises from unusual media encodings that AVAssetExportSession and its related classes are not expecting.

like image 151
kball Avatar answered Sep 19 '22 15:09

kball