AVFoundation, jak wyłączyć dźwięk migawki podczas przechwytywania obrazu w trybie synchronicznym z połączeniem?

Staram się uchwycić obraz podczas podglądu na żywo z kamery, przez Fundation przechwytuje obrazy w sposób synchroniczny z połączeniem . Jak na razie program działa zgodnie z oczekiwaniami. Jak jednak wyciszyć dźwięk migawki?

Author: Cœur, 2010-12-09

9 answers

Kiedyś użyłem tego kodu do przechwytywania domyślnego dźwięku migawki iOS (oto lista nazw plików dźwiękowych 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];

Następnie użyłem aplikacji innej firmy do wyodrębnienia photoShutter.caf z katalogu Documents (DiskAid for Mac). Następnie otworzyłem photoShutter.caf w Audacity audio editor i zastosowałem efekt inwersji, wygląda to tak przy dużym powiększeniu:

Tutaj wpisz opis obrazka

Potem zapisałem ten dźwięk jako photoShutter2.caf i próbowałem odtworzyć ten dźwięk tuż przed 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:
...

I to naprawdę działa! Testuje kilka razy, za każdym razem nie słyszę dźwięku migawki:)

Możesz uzyskać już odwrócony dźwięk, przechwycony na iPhone 5s iOS 7.1.1 z tego linku: https://www.dropbox.com/s/1echsi6ivbb85bv/photoShutter2.caf

 1503
Author: k06a,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-23 18:07:05

Moje rozwiązanie w Swift

Po wywołaniu AVCapturePhotoOutput.capturePhoto metody przechwytywania obrazu, jak poniższy kod.

photoOutput.capturePhoto(with: self.capturePhotoSettings, delegate: self)

Zostaną wywołane metody AVCapturePhotoCaptureDelegate. System próbuje odtworzyć dźwięk migawki po wywołaniu willCapturePhotoFor. Można więc pozbyć się dźwięku systemowego metodą willCapturePhotoFor.

Tutaj wpisz opis obrazka

extension PhotoCaptureService: AVCapturePhotoCaptureDelegate {

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

Zobacz też

 36
Author: Won,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-23 04:27:32

Metoda 1: Nie wiem, czy to zadziała, ale spróbuj odtworzyć pusty plik audio tuż przed wysłaniem zdarzenia przechwytywania.

Aby odtworzyć klip, dodaj framework Audio Toolbox, #include <AudioToolbox/AudioToolbox.h> i odtwórz plik audio w ten sposób natychmiast przed zrobieniem zdjęcia:

 NSString *path = [[NSBundle mainBundle] pathForResource:@"blank" ofType:@"wav"];
 SystemSoundID soundID;
 NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
 AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
 AudioServicesPlaySystemSound(soundID);

Oto pusty plik audio, jeśli go potrzebujesz. https://d1sz9tkli0lfjq.cloudfront.net/items/0Y3Z0A1j1H2r1c0z3n3t/blank.wav

________________________________________________________________________________________________________________________________________

Metoda 2: Istnieje również alternatywa, jeśli to nie zadziała. Jeśli nie musisz mieć dobrej rozdzielczości, możesz pobrać klatkę ze strumienia wideo , unikając w ten sposób dźwięku obrazu / align = "left" /

________________________________________________________________________________________________________________________________________

Metoda 3: innym sposobem na to byłoby wykonanie "zrzutu ekranu" aplikacji. Zrób to tak:

UIGraphicsBeginImageContext(self.window.bounds.size);
[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:@"foo.png" atomically:YES];

Jeśli chcesz, aby to wypełniło cały ekran podglądem strumienia wideo, aby twój zrzut ekranu wyglądał dobrze:

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];
 21
Author: sudo rm -rf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-23 13:30:13

Udało mi się to uruchomić za pomocą tego kodu w funkcji snapStillImage i działa idealnie dla mnie na iOS 8.3 iPhone 5. Potwierdziłem również, że Apple nie odrzuci Twojej aplikacji, jeśli jej użyjesz (nie odrzucili mojej)

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];

Po prostu pamiętaj, aby być miły i wyłączyć go, gdy aplikacja powróci!

 7
Author: frakman1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-28 16:19:30

Mieszkam w Japonii, więc nie mogę wyciszyć dźwięku, gdy robimy zdjęcia ze względów bezpieczeństwa. W wideo jednak dźwięk wyłącza się. Nie rozumiem dlaczego.

Jedynym sposobem na zrobienie zdjęcia bez dźwięku migawki jest użycie AVCaptureVideoDataOutput lub AVCaptureMovieFileOutput. Do analizy obrazu nieruchomego AVCaptureVideoDataOutput jest jedynym sposobem. W kodzie przykładowym 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);

W moim 3GS jest to bardzo ciężkie, gdy ustawiam CMTimeMake (1, 1); / / jedna klatka na sekundę.

W WWDC 2010 Przykładowy kod, FindMyiCone, znalazłem następujący kod,

[output setAlwaysDiscardsLateVideoFrames:YES];

Gdy ten API jest używany, czas nie jest przyznawany, ale API jest wywoływane sekwencyjnie. I to jest najlepsze rozwiązania.

 5
Author: Ben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-24 01:21:04

Możesz również pobrać klatkę ze strumienia wideo, aby uchwycić obraz (nie w pełnej rozdzielczości).

Jest używany tutaj do przechwytywania obrazów w krótkich odstępach czasu:

- (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;
}
 3
Author: Rivera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-26 02:18:54

Zobacz ten post dla innego rodzaju odpowiedzi: przechwytywanie obrazu z bufora obrazu. przechwytywanie ekranu podczas podglądu wideo nie powiodło się

 3
Author: Aaron Bratcher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:43

Jedynym możliwym obejściem, o którym mogę myśleć, byłoby wyciszenie dźwięku iphone ' a po naciśnięciu przycisku "zrób zdjęcie", a następnie odłączenie go sekundę później.

 0
Author: Linuxmint,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-09 18:44:27

Powszechną sztuczką w takich przypadkach jest sprawdzenie, czy framework wywołuje określoną metodę dla tego zdarzenia, a następnie tymczasowe zastąpienie tej metody, co unieważnia jej efekt.

Przykro mi, ale nie jestem wystarczająco dobrym hakerem, aby powiedzieć ci od razu, czy to działa w tym przypadku. Możesz wypróbować polecenie " nm " na plikach wykonywalnych frameworku, aby sprawdzić, czy istnieje funkcja o nazwie, która ma odpowiednią nazwę, lub użyć gdb z symulatorem, aby prześledzić, gdzie ona idzie.

Gdy już wiesz co to zastąp, są te niskopoziomowe funkcje wysyłania obiektów, których możesz użyć do przekierowania wyszukiwania dla funkcji, jak sądzę. Myślę, że robiłam to już jakiś czas temu, ale nie pamiętam szczegółów.

Mam nadzieję, że możesz użyć moich wskazówek, aby google kilka ścieżek rozwiązań do tego. Powodzenia.

 0
Author: Thomas Tempelmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-19 22:40:23