录制视频(无帧数版) IOS

本文详细介绍了如何通过代码更改实现视频录制功能,包括设置前置摄像头、后置摄像头、开始录制、停止录制等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用网上提供的获取每一帧的代码更改过来的。

//
// GLRecord.h
// PlayVideo
//
// Created by Ghost on 12-8-18.
// Copyright (c) 2012年 ZEPPLAB. All rights reserved.
//

#import <UIKit/UIKit.h>

#import <AVFoundation/AVFoundation.h>
#undef PRODUCER_HAS_VIDEO_CAPTURE
#define PRODUCER_HAS_VIDEO_CAPTURE (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 && TARGET_OS_EMBEDDED)
@protocol GLRecordDelegate ;
@interface GLRecord : NSObject
#if PRODUCER_HAS_VIDEO_CAPTURE
<AVCaptureFileOutputRecordingDelegate>
#endif
{
@private
  BOOL m_frontCamera;
  BOOL m_started;
  NSString *m_nameStr ;
  UIView* m_preview;
  id<GLRecordDelegate> outDelegate ;
#if PRODUCER_HAS_VIDEO_CAPTURE
  AVCaptureSession* m_captureSession;
  AVCaptureDevice *m_captureDevice;
  AVCaptureMovieFileOutput *m_captureMovieFileOutput ;
#endif
}
// 单例模式
+ (GLRecord*)shareGLRecord;
+ (void)closeCamera;
// 设置前置摄像头
- (BOOL)setFrontCamera;
// 设置后置摄像头
- (BOOL)setBackCamera;
// 开始前设置捕获参数
- (void)prepareVideoCaptureFrontCamera:(BOOL) v_bfront andPreview:(UIView*) v_view;
// 启动显示
- (void)startVideoCapture;
// 停止显示
- (void)stopVideoCapture;
// 开始录制
- (void)startRecording ;
// 停止录制
- (void)stopRecording ;
// 重置录制
- (void)resetRecording ;
// 设置要显示到得View
- (void)setPreview: (UIView*)v_preview;
// 设置数据输出
- (void)setVideoFileOutput:(id<GLRecordDelegate>)delegate;
// 设置文件保存名称
- (void)setVideoFileName:(NSString *) v_nameStr ;
@end

@protocol GLRecordDelegate
- (void) capture:(GLRecord *) glRecord didFailWithError:(NSError *)error;
- (void) captureRecordingBegan:(GLRecord *) glRecord;
- (void) captureRecordingFinished:(GLRecord *) glRecord;
@end
------------------------------------------------------------------------
//
// GLRecord.m
// PlayVideo
//
// Created by Ghost on 12-8-18.
// Copyright (c) 2012年 ZEPPLAB. All rights reserved.
//
#import "GLRecord.h"
//
// Private
//
@interface GLRecord(Private)

#define TEMP_MOVE_NAME @"TEMP_FILE.MOV"


#if PRODUCER_HAS_VIDEO_CAPTURE
+(AVCaptureDevice *)cameraAtPosition:(AVCaptureDevicePosition)position;
+ (NSURL *) tempFileURL ;
- (void)startPreview ;
- (void)stopPreview ;
#endif

@end

@implementation GLRecord (Private)

#if PRODUCER_HAS_VIDEO_CAPTURE
+ (AVCaptureDevice *)cameraAtPosition:(AVCaptureDevicePosition)position{
NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in cameras){
if (device.position == position){
return device;
}
}
return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
}

+ (AVCaptureConnection *)connectionWithMediaType:(NSString *)mediaType fromConnections:(NSArray *)connections
{
for ( AVCaptureConnection *connection in connections ) {
  for ( AVCaptureInputPort *port in [connection inputPorts] ) {
    if ( [[port mediaType] isEqual:mediaType] ) {
      return connection;
    }
  }
}
return nil;
}

+ (NSURL *) tempFileURL {
return [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), TEMP_MOVE_NAME]];
}

- (void)startPreview{
if(m_captureSession && m_preview && m_started){
  AVCaptureVideoPreviewLayer* previewLayer = [AVCaptureVideoPreviewLayer layerWithSession: m_captureSession];
  previewLayer.frame = m_preview.bounds;
  previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
  //   if(previewLayer.orientationSupported){
  //     previewLayer.orientation = mOrientation;
  //   }
  [m_preview.layer addSublayer: previewLayer];
 
  if(![m_captureSession isRunning]){
    [m_captureSession startRunning];
  }
}
}

- (void)stopPreview{
if(m_captureSession){  
  if([m_captureSession isRunning]){
    [m_captureSession stopRunning];
   
    // remove all sublayers
    if(m_preview){
      for(CALayer *ly in m_preview.layer.sublayers){
        if([ly isKindOfClass: [AVCaptureVideoPreviewLayer class]])
          {
          [ly removeFromSuperlayer];
          break;
          }
      }
    }
  }
}
}
#endif
@end

