rFlex / SCRecorder

iOS camera engine with Vine-like tap to record, animatable filters, slow motion, segments editing
Apache License 2.0
3.06k stars 582 forks source link

SCAssetExportSession throwing exception #186

Open justinmakaila opened 9 years ago

justinmakaila commented 9 years ago

Almost 1 in every 6 times, the SCAssetExportSession throws an exception:

Thread : Fatal Exception: NSInvalidArgumentException
0  CoreFoundation                 0x0000000182a9c2d8 __exceptionPreprocess
1  libobjc.A.dylib                0x00000001942c80e4 objc_exception_throw
2  AVFoundation                   0x0000000181299d14 -[AVAssetWriter initWithURL:fileType:error:]
3  AVFoundation                   0x00000001812999bc +[AVAssetWriter assetWriterWithURL:fileType:error:]
4  flare                          0x00000001001f0254 -[SCAssetExportSession exportAsynchronouslyWithCompletionHandler:] (SCAssetExportSession.m:448)
5  flare                          0x00000001000634c0 -[FLReviewViewController postVideo] (FLReviewViewController.m:239)
6  flare                          0x0000000100062b7c -[FLReviewViewController postButtonPressed:] (FLReviewViewController.m:151)
7  UIKit                          0x0000000187511404 -[UIApplication sendAction:to:from:forEvent:]
8  UIKit                          0x00000001874fa4e0 -[UIControl _sendActionsForEvents:withEvent:]
9  UIKit                          0x0000000187510da0 -[UIControl touchesEnded:withEvent:]
10 UIKit                          0x0000000187510a2c -[UIWindow _sendTouchesForEvent:]
11 UIKit                          0x0000000187509f68 -[UIWindow sendEvent:]
12 UIKit                          0x00000001874dd18c -[UIApplication sendEvent:]
13 UIKit                          0x000000018777e324 _UIApplicationHandleEventFromQueueEvent
14 UIKit                          0x00000001874db6a0 _UIApplicationHandleEventQueue
15 CoreFoundation                 0x0000000182a54240 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
16 CoreFoundation                 0x0000000182a534e4 __CFRunLoopDoSources0
17 CoreFoundation                 0x0000000182a51594 __CFRunLoopRun
18 CoreFoundation                 0x000000018297d2d4 CFRunLoopRunSpecific
19 GraphicsServices               0x000000018c1936fc GSEventRunModal
20 UIKit                          0x0000000187542fac UIApplicationMain
21 flare                          0x000000010007ea58 main (main.m:16)
22 libdyld.dylib                  0x0000000194946a08 start

I configure the session like so:

- (void)exportVideo:(void(^)(NSURL *, NSError *))completion {
    AVAsset *asset = self.recordSession.assetRepresentingSegments;
    NSURL *outputUrl = self.recordSession.outputUrl;

    SCAssetExportSession *assetExportSession = [[SCAssetExportSession alloc] initWithAsset:asset];
    assetExportSession.outputUrl = outputUrl;
    assetExportSession.outputFileType = AVFileTypeMPEG4;
    assetExportSession.videoConfiguration.preset = SCPresetHighestQuality;
    assetExportSession.audioConfiguration.preset = SCPresetMediumQuality;

    @try {
        [assetExportSession exportAsynchronouslyWithCompletionHandler:^{
            [MBProgressHUD hideAllLoadingIndicators];

            if (completion) {
                completion(assetExportSession.outputUrl, assetExportSession.error);
            }
        }];
    }
    @catch (NSException *exception) {
        [MBProgressHUD hideAllLoadingIndicators];
        NSError *exportExceptionError = // Create an error

        if (completion) {
            completion(nil, exportExceptionError);
        }
    }
}

The SCRecordSession is also impossible to retry (the exception is thrown over and over again).

The strange thing is that the SCRecordSession is only one segment, and should not be too complicated to export. Can you please provide insight? I'm trying to use the library for a client and this is blocking.

justinmakaila commented 9 years ago

I started to use a custom output url (also in the temp dir) and I'm seeing the error less. I'm not sure if that was actually the cause, and would still appreciate feedback.

rFlex commented 9 years ago

Could you share the additional informations held by this exception? Seems like you are using SCAssetExportSession correctly.

justinmakaila commented 9 years ago

Yes.

*** -[AVAssetWriter initWithURL:fileType:error:] invalid parameter not satisfying: outputURL != ((void *)0)

It's an NSInvalidArgumentException.

Let me know if you need more details.

rFlex commented 9 years ago

That helps! If you don't set a fileType inside the SCRecordSession, it tries to figure out one based on the info it has from SCRecorder. I suppose at that point you detached this recordSession from the recorder, which means it doesn't know which fileType to use anymore. It could be improved, as if the recordSession already has segments, it should be able to figure out a fileType without asking the recorder. The fix for now is to manually set a fileType inside your recordSession. Tell me if that works.

justinmakaila commented 9 years ago

@rFlex AWESOME. I'm going to implement your change this evening, I'll report back here. Thanks!

justinmakaila commented 9 years ago

@rFlex that solution worked for most cases. I'm now having the same issue exclusively with videos that are recorded to the maximum duration. Any ideas?