AVFoundation, जब कैप्चरस्टिल्मेजेसिंक्रोनस रूप से FromConnection, शटर ध्वनि को कैसे बंद करें?


89

मैं कैमरे से लाइव पूर्वावलोकन के दौरान AVFoundation CaptureStillImageAsynchronouslyFromConnection द्वारा एक छवि को कैप्चर करने का प्रयास कर रहा हूं । अब तक कार्यक्रम उम्मीद के मुताबिक काम करता है। हालांकि, मैं शटर ध्वनि को कैसे म्यूट कर सकता हूं?


5
उदाहरण के लिए जापान में आप ऐसा नहीं कर सकते। वहाँ शटर ध्वनि हमेशा खेलता है भले ही आपने फोन को म्यूट कर दिया हो। (गोपनीयता के उल्लंघन को रोकने के लिए कुछ अजीब नियम, उर्फ ​​upskirt फोटोग्राफी जापान में जहाँ तक मुझे पता है) की जगह हैं, तो मुझे नहीं लगता कि ऐसा करने का कोई तरीका है।
डंकलस्टर्न

3
हाँ, यह हो सकता है कि आपका iPhone म्यूट कैमरा शॉट्स की अनुमति न दे। मैं यूएस में हूं और मेरा iPhone तब आवाज नहीं करता जब मैं फोन के साथ तस्वीर लेता हूं; दूसरी ओर मेरी प्रेमिका, एक आवाज करती है (उसकी कोरिया से है)।
डॉनकीम

5
स्पष्ट होने के लिए, यह एक समाधान है जब फोन म्यूट / वाइब्रेट मोड नहीं है। उस मोड में, तस्वीर लेते समय कोई आवाज़ नहीं की जाती है।
न्यू एलेक्जेंड्रिया

31
जापान में @NewAlexandria मैंने शटर मोड में भी सुना है। यह कानून की आवश्यकता है।
k06a

3
डिवाइस म्यूट होने पर Btw AudioServicesPlaySystemSound नहीं चलेगा। इसलिए जापानी डिवाइसेस तब भी आवाज करेंगी जब म्यूट किया गया होगा, लेकिन नॉन-म्यूट होने पर नहीं ...
Filip Radelic

जवाबों:


1501

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दस्तावेज़ निर्देशिका (मैक के लिए डिस्कैड) से निकालने के लिए तीसरे पक्ष के ऐप का उपयोग किया। अगला चरण मैंने photoShutter.cafऑडेसिटी ऑडियो संपादक में खोला और उलटा प्रभाव लागू किया, यह उच्च ज़ूम पर इस तरह दिखता है:

यहां छवि विवरण दर्ज करें

फिर मैंने इस ध्वनि को सहेज लिया 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


104
बहुत ही शांत। केवल चेतावनी यह है कि जब फ्लैश चालू किया जाता है, तो यह एक डबल शटर ध्वनि का परिणाम देगा क्योंकि कैप्चरस्टीलइमेजएन्सएक्रिएन्सफ्रीक्रिएंटलीफ्रेमकॉन्फेक्शन के दौरान डिफ़ॉल्ट सिस्टम साउंड नहीं खेला जाता है: इसे कहा जाता है, लेकिन जब छवि वास्तव में कैप्चर की जाती है (फ्लैश अनुक्रम के दौरान)। इसके बजाय self -stillImageOutput पर एक key-value ऑब्जर्वर को जोड़ने के लिए keyPath 'कैप्चरस्टीलइमेज' का पता लगाने के लिए जब सही मायने में कैप्चर करना शुरू होता है, तो कॉलबैक विधि में उलटा ध्वनि बजाएं।
जेफ मस्किया

16
यह आधुनिक सैन्य विमान राडार को कैसे पराजित करता है। यही कारण है कि आप नए लड़ाकू डिजाइनों पर "स्टील्थ आकार" सिल्हूट नहीं देखते हैं: एक इलेक्ट्रॉनिक्स पैकेज है जो मूल रूप से एक रडार-पराजित चरण पारी को संभालता है जो एक "उलटा" (चरण-स्थानांतरित) डुप्लिकेट सिग्नल प्रसारित करता है।
L0j1k

5
@ L0j1k: यह इस बात पर निर्भर करता है कि आप किस तरह के स्टील्थ जहाज के बारे में बात कर रहे हैं। F22 एक ilk undetected होने में दिलचस्पी नहीं है, लेकिन अनलॉक करने योग्य होने में। चरण बदलाव तकनीक के साथ समस्या यह है कि आप हर दूसरी स्थिति से अविश्वसनीय रूप से स्पष्ट हैं, क्योंकि वे एक ही बदलाव नहीं देखेंगे।
ग्वेंटे

13
यह है कि शोर-रद्द करने वाले हेडफ़ोन काम करते हैं, सिवाय इसके कि वे वास्तविक समय में ध्वनि को
पकड़ते हैं

4
यह iOS7 के लिए बहुत अच्छा था, लेकिन यह अब iOS8 पर काम नहीं करता है, किसी भी विचार से iOS8 पर इसे कैसे हल किया जाए?
टिको

33

स्विफ्ट में मेरा समाधान

जब आप 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)
    }
}

यह सभी देखें