@implementation GLRecord
static GLRecord* g_camera = 0;
- (id)init
{
if(g_camera)
  return g_camera;
else
  {
  if(self = [super init])
    {
    self->m_frontCamera = NO;
    self->m_started = NO;
    g_camera = self;
    outDelegate = nil;
    }
  return g_camera;
  }
}
-(void)dealloc
{
#if PRODUCER_HAS_VIDEO_CAPTURE
[m_captureSession release];
[m_captureDevice release];
[m_captureMovieFileOutput release];
[m_preview release];
#endif
[super dealloc];
}
+ (GLRecord*)shareGLRecord
{
if(!g_camera)
  g_camera = [[GLRecord alloc] init];
return g_camera;
}
+ (void)closeCamera
{
if(g_camera)
  {
  [g_camera dealloc];
  g_camera = nil;
  }
}
- (void)prepareVideoCaptureFrontCamera:(BOOL) v_bfront andPreview:(UIView*) v_view
{
self->m_frontCamera = v_bfront;
if(v_view)
  self->m_preview = [v_view retain];
#if PRODUCER_HAS_VIDEO_CAPTURE
if([m_captureSession isRunning])
  {
  [self stopVideoCapture];
  [self startVideoCapture];
  }
#endif
}
- (void)startVideoCapture
{
#if PRODUCER_HAS_VIDEO_CAPTURE
//防锁
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
//打开摄像设备,并开始捕抓图像
//[labelState setText:@"Starting Video stream"];
if(m_captureDevice || m_captureSession || m_captureMovieFileOutput)
  {
  NSLog(@"Already capturing");
  return;
  }

if((m_captureDevice = [GLRecord cameraAtPosition:m_frontCamera? AVCaptureDevicePositionFront:AVCaptureDevicePositionBack]) == nil)
  {
  NSLog(@"Failed to get valide capture device");
  return;
  }

NSError *error = nil;
AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:m_captureDevice error:&error];
if (!videoInput)
  {
  NSLog(@"Failed to get video input");
  m_captureDevice = nil;
return;
  }

m_captureSession = [[AVCaptureSession alloc] init];

m_captureSession.sessionPreset = AVCaptureSessionPreset640x480;
if ([m_captureSession canAddInput:videoInput]) {
  [m_captureSession addInput:videoInput];  
}



m_captureMovieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
if ([m_captureSession canAddOutput:m_captureMovieFileOutput])
  [m_captureSession addOutput:m_captureMovieFileOutput];

if (![self recordsVideo]) {
  NSString *localizedDescription = NSLocalizedString(@"Video recording unavailable", @"Video recording unavailable description");
  NSString *localizedFailureReason = NSLocalizedString(@"Movies recorded on this device will only contain audio. They will be accessible through iTunes file sharing.", @"Video recording unavailable failure reason");
  NSDictionary *errorDict = [NSDictionary dictionaryWithObjectsAndKeys:
                localizedDescription, NSLocalizedDescriptionKey,
                localizedFailureReason, NSLocalizedFailureReasonErrorKey,
                nil];
  NSError *noVideoError = [NSError errorWithDomain:@"AVCam" code:0 userInfo:errorDict];
  if (outDelegate && [outDelegate respondsToSelector:@selector(capture:didFailWithError:)]) {
    [outDelegate capture:self didFailWithError:noVideoError];
  }
}
#if 0
//
// // Currently, the only supported key is kCVPixelBufferPixelFormatTypeKey. Recommended pixel format choices are
// // kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange or kCVPixelFormatType_32BGRA.
// // On iPhone 3G, the recommended pixel format choices are kCVPixelFormatType_422YpCbCr8 or kCVPixelFormatType_32BGRA.
// //
// AVCaptureVideoDataOutput *avCaptureVideoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
//
// NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
// NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
// NSDictionary* settings = [NSDictionary dictionaryWithObject:value forKey:key];
// // NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
// //               //[NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange], //kCVPixelBufferPixelFormatTypeKey,
// //               [NSNumber numberWithInt: mWidth], (id)kCVPixelBufferWidthKey,
// // [NSNumber numberWithInt: mHeight], (id)kCVPixelBufferHeightKey,
// //               nil];
//
// avCaptureVideoDataOutput.videoSettings = settings;
// //[settings release];
// // avCaptureVideoDataOutput.minFrameDuration = CMTimeMake(1, 1.0f/30);
// avCaptureVideoDataOutput.alwaysDiscardsLateVideoFrames = YES;
//
//
//
// dispatch_queue_t queue = dispatch_queue_create("com.gh.cecall", NULL);
// [avCaptureVideoDataOutput setSampleBufferDelegate:self queue:queue];
// [m_captureSession addOutput:avCaptureVideoDataOutput];
// [settings release];
// [avCaptureVideoDataOutput release];
// dispatch_release(queue);
#endif
m_started = YES;
//start preview
[self startPreview];

