AVFoundation, как отключить звук затвора при captureStillImageAsynchronouslyFromConnection?

Я пытаюсь захватить изображение во время предварительного просмотра с камеры с помощью AVFoundation captureStillImageAsynchronouslyFrom. Пока программа работает как положено. Однако как я могу отключить звук срабатывания затвора?


person ohho    schedule 09.12.2010    source источник
comment
Я не думаю, что это возможно. Даже если этого не должно быть. Для этого могут возникнуть проблемы с нарушением конфиденциальности пользователей.   -  person nacho4d    schedule 09.12.2010
comment
Каковы проблемы нарушения конфиденциальности пользователей? Теперь пользователь может в любой момент отключить звук срабатывания затвора с помощью аппаратного выключателя звука. Мне нужен способ выключить звук независимо от настройки аппаратного выключателя звука.   -  person ohho    schedule 10.12.2010
comment
Например, в Японии вы не можете этого сделать. Там звук срабатывания затвора всегда играет, даже если вы отключили звук в телефоне. (Насколько мне известно, в Японии действуют некоторые странные правила для предотвращения нарушения конфиденциальности, также известные как фотография под юбкой). Так что я не думаю, что есть способ сделать это.   -  person Dunkelstern    schedule 16.12.2010
comment
Да, возможно, ваш iPhone не позволяет делать снимки с камеры с отключенным звуком. Я нахожусь в США, и мой iPhone не издает звука, когда я делаю снимок с отключенным телефоном; с другой стороны, моя девушка издает звук (ее девушка из Кореи).   -  person donkim    schedule 18.12.2010
comment
Чтобы быть ясным, это решение, когда телефон не отключен / не вибрирует. В этом режиме во время фотосъемки звук не издается.   -  person New Alexandria    schedule 23.05.2014
comment
@NewAlexandria Я слышал в Японии звуки затвора и в режиме вибрации. Это требование закона.   -  person k06a    schedule 23.05.2014
comment
Btw AudioServicesPlaySystemSound не будет воспроизводиться, если устройство отключено. Таким образом, японские устройства по-прежнему будут издавать звук при отключении звука, но не при отключении звука ...   -  person Filip Radelic    schedule 24.05.2014