3
यह एक सुंदर समाधान है और यह पूरी तरह से काम करता है। शानदार जवाब भी। शुक्रिया @kyle
युद्धरत

1
यह पूरी तरह से काम है। यदि आपको मूक मोड और सामान्य मोड को अलग करने की आवश्यकता है, तो AudioServicesPlaySytemSoundID (1108) का उलटा उपयोग करें। धन्यवाद।
एमजे स्टूडियो

1
यह काम करता हैं! मैं जानना चाहता हूं कि क्या आपको इस तरह की विधि से AppStore पर अपलोड करने में कोई परेशानी है?
Liew जून तुंग

2
@LiewJunTung इस समाधान के साथ कोई परेशानी नहीं है। मैंने पहले ही इस समाधान के साथ ऐप अपलोड कर दिए हैं। बहुत सारे ऐप हैं जो इस तरह के समाधान का उपयोग करते हैं। खुश कोडिंग।
जीता

मैंने एक समस्या खोज ली है। मुझे आश्चर्य है कि क्या आपने इस समस्या का पता लगाया है। यह मूल रूप से एक मेमोरी लीक है जो केवल तब होता है जब AudioServicesDisposeSystemSoundID(1108)कहा जाता है। क्या आपके पास इसके लिए कोई उपाय है? :)
Liew जून तुंग

21

विधि 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];

2
मुझे नहीं लगता कि यह काम करेगा, यह सिर्फ एक "खाली" ध्वनि बजाएगा, जबकि शटर शोर खेलता है। एक ही समय में 2 ध्वनियों को बजाने के लिए यह काफी संभव है। अन्य 2 विधियाँ कारगर लगती हैं!
लिनक्समिंट

2
इसे आजमा कर देखें। मुझे विश्वास नहीं है कि यह काम करेगा, लेकिन यहाँ उम्मीद है!
सुडो rm -rf

7

मैं 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];

बस अच्छा होना याद रखें और जब आपका ऐप वापस आए तो इसे अनम्यूट कर दें!


5

मैं जापान में रहता हूं, इसलिए जब हम सुरक्षा कारणों से तस्वीरें लेते हैं तो मैं ऑडियो म्यूट नहीं कर सकता। वीडियो में, हालांकि ऑडियो बंद हो जाता है। मुझे समझ में नहीं आता क्यों।

जिस तरह से मैं शटर साउंड के बिना एक फोटो लेता हूं वह 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 को क्रमिक रूप से कहा जाता है। मैं यह सबसे अच्छा समाधान है।


3

आप एक वीडियो स्ट्रीम से एक (पूर्ण रिज़ॉल्यूशन नहीं) छवि कैप्चर करने के लिए एक फ़्रेम भी ले सकते हैं।

इसका उपयोग यहाँ छोटे अंतराल पर चित्र कैप्चर करने के लिए किया जाता है :

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

क्या आप AVCaptureVideoDataOutput को प्राप्त करने में सक्षम हैं जबकि AVCaptureMovieFileOutput का उपयोग किया जा रहा है? जब मैं उन दोनों का उपयोग करने की कोशिश करता हूं तो AVCaptureVideoDataOutput के प्रतिनिधि तरीकों को नहीं बुलाया जाता है।
पॉल सीज़न

क्षमा करें, मैंने एक ही समय में एक से अधिक आउटपुट की कोशिश नहीं की है।
रिवरएप


0

केवल संभव काम-के आसपास मैं सोच सकता हूं कि जब वे "तस्वीर लें" बटन दबाते हैं, तो iPhone ध्वनि को म्यूट करना होगा, और फिर दूसरे-बाद में इसे म्यूट करें।


प्रोग्राम को iPhone ध्वनि कैसे म्यूट करें? धन्यवाद!
ओहो

यहां तक ​​कि अगर आप कर सकते हैं, तो Apple अनुमोदन नहीं करेगा कि

0

ऐसे मामलों में एक सामान्य ट्रिक यह पता लगाना है कि क्या फ्रेमवर्क इस घटना के लिए एक निश्चित विधि को लागू करता है, और फिर उस पद्धति को अस्थायी रूप से अधिलेखित कर देता है, जिससे इसका प्रभाव शून्य हो जाता है।

मुझे खेद है, लेकिन मैं इस मामले में काम करने के लिए अभी आपको बताने के लिए एक अच्छा हैक नहीं हूं। आप फ्रेमवर्क एक्जीक्यूटिव पर "nm" कमांड को यह देखने के लिए आज़मा सकते हैं कि क्या एक नामित फ़ंक्शन है जिसमें एक उपयुक्त नाम है, या जहाँ यह जाता है, ट्रेस करने के लिए सिम्युलेटर के साथ gdb का उपयोग करें।

एक बार जब आप जानते हैं कि अधिलेखित करने के लिए क्या है, तो निम्न स्तर के ओबीजसी प्रेषण कार्य हैं जिन्हें आप फ़ंक्शंस के लिए लुकअप को पुनर्निर्देशित करने के लिए उपयोग कर सकते हैं, मुझे विश्वास है। मुझे लगता है कि मैंने ऐसा कुछ समय पहले किया है, लेकिन विवरण याद नहीं कर सकता।

उम्मीद है, आप मेरे संकेत का उपयोग कर सकते हैं यह करने के लिए कुछ समाधान पथ गूगल। सौभाग्य।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.