Я пытаюсь захватить изображение во время предварительного просмотра с камеры с помощью AVFoundation captureStillImageAsynchronouslyFromConnection . Пока программа работает как положено. Однако как я могу отключить звук срабатывания затвора?
90
Ответы:
Я однажды использовал этот код, чтобы записать звук затвора 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
источник
Мое решение в 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)
вызове. У вас есть какие-то решения для этого? :)Метод 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, и он отлично работает для меня на iPhone 5 с iOS 8.3. Я также подтвердил, что 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 вызывается последовательно. Я это лучшее решение.
источник
Вы также можете взять кадр из видеопотока, чтобы захватить изображение (не в полном разрешении).
Он используется здесь для изображений захвата через короткие промежутки времени:
- (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; }
источник
Смотрите этот пост для другого ответа: Захват изображения из буфера изображений. Не удается сделать снимок экрана во время предварительного просмотра видео
источник
Единственный возможный обходной путь, о котором я могу думать, - это отключить звук iphone, когда они нажимают кнопку «сделать снимок», а затем включить его через секунду.
источник
Распространенный прием в таких случаях - выяснить, вызывает ли фреймворк определенный метод для этого события, а затем временно перезаписать этот метод, аннулируя его эффект.
Мне очень жаль, но я недостаточно хорош, чтобы сразу сказать вам, работает ли это в данном случае. Вы можете попробовать команду «nm» на исполняемых файлах фреймворка, чтобы увидеть, есть ли именованная функция с подходящим именем, или использовать gdb с Simulator, чтобы отследить, куда она идет.
Я считаю, что когда вы знаете, что перезаписывать, появляются те низкоуровневые диспетчерские функции ObjC, которые вы можете использовать для перенаправления поиска функций. Я думаю, что делал это некоторое время назад, но не могу вспомнить детали.
Надеюсь, вы сможете воспользоваться моими подсказками, чтобы найти в Google несколько путей решения этой проблемы. Удачи.
источник