Tôi đang cố chụp ảnh trong khi xem trước trực tiếp từ máy ảnh, bằng AVFoundation captureStillImageAsynchronouslyFromConnection . Cho đến nay chương trình hoạt động như mong đợi. Tuy nhiên, làm cách nào để tắt âm thanh cửa trập?
Tôi đang cố chụp ảnh trong khi xem trước trực tiếp từ máy ảnh, bằng AVFoundation captureStillImageAsynchronouslyFromConnection . Cho đến nay chương trình hoạt động như mong đợi. Tuy nhiên, làm cách nào để tắt âm thanh cửa trập?
Câu trả lời:
Tôi đã sử dụng mã này một lần để ghi lại âm thanh cửa trập mặc định của iOS (đây là danh sách tên tệp âm thanh 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];
Sau đó, tôi sử dụng ứng dụng của bên thứ ba để giải nén photoShutter.caf
từ thư mục Documents (DiskAid cho Mac). Bước tiếp theo tôi đã mở photoShutter.caf
trong trình chỉnh sửa âm thanh Audacity và áp dụng hiệu ứng đảo ngược, nó trông giống như thế này khi thu phóng cao:
Sau đó, tôi đã lưu âm thanh này dưới dạng photoShutter2.caf
và cố gắng phát âm thanh này ngay trước đó 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:
...
Và điều này thực sự hiệu quả! Tôi chạy thử nghiệm nhiều lần, lần nào cũng không nghe thấy âm thanh cửa trập :)
Bạn có thể nhận được âm thanh đã được đảo ngược, được ghi lại trên iPhone 5S iOS 7.1.1 từ liên kết này: https://www.dropbox.com/s/1echsi6ivbb85bv/photoShutter2.caf
Khi bạn gọi AVCapturePhotoOutput.capturePhoto
phương thức để chụp một hình ảnh như đoạn mã dưới đây.
photoOutput.capturePhoto(with: self.capturePhotoSettings, delegate: self)
Các phương thức AVCapturePhotoCaptureDelegate sẽ được gọi. Và hệ thống sẽ cố gắng phát âm thanh màn trập sau khi willCapturePhotoFor
được gọi. Vì vậy, bạn có thể loại bỏ âm thanh hệ thống trong willCapturePhotoFor
phương pháp.
extension PhotoCaptureService: AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
// dispose system shutter sound
AudioServicesDisposeSystemSoundID(1108)
}
}
AudioServicesDisposeSystemSoundID(1108)
được gọi. Bạn có bất kỳ giải pháp cho điều này? :)
Phương pháp 1: Không chắc liệu cách này có hiệu quả hay không, nhưng hãy thử phát tệp âm thanh trống ngay trước khi bạn gửi sự kiện chụp.
Để phát clip, hãy thêm Audio Toolbox
khung #include <AudioToolbox/AudioToolbox.h>
và phát tệp âm thanh như thế này ngay lập tức trước khi bạn chụp ảnh:
NSString *path = [[NSBundle mainBundle] pathForResource:@"blank" ofType:@"wav"];
SystemSoundID soundID;
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
AudioServicesPlaySystemSound(soundID);
Đây là tệp âm thanh trống nếu bạn cần. https://d1sz9tkli0lfjq.cloudfront.net/items/0Y3Z0A1j1H2r1c0z3n3t/blank.wav
________________________________________________________________________________________________________________________________________
Phương pháp 2: Cũng có một giải pháp thay thế nếu điều này không hiệu quả. Miễn là bạn không cần phải có độ phân giải tốt, bạn có thể lấy khung hình từ luồng video , do đó tránh hoàn toàn âm thanh hình ảnh.
________________________________________________________________________________________________________________________________________
Phương pháp 3: Một cách khác để thực hiện việc này là chụp "ảnh màn hình" ứng dụng của bạn. Làm như thế này:
UIGraphicsBeginImageContext(self.window.bounds.size);
[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:@"foo.png" atomically:YES];
Nếu bạn muốn điều này lấp đầy toàn bộ màn hình với bản xem trước của luồng video để ảnh chụp màn hình của bạn trông đẹp:
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];
Tôi đã có thể làm cho điều này hoạt động bằng cách sử dụng mã này trong chức năng snapStillImage và nó hoạt động hoàn hảo đối với tôi trên iOS 8.3 iPhone 5. Tôi cũng đã xác nhận rằng Apple sẽ không từ chối ứng dụng của bạn nếu bạn sử dụng mã này (họ không từ chối của tôi)
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];
Chỉ cần nhớ trở nên tốt đẹp và bật tiếng khi ứng dụng của bạn trở lại!
Tôi sống ở Nhật Bản, vì vậy tôi không thể tắt âm thanh khi chúng tôi chụp ảnh vì lý do bảo mật. Trong video, tuy nhiên, âm thanh tắt. Tôi không hiểu tại sao.
Cách duy nhất tôi chụp ảnh mà không có âm thanh cửa trập là sử dụng AVCaptureVideoDataOutput hoặc AVCaptureMovieFileOutput. Để phân tích hình ảnh tĩnh AVCaptureVideoDataOutput là cách duy nhất. Trong mã mẫu 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);
Trong 3GS của tôi, nó rất nặng khi tôi đặt CMTimeMake (1, 1); // Một khung hình trên giây.
Trong mã mẫu WWDC 2010, FindMyiCone, tôi tìm thấy mã sau,
[output setAlwaysDiscardsLateVideoFrames:YES];
Khi API này được sử dụng, thời gian không được cấp, nhưng API được gọi tuần tự. Tôi đây là giải pháp tốt nhất.
Bạn cũng có thể lấy một khung hình từ luồng video để chụp ảnh (không phải độ phân giải đầy đủ).
Nó được sử dụng ở đây để chụp ảnh trong khoảng thời gian ngắn:
- (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;
}
Xem bài đăng này để biết một loại câu trả lời khác: Chụp ảnh từ bộ đệm ảnh. Chụp màn hình trong khi xem trước video không thành công
Một thủ thuật phổ biến trong những trường hợp như vậy là tìm hiểu xem khung công tác có gọi một phương thức nào đó cho sự kiện này hay không và sau đó ghi đè phương thức đó tạm thời, do đó làm mất tác dụng của nó.
Tôi xin lỗi nhưng tôi không phải là một hack đủ tốt để nói với bạn ngay lập tức nếu điều đó hoạt động trong trường hợp này. Bạn có thể thử lệnh "nm" trên các tệp thực thi của khung công tác để xem liệu có một hàm được đặt tên có tên phù hợp hay không hoặc sử dụng gdb với Trình mô phỏng để theo dõi vị trí của nó.
Khi bạn biết những gì cần ghi đè, có những chức năng điều phối objC cấp thấp mà bạn có thể sử dụng để chuyển hướng tra cứu các chức năng, tôi tin. Tôi nghĩ rằng tôi đã làm điều đó một lần trước đây, nhưng không thể nhớ chi tiết.
Hy vọng rằng bạn có thể sử dụng gợi ý của tôi để google một vài giải pháp cho vấn đề này. Chúc may mắn.