利用AVFoundation實現Blink拍照和錄像的功能
github代碼
前幾天偶然發現一個app叫Blink,閑來無事,純當練手,于是就嘗試下自己實現它的功能.
頁面都挺簡單的
1.打開相機
- (void)openCamera:(AVCaptureDevicePosition)cameraPostion {
BOOL hasCamera = ([[AVCaptureDevice devices] count] > );
if (hasCamera) {
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[captureVideoPreviewLayer setFrame:self.cameraImageView.bounds];
[self.cameraImageView.layer addSublayer:captureVideoPreviewLayer];
AVCaptureDevice *device = [self getCamera:cameraPostion];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
[session addInput:input];
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = @{ AVVideoCodecKey : AVVideoCodecJPEG};
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
movieOutput = [[AVCaptureMovieFileOutput alloc] init];
[session addOutput:movieOutput];
[session startRunning];
}
BOOL hasCamera = ([[AVCaptureDevice devices] count] > );
if (hasCamera) {
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[captureVideoPreviewLayer setFrame:self.cameraImageView.bounds];
[self.cameraImageView.layer addSublayer:captureVideoPreviewLayer];
AVCaptureDevice *device = [self getCamera:cameraPostion];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
[session addInput:input];
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = @{ AVVideoCodecKey : AVVideoCodecJPEG};
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
movieOutput = [[AVCaptureMovieFileOutput alloc] init];
[session addOutput:movieOutput];
[session startRunning];
}
}
- (AVCaptureDevice *)getCamera:(AVCaptureDevicePosition)cameraPostion {
NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in cameras) {
if (device.position == cameraPostion)
return device;
}
return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in cameras) {
if (device.position == cameraPostion)
return device;
}
return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
}
2.獲取靜態圖片
- (void)captureNow {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
videoConnection = connection;
break;
}
}
if (videoConnection) { break; }
}
// 取靜態圖片
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
NSData *compressedData = [imageData gzippedDataWithCompressionLevel:1.0];
NSData *outputData = [compressedData gunzippedData];
UIImage *imageT = [[UIImage alloc] initWithData:outputData];
_testImageView.image = imageT;
_testImageView.hidden = NO;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(),@"main.png"];
[fileManager createFileAtPath:filePath contents:imageData attributes:nil];
NSString *zipFile = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(),@"main.zip"];
ZipArchive *za = [[ZipArchive alloc] init];
[za CreateZipFile2:zipFile];
[za addFileToZip:filePath newname:@"main.png"];
}];
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
videoConnection = connection;
break;
}
}
if (videoConnection) { break; }
}
// 取靜態圖片
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
NSData *compressedData = [imageData gzippedDataWithCompressionLevel:1.0];
NSData *outputData = [compressedData gunzippedData];
UIImage *imageT = [[UIImage alloc] initWithData:outputData];
_testImageView.image = imageT;
_testImageView.hidden = NO;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(),@"main.png"];
[fileManager createFileAtPath:filePath contents:imageData attributes:nil];
NSString *zipFile = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(),@"main.zip"];
ZipArchive *za = [[ZipArchive alloc] init];
[za CreateZipFile2:zipFile];
[za addFileToZip:filePath newname:@"main.png"];
}];
}
3.錄像和播放錄像
- (IBAction)beginRecord:(id)sender {
[movieOutput startRecordingToOutputFileURL:[self fileURLWithName:@"main.mp4"] recordingDelegate:self];
[movieOutput startRecordingToOutputFileURL:[self fileURLWithName:@"main.mp4"] recordingDelegate:self];
}
- (void)stopRecord {
[movieOutput stopRecording];
[movieOutput stopRecording];
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error {
BOOL recordedSuccessfully = YES;
if (error == nil) {
[self playVideo:outputFileURL];
}
if ([error code] != noErr) {
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value) {
recordedSuccessfully = [value boolValue];
}
}
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error {
BOOL recordedSuccessfully = YES;
if (error == nil) {
[self playVideo:outputFileURL];
}
if ([error code] != noErr) {
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value) {
recordedSuccessfully = [value boolValue];
}
}
}
- (void)playVideo:(NSURL *)url {
AVPlayer *player = [AVPlayer playerWithURL:url];
playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame = CGRectMake(, , 160, 284);
playerLayer.position = self.view.center;
[self.view.layer addSublayer:playerLayer];
playerLayer.masksToBounds = YES;
playerLayer.cornerRadius = 20;
playerLayer.borderWidth = 1;
playerLayer.borderColor = [UIColor grayColor].CGColor;
[player play];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(removePlayer)
name:AVPlayerItemDidPlayToEndTimeNotification
object:nil];
AVPlayer *player = [AVPlayer playerWithURL:url];
playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame = CGRectMake(, , 160, 284);
playerLayer.position = self.view.center;
[self.view.layer addSublayer:playerLayer];
playerLayer.masksToBounds = YES;
playerLayer.cornerRadius = 20;
playerLayer.borderWidth = 1;
playerLayer.borderColor = [UIColor grayColor].CGColor;
[player play];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(removePlayer)
name:AVPlayerItemDidPlayToEndTimeNotification
object:nil];
}
- (void)removePlayer {
[playerLayer removeFromSuperlayer];
[playerLayer removeFromSuperlayer];
}
看了下它的網絡數據格式方面,Blink主要是打包成zip文件,里面包含json,mp4,png文件.
等有空了,把服務器也寫一下,或者誰有興趣可以把它的服務器實現下.
當然Blink還有一些添加好友,分享等的功能,這些細節還是比較好實現的.
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!