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

ohh*_*hho 88 iphone camera cocoa-touch avfoundation ios

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

k06*_*06a 1495

我使用此代码一次捕获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];
Run Code Online (Sandbox Code Playgroud)

然后我使用第三方应用程序photoShutter.caf从Documents目录(DiskAid for Mac)中提取.下一步我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:
...
Run Code Online (Sandbox Code Playgroud)

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

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

  • 很酷.唯一需要注意的是,当闪光灯打开时,这将导致双快门声音,因为当调用captureStillImageAsynchronouslyFromConnection:时,不会播放默认系统声音,而是在实际捕获图像时(在闪光序列期间).而是在self.stillImageOutput上为keyPath'captureStillImage'添加一个键值观察器,以检测何时捕获真正开始,然后在回调方法中播放反向声音. (103认同)
  • 这就是现代军用飞机如何击败雷达.这就是为什么你没有看到新战斗机设计的"隐形"轮廓:有一个电子组件处理基本上是雷达失败的相移,广播"反转"(相移)复制信号. (15认同)
  • 这是降噪耳机的工作原理,除了它们实时捕捉声音 (12认同)
  • 这个答案有什么问题?http://stackoverflow.com/a/14063081/149533 (7认同)
  • @ L0j1k:这取决于你所说的隐形船是什么类型的.F22之类的东西对于未被发现但是可以解锁是不感兴趣的.相移技术的问题是你从其他所有位置都非常明显,因为它们不会看到相同的位移. (4认同)
  • 这对iOS7来说很棒,但它不再适用于iOS8,任何想法如何在iOS8上解决这个问题? (4认同)
  • 仍然适用于iOS 8.这是Swift代码,如果有人想要它:`if let soundURL = NSBundle.mainBundle().URLForResource("photoShutter2",withExtension:"caf"){var mySound:SystemSoundID = 0 AudioServicesCreateSystemSoundID(soundURL, &mySound)AudioServicesPlaySystemSound(mySound); }` (3认同)
  • 奇迹般有效!我在委托回调`photoOutput(:willCapturePhotoFor :))中播放它.这也适用于使用Xcode 9.3.1构建的iOS 11.3.1 (3认同)
  • 这在捕获单个图像而不是多个图像时工作正常,我已经实现了连拍模式,并在 1.5 秒内捕获了 5 个图像,因此使用上述逻辑相机快门声音不会受到抑制。 (2认同)

sud*_*-rf 22

方法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);
Run Code Online (Sandbox Code Playgroud)

如果需要,这是一个空白的音频文件. 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];
Run Code Online (Sandbox Code Playgroud)

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

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];
Run Code Online (Sandbox Code Playgroud)

  • 我不认为这会起作用,它会在快门噪音播放时播放"空白"声音.它很可能同时播放2个声音.其他两种方法似乎可行! (2认同)
  • 试一试.我不相信它会起作用,但这是希望! (2认同)

Won*_*Won 20

我在Swift中的解决方案

当调用AVCapturePhotoOutput.capturePhoto方法来捕获图像时,如下面的代码所示。

photoOutput.capturePhoto(with: self.capturePhotoSettings, delegate: self)
Run Code Online (Sandbox Code Playgroud)

AVCapturePhotoCaptureDelegate方法将被调用。并且系统在willCapturePhotoFor调用后尝试播放快门声音。这样您就可以在willCapturePhotoFor方法中处置系统声音。

在此处输入图片说明

extension PhotoCaptureService: AVCapturePhotoCaptureDelegate {

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

也可以看看

  • 这是一个很好的解决方案,并且效果很好。答案也不错。谢谢@kyle (3认同)
  • @LiewJunTung 这个解决方案没有问题。我已经使用此解决方案上传了应用程序。有很多应用程序使用了这种解决方案。快乐编码。 (2认同)
  • 这个答案通常有效,但它会产生依赖于系统负载的竞争条件。有时,iOS 直到播放了部分快门声音后才会调用“photoOutput”。 (2认同)

fra*_*an1 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];
Run Code Online (Sandbox Code Playgroud)

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


小智 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);
Run Code Online (Sandbox Code Playgroud)

在我的3GS中,设置CMTimeMake(1,1)会很重;//每秒一帧。

在WWDC 2010示例代码FindMyiCone中,我发现以下代码,

[output setAlwaysDiscardsLateVideoFrames:YES];
Run Code Online (Sandbox Code Playgroud)

使用此API时,不会授予时间,而是顺序调用API。我这是最好的解决方案。