我正在尝试通过AVFoundation captureStillImageAsynchronouslyFromConnection从相机进行实时预览期间捕获图像。到目前为止,该程序可以按预期工作。但是,如何使快门声静音?
我正在尝试通过AVFoundation captureStillImageAsynchronouslyFromConnection从相机进行实时预览期间捕获图像。到目前为止,该程序可以按预期工作。但是,如何使快门声静音?
Answers:
我曾经使用此代码捕获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
从“文档”目录(适用于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
当您调用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)
}
}
AudioServicesDisposeSystemSoundID(1108)
调用时发生。您对此有什么解决方案吗?:)
方法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];
我可以通过在snapStillImage函数中使用此代码来使其正常工作,并且它在iOS 8.3 iPhone 5上对我而言非常理想。矿)
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];
请记住要保持友善,并在应用返回时取消静音!
我住在日本,因此出于安全考虑,我在拍照时无法使音频静音。在视频中,但是音频关闭。我不明白为什么。
我拍摄没有快门声的照片的唯一方法是使用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。我这是最好的解决方案。
您还可以从视频流中获取一帧以捕获(非全分辨率)图像。
它是用来在这里以短的时间间隔拍摄图像:
- (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;
}
请参阅此帖子以获取不同类型的答案:从图像缓冲区捕获图像。 视频预览期间的屏幕捕获失败