Ответы (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

person k06a    schedule 20.05.2014
comment
Классный хак! Интересно, можно ли использовать этот трюк для подавления звука UIPickerView, который нельзя отключить через общедоступный API: stackoverflow.com/ q / 1441849/214070 - person bugloaf; 23.05.2014
comment
Очень круто. Единственное предостережение в том, что при включении вспышки это приведет к звуку двойного затвора, потому что системный звук по умолчанию не воспроизводится при вызове captureStillImageAsynchronouslyFromConnection:, а при фактическом захвате изображения (во время последовательности вспышки). Вместо этого добавьте в self.stillImageOutput наблюдателя «ключ-значение» для keyPath 'capturingStillImage', чтобы определить, когда действительно начинается захват, а затем воспроизвести обратный звук в методе обратного вызова. - person Jeff Mascia; 24.05.2014
comment
Так современные военные самолеты побеждают радар. Вот почему вы не видите силуэт невидимой формы на новых конструкциях истребителей: есть пакет электроники, который обрабатывает то, что в основном является нарушением фазового сдвига, которое передает инвертированный (сдвинутый по фазе) дублированный сигнал. - person L0j1k; 24.05.2014
comment
@ L0j1k: Это зависит от того, о каком корабле-невидимке вы говорите. F22 и иже с ним не заинтересованы в том, чтобы их не обнаружили, а в том, чтобы их можно было разблокировать. Проблема с технологией фазового сдвига в том, что вы невероятно заметны из любой другой позиции, поскольку они не увидят такой же сдвиг. - person Guvante; 24.05.2014
comment
Вот как работают наушники с шумоподавлением, за исключением того, что они улавливают звук в реальном времени. - person Daniel Serodio; 24.05.2014
comment
Мне интересно, как это обеспечивает точное перекрытие двух волн. AFAIK, даже если это один сэмпл, отмена не будет идеальной. - person notthetup; 02.06.2014
comment
Это, вероятно, будет хорошим способом получить отказ в магазине приложений, как только Apple поймет это. - person nobody; 09.06.2014
comment
Это было здорово для iOS7, но это больше не работает на iOS8, есть идеи, как решить эту проблему на iOS8? - person Ticko; 28.10.2014
comment
@ kO6a: да, не работает на устройствах iOS8. Пожалуйста, дайте какое-нибудь решение. - person V-Xtreme; 18.11.2014
comment
@Ticko, вы использовали прикрепленный аудиофайл из моего Dropbox или инвертировали свой собственный? iOS8, возможно, изменил звук и / или случайный сон перед звуком срабатывания затвора ... - person k06a; 19.11.2014
comment
Это отлично работает при захвате одного изображения, а не для нескольких, я реализовал режим серийной съемки и захват 5 изображений в течение 1,5 секунд, поэтому при использовании вышеупомянутой логики звук затвора камеры не подавляется. - person iLearner; 20.05.2015
comment
По-прежнему работает на iOS 8. Это код Swift, если он кому-то нужен: if let soundURL = NSBundle.mainBundle().URLForResource("photoShutter2", withExtension: "caf") { var mySound: SystemSoundID = 0 AudioServicesCreateSystemSoundID(soundURL, &mySound) AudioServicesPlaySystemSound(mySound); } - person Sam; 28.10.2015
comment
Что, если Apple изменит звук? - person Albert Renshaw; 22.04.2016
comment
@iLearner Если вам нужно отключить звук при съемке фотографий BURST, вы можете сделать это с небольшой потерей качества, используя этот метод: stackoverflow.com/a/9672242/2057171 ——— Я отредактировал это в вопросе для будущих читателей O :) - person Albert Renshaw; 22.04.2016
comment
@AlbertRenshaw вы добавили ссылку на этот ответ с решением, которое вы можете найти где угодно: просто захват кадров из видео. Извините, я удалил эту ссылку из ответа - я думаю, что это решение достаточно популярно, чтобы его можно было найти в Google или SO. - person k06a; 23.04.2016
comment
@AlbertRenshaw Вы можете записывать и инвертировать несколько звуков, а также использовать конкретный звук для конкретной версии iOS. iOS7, iOS8, iOS9 имеют одинаковый звук :) - person k06a; 23.04.2016
comment
Да, но если Apple изменит звук, скажем, в iOS 10, это может быть плохо для приложений, захватывающих, скажем, 60 кадров в секунду, со звуком срабатывания затвора, срабатывающим 60 раз в секунду, а также инверсией старого звука, также срабатывающим 60 раз в секунду. @ k06a - person Albert Renshaw; 24.04.2016
comment
@AlbertRenshaw, конечно, но у разработчиков приложений будет 3-5 месяцев, чтобы адаптировать свои приложения к новой версии iOS. Надеюсь, он будет называться iOS X :) - person k06a; 24.04.2016
comment
Этот ответ просто не соответствует действительности. Пробовал с iOS 9.3 и iPhone 6+, не работает. - person raven99; 10.05.2016
comment
@ raven99 Apple может изменить звук в любой будущей версии iOS. Любая задержка в 5 мс при воспроизведении звука может разрушить все волшебство. Думаю, этот метод не готов к производству. Это об обмане и веселье :) - person k06a; 10.05.2016
comment
@ k06a Я использую методы AVCapturePhotoCaptureDelegate, в каком методе мне следует поместить этот код, чтобы отключить звук срабатывания затвора? Я попытался добавить этот код в метод didCapturePhotoForResolvedSettings, но он не работает. любая помощь? - person Satish Mavani; 17.05.2017
comment
@SatishMavani Я написал это прямо перед вызовом captureStillImageAsynchronouslyFromConnection: метода. Не уверен, что этот метод будет работать на всех версиях iOS, потому что он требует очень высокой точности синхронизации воспроизведения звука и захвата изображения ... - person k06a; 17.05.2017
comment
@ k06a captureStillImageAsynchronouslyFromConnection: сейчас устарел, и я не могу найти такого метода с помощью AVCapturePhotoCaptureDelegate, вы можете помочь с каким-либо другим решением? - person Satish Mavani; 17.05.2017
comment
В XCode 9.3 с использованием AVCapturePhotoCaptureDelegate это не работает. В документации photoOutput (: willCapturePhotoFor :) говорится, что вывод фотографий вызывает этот метод как можно ближе к начальному моменту захвата. Если включен звук срабатывания затвора, этот вызов происходит сразу после того, как при выводе фотографий начинает воспроизводиться звук срабатывания затвора. И этот метод, и метод photoOutput (: willBeginCaptureFor :) не совпадают с событием начала звука затвора. - person Glavid; 18.04.2018
comment
@Glavid офигенно, через 4 года наконец сделали защиту от этой уловки. - person k06a; 19.04.2018
comment
Работает как шарм! Я играю это в обратном вызове делегата photoOutput(:willCapturePhotoFor:). Также это работает на iOS 11.3.1, созданной с Xcode 9.3.1 - person silicon_valley; 26.05.2018
comment
Не работает у меня на iOS 11.1 ... На самом деле, я пытаюсь добиться этого в AVCaptureMetadataOutputObjectsDelegate, поскольку мое требование - когда сканирование будет выполнено, мне нужно сделать снимок отсканированного штрих-кода. Не могли бы вы помочь мне, как я могу достичь вышеупомянутой функции. - person iGW; 03.07.2018
comment
@iGW пытается сделать это в photoOutput(:willCapturePhotoFor:), как @silicon_valley, предложенный в предыдущем комментарии, похоже, это работает для него даже в 11.3.1. - person k06a; 04.07.2018
comment
Я применил решение, предложенное @silicon_valley, и при многократном нажатии значка камеры 1-2 из 10 давал звук срабатывания затвора. Также в соответствии с моими требованиями, как я уже упоминал в своем предыдущем комментарии, что: - При получении результата штрих-кода внутри - didOutputMetadataObjects мне просто нужно одновременно щелкнуть фотографию отсканированного штрих-кода и сохранить этот результат вместе с изображением в основных данных. - person iGW; 06.07.2018
comment
В настоящее время я читаю штрих-код с помощью AVCaptureMetadataOutputObjectsDelegate и использую метод captureStillImageAsynchronously для захвата изображения внутри этого делегата. Надеюсь, я смогу правильно объяснить свое требование. - person iGW; 06.07.2018
comment
Этот метод действительно работает. Однако необходимо обратить внимание на следующие моменты. - Воспроизведение звука срабатывания затвора, даже когда устройство отключено или подключено к наушникам - Звук затвора воспроизводится точно в то же время, что и настоящий звук срабатывания затвора - person shtnkgm; 11.11.2018
comment
@Glavid Мне удалось заставить его работать на iPhone 10, добавив небольшую задержку (0,02 секунды), когда я проигрываю звук, делая это так, как будто это работает для меня - person Quinn; 06.03.2019
comment
Поцарапайте мой предыдущий комментарий, он работает как 99% времени с задержкой, но иногда звук будет :( - person Quinn; 06.03.2019

Мое решение в 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)
    }
}

