12

We capture video on iOS while using setPreferredVideoStabilizationMode:AVCaptureVideoStabilizationModeAuto, but the video still sometimes comes out blurry at the start and at the end (fine in the middle, though), which is very problematic because we grab the first frame as a still image (in order to enable video & photo capabilities without switching camera modes).

Placing the device flat on a desk removes all blurriness, so the whole video is sharp throughout. This suggests it has something to do with video stabilization, but is there another property to set?

Does locking the focus mode matter?

Any other troubleshooting tips?

Here is the video capture function from PBJVision, which we use:

- (void)startVideoCapture
{
    if (![self _canSessionCaptureWithOutput:_currentOutput] || _cameraMode != PBJCameraModeVideo) {
        [self _failVideoCaptureWithErrorCode:PBJVisionErrorSessionFailed];
        DLog(@"session is not setup properly for capture");
        return;
    }

    DLog(@"starting video capture");

    [self _enqueueBlockOnCaptureVideoQueue:^{

        if (_flags.recording || _flags.paused)
            return;

        NSString *guid = [[NSUUID new] UUIDString];
        NSString *outputFile = [NSString stringWithFormat:@"video_%@.mp4", guid];

        if ([_delegate respondsToSelector:@selector(vision:willStartVideoCaptureToFile:)]) {
            outputFile = [_delegate vision:self willStartVideoCaptureToFile:outputFile];

            if (!outputFile) {
                [self _failVideoCaptureWithErrorCode:PBJVisionErrorBadOutputFile];
                return;
            }
        }

        NSString *outputDirectory = (_captureDirectory == nil ? NSTemporaryDirectory() : _captureDirectory);
        NSString *outputPath = [outputDirectory stringByAppendingPathComponent:outputFile];
        NSURL *outputURL = [NSURL fileURLWithPath:outputPath];
        if ([[NSFileManager defaultManager] fileExistsAtPath:outputPath]) {
            NSError *error = nil;
            if (![[NSFileManager defaultManager] removeItemAtPath:outputPath error:&error]) {
                [self _failVideoCaptureWithErrorCode:PBJVisionErrorOutputFileExists];

                DLog(@"could not setup an output file (file exists)");
                return;
            }
        }

        if (!outputPath || [outputPath length] == 0) {
            [self _failVideoCaptureWithErrorCode:PBJVisionErrorBadOutputFile];

            DLog(@"could not setup an output file");
            return;
        }

        if (_mediaWriter) {
            _mediaWriter.delegate = nil;
            _mediaWriter = nil;
        }
        _mediaWriter = [[PBJMediaWriter alloc] initWithOutputURL:outputURL];
        _mediaWriter.delegate = self;

        AVCaptureConnection *videoConnection = [_captureOutputVideo connectionWithMediaType:AVMediaTypeVideo];
        [self _setOrientationForConnection:videoConnection];

        _startTimestamp = CMClockGetTime(CMClockGetHostTimeClock());
        _timeOffset = kCMTimeInvalid;

        _flags.recording = YES;
        _flags.paused = NO;
        _flags.interrupted = NO;
        _flags.videoWritten = NO;

        _captureThumbnailTimes = [NSMutableSet set];
        _captureThumbnailFrames = [NSMutableSet set];

        if (_flags.thumbnailEnabled && _flags.defaultVideoThumbnails) {
            [self captureVideoThumbnailAtFrame:0];
        }

        [self _enqueueBlockOnMainQueue:^{                
            if ([_delegate respondsToSelector:@selector(visionDidStartVideoCapture:)])
                [_delegate visionDidStartVideoCapture:self];
        }];
    }];
}

This code configures PBJVision and starts video capture:

private func initPBJVision() {
    // Configure PBJVision
    pbj.delegate = self
    pbj.cameraMode = .Video
    pbj.cameraOrientation = .Portrait
    pbj.focusMode = .AutoFocus
    pbj.outputFormat = .Preset
    pbj.cameraDevice = .Back
    pbj.thumbnailEnabled = false

    // Log status
    print("Configured PBJVision")

    pbj.startVideoCapture()
}

Once PBJ is ready with its preview, we make the camera focus on the midpoint of the screen.

// Called when PBJVision preview begins
func visionSessionDidStartPreview(vision: PBJVision) {
    // Focus screen at midpoint
    let focus_x = CGFloat(0.5)
    let focus_y = CGFloat(0.5)
}
Crashalot
  • 33,605
  • 61
  • 269
  • 439
  • Please post code of video capturing. It may help in imitation of your problem. – rkyr Jan 21 '16 at 10:17
  • We are using PBJVision to capture video, but will post the code here. Thanks again @rkyr! – Crashalot Jan 21 '16 at 10:50
  • @rkyr any suggestions Roma? Thanks again for your help! – Crashalot Jan 22 '16 at 20:03
  • Yes, few guesses I have. But I need try. I have troubles with my laptop. Tomorrow I'll try and let you know. I guess the problem actually in focus – rkyr Jan 22 '16 at 21:17
  • Assuming you can't work around blur at the beginning/end, can you start capturing earlier and discard that part? – Rhythmic Fistman Jan 22 '16 at 23:03
  • @RhythmicFistman thanks for the suggestion. What you suggest seems possible but is there a way of knowing at which frame the images become clear, i.e., at which frame does the blurriness stop? Otherwise, just blindly picking a frame doesn't seem to help the root issue of blurriness? – Crashalot Jan 22 '16 at 23:06
  • 1
    can you try using AVCaptureVideoStabilizationModeCinematic – oiledCode Jan 26 '16 at 10:24
  • @elio.d thanks but it didn't help. other suggestions? – Crashalot Jan 26 '16 at 10:51
  • @rkyr any suggestions Roma? Thanks again! – Crashalot Jan 28 '16 at 18:09
  • @Crashalot, no, sorry. It seems that NCIXGreg is right. Default Camera app can use different api level. You could try to open issue in PBJVision repo. – rkyr Jan 31 '16 at 09:50

2 Answers2

2

Video is blurry by its nature. 24 or 30 frames per second video will always have some blur in the shot because that's the way our eyes are tricked into believing the pictures are actually moving. The longer shutter speed allows the camera to give the impression of motion.

Photos use a much shorter shutter speed (1/60th of a second or less) to give a clear, still picture.

There's some info here on how to take a picture while recording video:

How to Programmatically Take Photos While Recording Video

Community
  • 1
  • 1
Greg
  • 533
  • 3
  • 14
  • In concept what you say makes sense, but there is something different about this capture code vs. the default camera app because the first frame or two is blurry 50% of the time if the camera isn't still enough whereas this doesn't occur with the default camera app. – Crashalot Jan 28 '16 at 07:45
2

I do not know about the PBJVision framework, but you could check the adjustingFocus of the AVCaptureDevice before extracting the picture you need.


Apparently, you can check the focusing status of the device by using PBJVision isAdjustingFocus method.

  • 1
    Thanks, we actually use its method to adjust focus before capturing video. Will update the question to reflect this. – Crashalot Jan 28 '16 at 18:07