AVFoundation, captureStillImageAsynchronouslyFromConnection시 셔터 소리를 끄는 방법은 무엇입니까?


90

AVFoundation captureStillImageAsynchronouslyFromConnection에 의해 카메라에서 라이브 미리보기 중에 이미지를 캡처하려고합니다 . 지금까지 프로그램은 예상대로 작동합니다. 그러나 어떻게 셔터 음을 음소거 할 수 있습니까?


5
예를 들어 일본에서는 그렇게 할 수 없습니다. 전화기를 음소거해도 셔터 소리가 항상 재생됩니다. (사생활 침해를 방지하기위한 이상한 규칙, 즉 업 스커트 사진은 내가 아는 한 일본에 있습니다) 그래서 그렇게 할 방법이 없다고 생각합니다.
Dunkelstern 2010

3
예, iPhone이 음소거 된 카메라 촬영을 허용하지 않을 수 있습니다. 저는 미국에 있고 전화기를 음소거 한 상태에서 사진을 찍을 때 iPhone에서 소리가 나지 않습니다. 반면에 내 여자 친구는 소리를 낸다 (한국 출신이다).
donkim

5
명확하게 말하면 이것은 전화가 음소거 / 진동 모드가 아닌 경우에 대한 솔루션입니다. 이 모드에서는 사진을 찍을 때 소리가 나지 않습니다.
New Alexandria

31
@NewAlexandria 진동 모드에서도 일본 셔터 소리가 들립니다. 이것은 법률 요건입니다.
k06a 2014 년

3
Btw AudioServicesPlaySystemSound는 장치가 음소거 된 경우 재생되지 않습니다. 비 음소거 그래서 일본어 장치는 여전히 음소거 할 때 소리가 아닌 것입니다 ...
필립 라 델릭

답변:


1500

이 코드를 한 번 사용하여 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];

그런 다음 타사 앱을 사용 photoShutter.caf하여 Documents 디렉토리 (Mac 용 DiskAid)에서 추출 했습니다. 다음 단계 photoShutter.caf는 Audacity 오디오 편집기에서 열고 반전 효과를 적용했습니다. 높은 확대 / 축소에서 다음과 같이 보입니다.

여기에 이미지 설명 입력

그런 다음이 사운드를로 저장 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


104
아주 멋지다. 주의 할 점은 flash가 켜져있을 때 captureStillImageAsynchronouslyFromConnection :이 호출 될 때 기본 시스템 사운드가 재생되지 않고 이미지가 실제로 캡처 될 때 (플래시 시퀀스 중에) 이중 셔터 사운드가 발생한다는 것입니다. 대신 keyPath 'capturingStillImage'에 대한 self.stillImageOutput에 키-값 관찰자를 추가하여 캡처가 실제로 시작되는시기를 감지 한 다음 콜백 메서드에서 역음을 재생합니다.
Jeff Mascia 2014 년

16
이것이 현대 군용기가 레이더를 물리 치는 방법입니다. 이것이 새로운 전투기 설계에서 "스텔스 모양"실루엣이 보이지 않는 이유입니다. "반전 된"(위상 편이) 중복 신호를 방송하는 기본적으로 레이더를 파괴하는 위상 편이를 처리하는 전자 패키지가 있습니다.
L0j1k

5
@ L0j1k : 그것은 당신이 말하는 스텔스 우주선의 종류에 달려 있습니다. F22 및 ilk는 탐지되지 않고 잠금 해제되는 데 관심이 없습니다. 위상 변이 기술의 문제는 다른 모든 위치에서 똑같은 변화를 보지 못하기 때문에 믿을 수 없을 정도로 분명하다는 것입니다.
Guvante 2014 년

13
실시간으로 사운드를 캡처하는 것을 제외하고는 소음 제거 헤드폰이 작동하는 방식입니다
Daniel Serodio 2014 년

4
이것은 iOS7에서 훌륭했지만 더 이상 iOS8에서 작동하지 않습니다 .iOS8에서이 문제를 해결하는 방법은 무엇입니까?
Ticko 2014 년

36

Swift의 내 솔루션

AVCapturePhotoOutput.capturePhoto아래 코드와 같이 이미지를 캡쳐하기 위해 메소드를 호출 할 때 .

photoOutput.capturePhoto(with: self.capturePhotoSettings, delegate: self)

AVCapturePhotoCaptureDelegate 메서드가 호출됩니다. 그리고 시스템은 willCapturePhotoFor호출 된 후 셔터 소리를 재생하려고합니다 . 따라서 시스템 사운드를 willCapturePhotoFor방법으로 처리 할 수 ​​있습니다 .

여기에 이미지 설명 입력

extension PhotoCaptureService: AVCapturePhotoCaptureDelegate {

    func photoOutput(_ output: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
        // dispose system shutter sound
        AudioServicesDisposeSystemSoundID(1108)
    }
}

또한보십시오


3
이것은 아름다운 솔루션이며 완벽하게 작동합니다. 너무 좋은 대답입니다. 감사합니다 @kyle
Warpling

