首页 文章

AVFoundation,如何在captureStillImageAsynchronouslyFromConnection时关闭快门声音?

提问于
浏览
76

我试图通过AVFoundation captureStillImageAsynchronouslyFromConnection在相机的实时预览中捕捉图像 . 到目前为止,该计划按预期工作 . 但是,如何将快门声静音?

8 回答

  • 2

    我使用此代码一次捕获iOS默认快门声音(这里是声音文件名列表https://github.com/TUNER88/iOSSystemSoundsLibrary):

    NSString *path = @"/System/Library/Audio/UISounds/photoShutter.caf";
    NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSData *data = [NSData dataWithContentsOfFile:path];
    [data writeToFile:[docs stringByAppendingPathComponent:@"photoShutter.caf"] atomically:YES];
    

    然后我使用第三方应用程序从Documents目录(DiskAid for Mac)中提取 photoShutter.caf . 下一步我在Audacity音频编辑器中打开 photoShutter.caf 并应用了反转效果,它在高变焦时看起来像这样:

    enter image description here

    然后我把这个声音保存为 photoShutter2.caf 并试图在 captureStillImageAsynchronouslyFromConnection 之前播放这个声音:

    static SystemSoundID soundID = 0;
    if (soundID == 0) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"photoShutter2" ofType:@"caf"];
        NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)filePath, &soundID);
    }
    AudioServicesPlaySystemSound(soundID);
    
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:
    ...
    

    这确实有效!每次听到没有快门声时我都会跑几次测试:)

    您可以通过以下链接获取已在iPhone 5S iOS 7.1.1上捕获的已反转声音:https://www.dropbox.com/s/1echsi6ivbb85bv/photoShutter2.caf

  • 2

    Method 1: 不确定这是否有效,但在发送捕获事件之前尝试播放空白音频文件 .

    要播放剪辑,请在拍摄前立即添加 Audio Toolbox 框架, #include <AudioToolbox/AudioToolbox.h> 并播放如下所示的音频文件:

    NSString *path = [[NSBundle mainBundle] pathForResource:@"blank" ofType:@"wav"];
     SystemSoundID soundID;
     NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
     AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
     AudioServicesPlaySystemSound(soundID);
    

    如果需要,这是一个空白的音频文件 . http://cl.ly/3cKi

    ________________________________________________________________________________________________________________________________________

    Method 2: 有's also an alternative if this doesn'工作 . 只要你不需要一个好的分辨率,你就可以grab a frame from the video stream,从而完全避免画面声音 .

    ________________________________________________________________________________________________________________________________________

    Method 3: 另一种方法是使用"screenshot"的应用程序 . 这样做:

    UIGraphicsBeginImageContext(self.window.bounds.size);
    [self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    NSData * data = UIImagePNGRepresentation(image);
    [data writeToFile:@"foo.png" atomically:YES];
    

    如果您希望通过预览视频流来填充整个屏幕,以便您的屏幕截图看起来很好:

    AVCaptureSession *captureSession = yourcapturesession;
    AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
    UIView *aView = theViewYouWantTheLayerIn;
    previewLayer.frame = aView.bounds; // Assume you want the preview layer to fill the view.
    [aView.layer addSublayer:previewLayer];
    
  • 19

    我可以通过在snapStillImage函数中使用此代码来实现此功能,并且它在iOS 8.3 iPhone 5上完美适用于我 . 我还确认,如果您使用此功能,Apple将不会拒绝您的应用程序(他们不会拒绝矿)

    MPVolumeView* volumeView = [[MPVolumeView alloc] init];
    //find the volumeSlider
    UISlider* volumeViewSlider = nil;
    for (UIView *view in [volumeView subviews]){
        if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
            volumeViewSlider = (UISlider*)view;
            break;
        }
    }
    // mute it here:
    [volumeViewSlider setValue:0.0f animated:YES];
    [volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
    

    当你的应用程序返回时,请记住保持良好并取消静音!

  • 6

    我住在日本,因此出于安全原因我拍摄照片时无法将音频静音 . 在视频中,音频会关闭 . 我不明白为什么 .

    我拍摄没有快门声的照片的唯一方法是使用AVCaptureVideoDataOutput或AVCaptureMovieFileOutput . 对于分析静止图像AVCaptureVideoDataOutput是唯一的方法 . 在AVFoundatation示例代码中,

    AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
    // If you wish to cap the frame rate to a known value, such as 15 fps, set 
    // minFrameDuration.
    output.minFrameDuration = CMTimeMake(1, 15);
    

    在我的3GS中,当我设置CMTimeMake(1,1)时它非常重; //每秒一帧

    在WWDC 2010示例代码FindMyiCone中,我找到了以下代码,

    [output setAlwaysDiscardsLateVideoFrames:YES];
    

    使用此API时,不会授予计时,但会按顺序调用API . 我这是最好的解决方案 .

  • 0

    您还可以从视频流中获取帧以捕获(非全分辨率)图像 .

    使用here以短间隔捕获图像:

    - (IBAction)startStopPictureSequence:(id)sender
    {
        if (!_capturingSequence)
        {
            if (!_captureVideoDataOutput)
            {
                _captureVideoDataOutput = [AVCaptureVideoDataOutput new];
                _captureVideoDataOutput.videoSettings = @{(NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)};
                [_captureVideoDataOutput setSampleBufferDelegate:self
                                                           queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)];
                if (_sequenceCaptureInterval == 0)
                {
                    _sequenceCaptureInterval = 0.25;
                }
            }
    
            if ([_captureSession canAddOutput:_captureVideoDataOutput])
            {
                [_captureSession addOutput:_captureVideoDataOutput];
                _lastSequenceCaptureDate = [NSDate date]; // Skip the first image which looks to dark for some reason
                _sequenceCaptureOrientation = (_currentDevice.position == AVCaptureDevicePositionFront ? // Set the output orientation only once per sequence
                                               UIImageOrientationLeftMirrored :
                                               UIImageOrientationRight);
                _capturingSequence = YES;
            }
            else
            {
                NBULogError(@"Can't capture picture sequences here!");
                return;
            }
        }
        else
        {
            [_captureSession removeOutput:_captureVideoDataOutput];
            _capturingSequence = NO;
        }
    }
    
    - (void)captureOutput:(AVCaptureOutput *)captureOutput
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
           fromConnection:(AVCaptureConnection *)connection
    {
        // Skip capture?
        if ([[NSDate date] timeIntervalSinceDate:_lastSequenceCaptureDate] < _sequenceCaptureInterval)
            return;
    
        _lastSequenceCaptureDate = [NSDate date];
    
        UIImage * image = [self imageFromSampleBuffer:sampleBuffer];
        NBULogInfo(@"Captured image: %@ of size: %@ orientation: %@",
                   image, NSStringFromCGSize(image.size), @(image.imageOrientation));
    
        // Execute capture block
        dispatch_async(dispatch_get_main_queue(), ^
                       {
                           if (_captureResultBlock) _captureResultBlock(image, nil);
                       });
    }
    
    - (BOOL)isRecording
    {
        return _captureMovieOutput.recording;
    }
    
  • 1486

    有关其他类型的答案,请参阅此文章:从图像缓冲区中捕获图像 . Screen capture during video preview fails

  • 0

    我能想到的唯一可能的解决方法是在按下“拍照”按钮时静音iphone声音,然后在一秒钟之后取消静音 .

  • 4

    在这种情况下,一个常见的技巧是找出框架是否为此事件调用某种方法,然后暂时覆盖该方法,从而消除其影响 .

    我很抱歉,但如果在这种情况下有效,我就不会立即告诉你 . 您可以在框架可执行文件上尝试“nm”命令,看看是否有一个具有适合名称的命名函数,或者使用gdb与Simulator一起跟踪它的去向 .

    一旦你知道要覆盖什么,我相信有一些低级别的ObjC调度函数可以用来重定向函数的查找 . 我想我刚刚做过这件事,但不记得细节了 .

    希望您可以使用我的提示谷歌一些解决方案路径 . 祝好运 .

相关问题