Я пытаюсь захватить изображение во время предварительного просмотра с камеры с помощью AVFoundation captureStillImageAsynchronouslyFrom. Пока программа работает как положено. Однако как я могу отключить звук срабатывания затвора?
AVFoundation, как отключить звук затвора при captureStillImageAsynchronouslyFromConnection?
Ответы (9)
Я однажды использовал этот код, чтобы записать звук затвора 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
из каталога документов (DiskAid для 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:
...
И это действительно работает! Я запускаю тест несколько раз, каждый раз не слышу звука срабатывания затвора :)
Вы можете получить уже инвертированный звук, записанный на iPhone 5S iOS 7.1.1 по этой ссылке: https://www.dropbox.com/s/1echsi6ivbb85bv/photoShutter2.caf
if let soundURL = NSBundle.mainBundle().URLForResource("photoShutter2", withExtension: "caf") { var mySound: SystemSoundID = 0 AudioServicesCreateSystemSoundID(soundURL, &mySound) AudioServicesPlaySystemSound(mySound); }
- person Sam; 28.10.2015
captureStillImageAsynchronouslyFromConnection:
метода. Не уверен, что этот метод будет работать на всех версиях iOS, потому что он требует очень высокой точности синхронизации воспроизведения звука и захвата изображения ...
- person k06a; 17.05.2017
photoOutput(:willCapturePhotoFor:)
. Также это работает на iOS 11.3.1, созданной с Xcode 9.3.1
- person silicon_valley; 26.05.2018
photoOutput(:willCapturePhotoFor:)
, как @silicon_valley, предложенный в предыдущем комментарии, похоже, это работает для него даже в 11.3.1.
- person k06a; 04.07.2018
Мое решение в 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)
}
}
Смотрите также
AudioServicesDisposeSystemSoundID(1108)
. У вас есть какие-то решения для этого? :)
- person Liew Jun Tung; 12.12.2019
photoOutput
до тех пор, пока не будет воспроизведена часть звука срабатывания затвора.
- person Edward Brey; 01.10.2020
Метод 1. Не уверен, что это сработает, но попробуйте воспроизвести пустой аудиофайл прямо перед отправкой события захвата.
Чтобы воспроизвести клип, добавьте Audio Toolbox
framework, #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/items1/0Y2 >
________________________________________________________________________________________________________________________________________
Метод 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. Я также подтвердил, что 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];
Просто не забудьте быть вежливым и включить звук, когда ваше приложение вернется!
Я живу в Японии, поэтому из соображений безопасности я не могу отключить звук, когда мы делаем фотографии. Однако в видео звук отключается. Не понимаю почему.
Единственный способ сделать снимок без звука срабатывания затвора - использовать 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 вызывается последовательно. Я это лучшее решение.
Вы также можете взять кадр из видеопотока, чтобы захватить изображение (не в полном разрешении).
См. Этот пост для другого ответа: Захват изображения из буфера изображений. Не удается сделать снимок экрана во время предварительного просмотра видео
Единственный возможный обходной путь, о котором я могу думать, - это отключить звук iphone, когда они нажимают кнопку «сделать снимок», а затем включить его через секунду.
Распространенный прием в таких случаях - выяснить, вызывает ли фреймворк определенный метод для этого события, а затем временно перезаписать этот метод, тем самым аннулируя его эффект.
Мне очень жаль, но я недостаточно хорош, чтобы сразу сказать вам, работает ли это в данном случае. Вы можете попробовать команду «nm» в исполняемых файлах фреймворка, чтобы увидеть, есть ли именованная функция с подходящим именем, или использовать gdb с симулятором, чтобы отследить, куда она идет.
Я полагаю, что когда вы знаете, что перезаписывать, есть те низкоуровневые диспетчерские функции ObjC, которые вы можете использовать для перенаправления поиска функций. Я думаю, что делал это некоторое время назад, но не могу вспомнить детали.
Надеюсь, вы сможете использовать мои подсказки, чтобы найти в Google несколько путей решения этой проблемы. Удачи.