#endif
}
- (void)stopVideoCapture
{
#if PRODUCER_HAS_VIDEO_CAPTURE
if(m_captureSession){
  [m_captureSession stopRunning];
  [m_captureSession release], m_captureSession = nil;
  NSLog(@"Video capture stopped");
}
[m_captureDevice release], m_captureDevice = nil;
[m_captureMovieFileOutput release], m_captureMovieFileOutput = nil ;
if(m_preview){
  for (UIView *view in m_preview.subviews) {
    [view removeFromSuperview];
  }
}
#endif
}
-(BOOL)recordsVideo
{
AVCaptureConnection *videoConnection = [GLRecord connectionWithMediaType:AVMediaTypeVideo fromConnections:m_captureMovieFileOutput.connections];

return [videoConnection isActive];
}
-(void)startRecording
{
AVCaptureConnection *videoConnection = [GLRecord connectionWithMediaType:AVMediaTypeVideo fromConnections:m_captureMovieFileOutput.connections] ;
// if ([videoConnection isVideoOrientationSupported])
// 此处保存的视频可以更换宽高AVCaptureVideoOrientationPortrait||AVCaptureVideoOrientationLandscapeRight
[videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];

NSURL *outputFileUrl = [GLRecord tempFileURL] ;
// 生成缓存文件

[m_captureMovieFileOutput startRecordingToOutputFileURL:outputFileUrl recordingDelegate:self];
}

-(void)stopRecording
{
[m_captureMovieFileOutput stopRecording];
}

- (void) resetRecording {
[m_captureMovieFileOutput stopRecording];
// 移除缓存文件



}

- (BOOL)setFrontCamera
{
if(m_frontCamera)
  return YES;
[self stopVideoCapture];
m_frontCamera = YES;
[self startVideoCapture];
return YES;
}

- (BOOL)setBackCamera{
if(!m_frontCamera)
  return YES;
[self stopVideoCapture];
m_frontCamera = NO;
[self startVideoCapture];
return YES;
}

- (void) setPreview: (UIView*)v_preview{
#if PRODUCER_HAS_VIDEO_CAPTURE
if(v_preview == nil){
  // stop preview
  [self stopPreview];
  // remove layers
  if(m_preview){
    for(CALayer *ly in m_preview.layer.sublayers){
      if([ly isKindOfClass: [AVCaptureVideoPreviewLayer class]]){
        [ly removeFromSuperlayer];
        break;
      }
    }
    [m_preview release], m_preview = nil;
  }
}
else {
  //start preview
if (m_preview) {
[m_preview release];
m_preview = nil;
}
  if((m_preview = [v_preview retain])){
    [self startPreview];
  }
}

#endif
}
- (void)setVideoFileOutput:(id<GLRecordDelegate>)delegate
{
outDelegate = delegate;
}
// 设置文件保存名称
- (void)setVideoFileName:(NSString *) v_nameStr {
if (m_nameStr) {
  [m_nameStr release];
  m_nameStr = nil ;
}
m_nameStr = [v_nameStr retain];
}
#pragma mark -
#pragma mark AVCaptureFileOutputRecordingDelegate
#if PRODUCER_HAS_VIDEO_CAPTURE
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections {
NSLog(@"begin");
if (outDelegate && [outDelegate respondsToSelector:@selector(captureRecordingBegan:)]) {
  [outDelegate captureRecordingBegan:self];
}
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error {
NSLog(@"finish");
if (!m_nameStr) {
  return ;
}
// 进行文件复制
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *strMovPath = [docDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov",m_nameStr]];

NSFileManager *fm = [[NSFileManager alloc] init];
// 是否存在
BOOL isExistsOk = [fm fileExistsAtPath:[[GLRecord tempFileURL] path]];
NSLog(@"文件 %d 存在",isExistsOk);
BOOL isCopyOk ;
if (isExistsOk) {
  // 进行copy
  isCopyOk = [fm copyItemAtURL:[GLRecord tempFileURL] toURL:[NSURL fileURLWithPath:strMovPath] error:&error];
  NSLog(@"复制 %d",isCopyOk);
  // 不管成功还是失败。都删除这个缓存
  BOOL isDeleteOk = [fm removeItemAtURL:[GLRecord tempFileURL] error:nil];
  NSLog(@"删除缓存 %d",isDeleteOk);
}
if (!isCopyOk || !isExistsOk) {
  if (outDelegate && [outDelegate respondsToSelector:@selector(capture:didFailWithError:)]) {
    [outDelegate capture:self didFailWithError:error];
  }
}else {
  if (outDelegate && [outDelegate respondsToSelector:@selector(captureRecordingFinished:)]) {
    [outDelegate captureRecordingFinished:self];
  }
}

[fm release];
}
#endif
@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值