AVFoundation, come disattivare il suono dell'otturatore quando captureStillImageAsynchronouslyFromConnection?

StackOverflow https://stackoverflow.com/questions/4401232

Domanda

Sto cercando di catturare un'immagine durante un'anteprima in tempo reale dalla telecamera, da AVFoundation captureStillImageAsynchronouslyFromConnection . Finora il programma funziona come previsto. Tuttavia, come posso disattivare il suono di scatto?

È stato utile?

Soluzione

Ho usato questo codice una volta alla cattura iOS suono dell'otturatore di default (in questo caso è la lista di nomi di file audio 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];

Poi ho usato app di terze parti per estrarre photoShutter.caf dalla directory Documenti (DiskAid for Mac). Il passo successivo ho aperto photoShutter.caf in Audacity editor audio e l'effetto di inversione applicato, sembra che questo in alto zoom:

entrare descrizione dell'immagine qui

Poi ho salvato questo suono come photoShutter2.caf e ho cercato di riprodurre questo suono a destra prima 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:
...

E questo funziona davvero! I test viene eseguito più volte, ogni volta che sento alcun suono di scatto:)

È possibile ottenere già invertito suono, catturato su iPhone 5S iOS 7.1.1 da questo link: https: // www.dropbox.com/s/1echsi6ivbb85bv/photoShutter2.caf

Altri suggerimenti

Metodo 1:. Non so se questo lavoro sarà, ma prova a riprodurre un file audio vuoto a destra prima di inviare l'evento di cattura

Per riprodurre un clip, aggiungere il quadro Audio Toolbox, #include <AudioToolbox/AudioToolbox.h> and riprodurre il file audio come questo immediatamente prima di scattare la foto:

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

Ecco un file vuoto audio se ne avete bisogno. http://cl.ly/3cKi

________________________________________________________________________________________________________________________________________

Metodo 2: C'è anche un'alternativa se questo non funziona. Finché non c'è bisogno di avere una risoluzione buona, è possibile grab un fotogramma del flusso video , evitando così il suono immagine del tutto.

________________________________________________________________________________________________________________________________________

Metodo 3: Un altro modo per farlo sarebbe quello di prendere una "screenshot" della vostra applicazione. Farlo in questo modo:

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

Se hai intenzione questo per riempire l'intero schermo con un'anteprima del flusso video in modo che la vostra screenshot sembra buono:

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

La mia soluzione a Swift

Quando si chiama il metodo AVCapturePhotoOutput.capturePhoto Acquisizione Immagine per come qui di seguito il codice.

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

verrà richiamato metodi AVCapturePhotoCaptureDelegate. E il sistema tenta di riprodurre il suono di scatto dopo willCapturePhotoFor invocato. Così si può smaltire audio del sistema in modo willCapturePhotoFor.

 entrare descrizione dell'immagine qui

extension PhotoCaptureService: AVCapturePhotoCaptureDelegate {

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

Vedi anche

sono stato in grado di ottenere questo al lavoro utilizzando questo codice nella funzione snapStillImage e funziona perfettamente per me su iOS 8.3 iPhone 5. Ho anche confermato che Apple non rifiuterà la vostra applicazione se si utilizza questo (che didn 't rifiutano mio)

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

Basta ricordarsi di essere bello e riattivare quando i rendimenti app!

Io vivo a in Giappone, quindi non posso disattivare l'audio quando prendiamo le foto per motivi di sicurezza. Nel video, si trasforma tuttavia audio spento. Non capisco perché.

L'unico modo che scattare foto anche senza suono dell'otturatore sta usando AVCaptureVideoDataOutput o AVCaptureMovieFileOutput. Per analizzare un'immagine ancora AVCaptureVideoDataOutput è unico modo. In AVFoundatation codice di esempio,

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

Nel mio 3GS è molto pesante quando ho impostato CMTimeMake (1, 1); // Un frame per secondo.

In WWDC 2010 di codice di esempio, FindMyiCone, ho trovato seguente codice,

[output setAlwaysDiscardsLateVideoFrames:YES];

Quando si utilizza questa API, la sincronizzazione non viene concessa, ma API viene chiamato in sequenza. Ho questo è migliori soluzioni.

Si può anche prendere un fotogramma da un flusso video per catturare un'immagine (non piena risoluzione).

E 'utilizzato qui per catturare immagini a intervalli brevi:

- (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;
}

Vedere questo post per un diverso tipo di risposta: Cattura l'immagine dal buffer di immagini. durante l'anteprima video non riesce

Il possibile solo work-around mi viene in mente sarebbe quello di disattivare l'audio iPhone quando si preme il pulsante "Scatta foto", e quindi riattivare un secondo più tardi.

Un trucco comune in questi casi è quello di scoprire se il quadro richiama un certo metodo per questo evento, e quindi per sovrascrivere il metodo temporaneamente, annullando così il suo effetto.

Mi dispiace, ma io non sono un buon trucco abbastanza per dirvi subito se funziona in questo caso. Si potrebbe provare il comando "nm" sulle eseguibili quadro per vedere se c'è una funzione denominata che ha un nome suitatable, o l'uso gdb con il simulatore di rintracciare dove va.

Una volta che sai cosa sovrascrivere, ci sono quelli di basso livello objC funzioni che è possibile utilizzare per reindirizzare la ricerca per le funzioni di dispacciamento, credo. Credo di aver fatto che una volta che qualche tempo fa, ma non ricordo i dettagli.

Si spera, è possibile utilizzare i miei suggerimenti a Google un paio di soluzioni percorsi per questo. Buona fortuna.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top