मैं कैमरे से लाइव पूर्वावलोकन के दौरान AVFoundation CaptureStillImageAsynchronouslyFromConnection द्वारा एक छवि को कैप्चर करने का प्रयास कर रहा हूं । अब तक कार्यक्रम उम्मीद के मुताबिक काम करता है। हालांकि, मैं शटर ध्वनि को कैसे म्यूट कर सकता हूं?
मैं कैमरे से लाइव पूर्वावलोकन के दौरान AVFoundation CaptureStillImageAsynchronouslyFromConnection द्वारा एक छवि को कैप्चर करने का प्रयास कर रहा हूं । अब तक कार्यक्रम उम्मीद के मुताबिक काम करता है। हालांकि, मैं शटर ध्वनि को कैसे म्यूट कर सकता हूं?
जवाबों:
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
जब आप 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 फ़ंक्शन में इस कोड का उपयोग करके इसे प्राप्त करने में सक्षम था और यह 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];
बस अच्छा होना याद रखें और जब आपका ऐप वापस आए तो इसे अनम्यूट कर दें!
मैं जापान में रहता हूं, इसलिए जब हम सुरक्षा कारणों से तस्वीरें लेते हैं तो मैं ऑडियो म्यूट नहीं कर सकता। वीडियो में, हालांकि ऑडियो बंद हो जाता है। मुझे समझ में नहीं आता क्यों।
जिस तरह से मैं शटर साउंड के बिना एक फोटो लेता हूं वह 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 का उपयोग करें।
एक बार जब आप जानते हैं कि अधिलेखित करने के लिए क्या है, तो निम्न स्तर के ओबीजसी प्रेषण कार्य हैं जिन्हें आप फ़ंक्शंस के लिए लुकअप को पुनर्निर्देशित करने के लिए उपयोग कर सकते हैं, मुझे विश्वास है। मुझे लगता है कि मैंने ऐसा कुछ समय पहले किया है, लेकिन विवरण याद नहीं कर सकता।
उम्मीद है, आप मेरे संकेत का उपयोग कर सकते हैं यह करने के लिए कुछ समाधान पथ गूगल। सौभाग्य।