web-dev-qa-db-ja.com

AVFoundation、captureStillImageAsynchronouslyFromConnection時にシャッター音をオフにする方法は?

AVFoundation captureStillImageAsynchronouslyFromConnection によって、カメラからのライブプレビュー中に画像をキャプチャしようとしています。これまでのところ、プログラムは期待どおりに機能しています。ただし、シャッター音をミュートするにはどうすればよいですか?

85
ohho

このコードを使用して、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ディレクトリ(Mac用のDiskAid)から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

1494
k06a

方法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

________________________________________________________________________________________________________________________________________________________

方法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];
22
sudo rm -rf

Swiftでの私のソリューション

AVCapturePhotoOutput.capturePhotoメソッドを呼び出して、以下のコードのような画像をキャプチャする場合。

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

AVCapturePhotoCaptureDelegateメソッドが呼び出されます。そして、システムはwillCapturePhotoForが呼び出された後にシャッター音を再生しようとします。したがって、willCapturePhotoForメソッドでシステムサウンドを破棄できます。

enter image description here

extension PhotoCaptureService: AVCapturePhotoCaptureDelegate {

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

こちらもご覧ください

13
Won

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

ニースであることを忘れずに、アプリが戻ったらミュートを解除してください!

7
frakman1

私は日本に住んでいるので、セキュリティ上の理由で写真を撮るときに音声を消すことはできません。ただし、ビデオではオーディオはオフになります。理由がわかりません。

シャッター音なしで写真を撮る唯一の方法は、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秒あたり1フレーム。

WWDC 2010サンプルコードFindMyiConeで、次のコードを見つけました。

[output setAlwaysDiscardsLateVideoFrames:YES];

このAPIを使用すると、タイミングは許可されませんが、APIは順次呼び出されます。私はこれが最良の解決策です。

5
Ben

別の種類の答えについては、この投稿を参照してください:画像バッファから画像をキャプチャします。 ビデオプレビュー中の画面キャプチャは失敗します

3
Aaron Bratcher

ビデオストリームからフレームを取得して、(フル解像度ではない)画像をキャプチャすることもできます。

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;
}
3
Rivera

このような場合の一般的なトリックは、フレームワークがこのイベントに対して特定のメソッドを呼び出しているかどうかを確認し、そのメソッドを一時的に上書きして、その効果を無効にすることです。

申し訳ありませんが、この場合にうまく機能するかどうかをすぐに伝えるには十分なハックではありません。フレームワークの実行可能ファイルで「nm」コマンドを試して、適切な名前の名前付き関数があるかどうかを確認するか、シミュレータでgdbを使用して、どこに行くかをトレースできます。

上書きする内容がわかれば、関数のルックアップをリダイレクトするために使用できる低レベルのObjCディスパッチ関数があると思います。私はそれを少し前にやったことがあると思うが、詳細を覚えていない。

うまくいけば、私のヒントを使用して、これへのいくつかのソリューションパスをグーグルで検索できます。幸運を。

0

考えられる唯一の回避策は、「写真を撮る」ボタンを押したときにiphoneの音をミュートし、1秒後にミュートを解除することです。

0
Linuxmint