Смотрите также

person Won    schedule 19.03.2019
comment
Это красивое решение, и оно отлично работает. Тоже отличный ответ. Спасибо @kyle - person Warpling; 22.03.2019
comment
Это прекрасно работает. Если вам нужно разделить беззвучный режим и нормальный режим, используйте AudioServicesPlaySytemSoundID (1108) наоборот. Спасибо. - person MJ Studio; 10.04.2019
comment
Оно работает! Я хочу знать, есть ли у вас проблемы с загрузкой в ​​AppStore таким методом? - person Liew Jun Tung; 22.11.2019
comment
@LiewJunTung Нет проблем с этим решением. Я уже загрузил приложения с этим решением. Есть много приложений, которые используют такое решение. Удачного кодирования. - person Won; 23.11.2019
comment
Я обнаружил проблему. Мне интересно, обнаружили ли вы эту проблему. По сути, это утечка памяти, которая происходит только при вызове AudioServicesDisposeSystemSoundID(1108). У вас есть какие-то решения для этого? :) - person Liew Jun Tung; 12.12.2019
comment
Вам не нужно отделять тихий режим от обычного @MJStudio. Установите для категории AVAudioSession.sharedInstance () значение .soloAmbient. Таким образом, звук отключается с помощью блокировки экрана и переключателя Silent. - person gafos; 29.05.2020
comment
Этот ответ обычно работает, но создает состояние гонки, зависящее от загрузки системы. Иногда iOS не успевает вызвать 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];
person sudo rm -rf    schedule 13.12.2010
comment
Я не думаю, что это сработает, он просто воспроизводит пустой звук, пока играет шум затвора. Вполне возможно играть 2 звука одновременно. Остальные 2 метода кажутся работоспособными! - person Linuxmint; 14.12.2010
comment
Дать ему шанс. Я не уверен, что это сработает, но надеюсь! - person sudo rm -rf; 14.12.2010

Мне удалось заставить это работать, используя этот код в функции 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];

Просто не забудьте быть вежливым и включить звук, когда ваше приложение вернется!

person frakman1    schedule 26.07.2015

Я живу в Японии, поэтому из соображений безопасности я не могу отключить звук, когда мы делаем фотографии. Однако в видео звук отключается. Не понимаю почему.

Единственный способ сделать снимок без звука срабатывания затвора - использовать 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 вызывается последовательно. Я это лучшее решение.

person Ben    schedule 24.12.2010


См. Этот пост для другого ответа: Захват изображения из буфера изображений. Не удается сделать снимок экрана во время предварительного просмотра видео

person Aaron Bratcher    schedule 08.06.2015

Единственный возможный обходной путь, о котором я могу думать, - это отключить звук iphone, когда они нажимают кнопку «сделать снимок», а затем включить его через секунду.

person Linuxmint    schedule 09.12.2010
comment
Как программно отключить звук iPhone? Спасибо! - person ohho; 10.12.2010
comment
даже если бы вы могли, Apple не одобрила бы это - person ; 19.12.2010

Распространенный прием в таких случаях - выяснить, вызывает ли фреймворк определенный метод для этого события, а затем временно перезаписать этот метод, тем самым аннулируя его эффект.

Мне очень жаль, но я недостаточно хорош, чтобы сразу сказать вам, работает ли это в данном случае. Вы можете попробовать команду «nm» в исполняемых файлах фреймворка, чтобы увидеть, есть ли именованная функция с подходящим именем, или использовать gdb с симулятором, чтобы отследить, куда она идет.

Я полагаю, что когда вы знаете, что перезаписывать, есть те низкоуровневые диспетчерские функции ObjC, которые вы можете использовать для перенаправления поиска функций. Я думаю, что делал это некоторое время назад, но не могу вспомнить детали.

Надеюсь, вы сможете использовать мои подсказки, чтобы найти в Google несколько путей решения этой проблемы. Удачи.

person Thomas Tempelmann    schedule 19.12.2010