1
이것은 완벽하게 작동합니다. 무음 모드와 일반 모드를 분리해야하는 경우 AudioServicesPlaySytemSoundID (1108)를 반대로 사용하십시오. 감사합니다.
MJ Studio

1
효과가있다! 그런 방법으로 AppStore에 업로드하는 데 문제가 있는지 알고 싶습니다.
Liew Jun Tung

2
@LiewJunTung이 솔루션에는 문제가 없습니다. 이 솔루션으로 이미 앱을 업로드했습니다. 이런 종류의 솔루션을 사용한 앱이 많이 있습니다. 즐거운 코딩입니다.
승리

문제를 발견했습니다. 이 문제를 발견했는지 궁금합니다. 기본적으로를 AudioServicesDisposeSystemSoundID(1108)호출 할 때만 발생하는 메모리 누수입니다 . 이에 대한 해결책이 있습니까? :)
Liew 6월 퉁

21

방법 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);

필요한 경우 여기에 빈 오디오 파일이 있습니다. https://d1sz9tkli0lfjq.cloudfront.net/items/0Y3Z0A1j1H2r1c0z3n3t/blank.wav

________________________________________________________________________________________________________________________________________

방법 2 : 이것이 작동하지 않는 경우 대안이 있습니다. 좋은 해상도가 필요하지 않은 한 비디오 스트림에서 프레임을 가져 와서 사진 소리를 완전히 피할 수 있습니다.

________________________________________________________________________________________________________________________________________

방법 3 : 이 작업을 수행하는 또 다른 방법은 응용 프로그램의 "스크린 샷"을 찍는 것입니다. 다음과 같이하십시오.

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];

2
나는 그것이 작동하지 않을 것이라고 생각한다. 그것은 단지 셔터 소음이 재생되는 동안 "빈"소리를 낼 것이다. 동시에 2 개의 사운드를 재생할 수 있습니다. 다른 두 가지 방법은 실행 가능해 보입니다!
Linuxmint 2010

2
한번 시도해보세요. 나는 그것이 효과가있을 것이라고 확신하지 않지만, 여기에 희망이있다!
sudo rm -rf

7

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];

앱이 돌아 오면 멋지게 꾸미고 음소거를 해제하세요!


5

저는 일본에 살고 있기 때문에 보안상의 이유로 사진을 찍을 때 오디오를 음소거 할 수 없습니다. 그러나 비디오에서는 오디오가 꺼집니다. 이유를 모르겠습니다.

셔터 소리없이 사진을 찍는 유일한 방법은 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)를 설정할 때 매우 무겁습니다. // 초당 1 프레임.

WWDC 2010 샘플 코드 FindMyiCone에서 다음 코드를 찾았습니다.

[output setAlwaysDiscardsLateVideoFrames:YES];

이 API를 사용하면 타이밍이 부여되지 않고 순차적으로 API가 호출됩니다. 나는 이것이 최고의 솔루션입니다.


3

비디오 스트림에서 프레임을 가져와 전체 해상도가 아닌 이미지를 캡처 할 수도 있습니다.

짧은 간격으로 이미지를 캡처 하는 데 사용 됩니다 .

- (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;
}

AVCaptureMovieFileOutput을 사용하는 동안 AVCaptureVideoDataOutput이 작동하도록 할 수 있습니까? 둘 다 사용하려고하면 AVCaptureVideoDataOutput의 대리자 메서드가 호출되지 않습니다.
Paul Cezanne

동시에 두 개 이상의 출력을 시도하지 않아서 죄송합니다.
Rivera


0

내가 생각할 수있는 유일한 해결 방법은 "사진 찍기"버튼을 누를 때 아이폰 사운드를 음소거 한 다음 잠시 후에 음소거를 해제하는 것입니다.


프로그래밍 방식으로 iPhone 사운드를 음소거하는 방법은 무엇입니까? 감사!
ohho 2010

당신은 애플이 승인하지 않을 수있는 경우에도

0

이러한 경우 일반적인 트릭은 프레임 워크가이 이벤트에 대해 특정 메서드를 호출하는지 확인한 다음 해당 메서드를 일시적으로 덮어 써서 그 효과를 무효화하는 것입니다.

죄송하지만이 경우에 작동하는지 즉시 알려줄 수있는 해킹이 아닙니다. 프레임 워크 실행 파일에서 "nm"명령을 사용하여 적합한 이름을 가진 명명 된 함수가 있는지 확인하거나 시뮬레이터와 함께 gdb를 사용하여 이동 위치를 추적 할 수 있습니다.

무엇을 덮어 쓸지 알면 함수 조회를 리디렉션하는 데 사용할 수있는 저수준 ObjC 디스패치 함수가 있다고 생각합니다. 예전에 해본 것 같은데 세부 사항이 기억 나지 않습니다.

바라건대, 내 힌트를 사용하여 이에 대한 몇 가지 솔루션 경로를 Google에 알릴 수 있습니다. 행운을 빕니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.