iOS 录音和视频录制播放

来源:互联网 发布:梦想小镇mac同步ios 编辑:程序博客网 时间:2024/05/17 06:08

提供一个全面具体的学习网址:http://www.cnblogs.com/kenshincui/p/4186022.html#uiImagePickerController

使用框架 AVFoundation

一、录音

录音使用AVAudioRecorder  里面使用了AVAudioSession 声音会话,还有录音的配置

直接上代码:

if (_recoder ==nil) {

        NSError *error =nil;

        _recoder = [[AVAudioRecorderalloc]initWithURL:[selfsetLocalRecordSoundsFile] settings:[selfsetRecordSetting] error:&error];

        [_recoderprepareToRecord];

    }


#pragma mark 设置录音

- (void)setAudioSession

{

    NSError *error =nil;

    AVAudioSession *session = [AVAudioSessionsharedInstance];

    [session setCategory:AVAudioSessionCategoryPlayAndRecorderror:&error];

    [session setActive:YESerror:&error];

    

}

//设置本地文件路径

- (NSURL *)setLocalRecordSoundsFile

{

    NSString *urlPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject];

    urlPath = [urlPathstringByAppendingString:kRecordFile];

    return [NSURLfileURLWithPath:urlPath];

}

//设置配置

- (NSDictionary *)setRecordSetting

{

    NSMutableDictionary *dic = [NSMutableDictionarydictionary];

    //设置录音格式

    [dic setObject:@(kAudioFormatLinearPCM)forKey:AVFormatIDKey];

    //设置录音采样率 8000shi电话采样率 对于一般录音已经够了

    [dic setObject:@(44100)forKey:AVSampleRateKey];

    //设置通道,这里采用单通道

    [dic setObject:@(1)forKey:AVNumberOfChannelsKey];

    //每个采样点位数分别为 8 16 24 32

    [dic setObject:@(8)forKey:AVLinearPCMBitDepthKey];

    //是否采用浮点数采样

    [dic setObject:@(YES)forKey:AVLinearPCMIsFloatKey];

    return dic;

}

1、先设置声音会话,为录制和播放,激活。

2、设置录制的文件

3、设置录音的配置格式为字典

4、初始化录音配置

AVAudioRecorder的方法有 :

record 录制

pause 暂停录制

stop  停止录制

isRecording 判断是否正在录制。


好了录音就可以运行了。


录完音了,总的需要播放吧,简单的就使用AVAudioPlayer这个播放器了

直接上代码:

- (AVAudioPlayer *)audioPlayer

{

    if (_audioPlayer ==nil) {

        NSError *error =nil;

        _audioPlayer = [[AVAudioPlayeralloc]initWithContentsOfURL:[selfsetLocalRecordSoundsFile] error:&error];

        _audioPlayer.delegate =self;

        [_audioPlayerprepareToPlay];

    }

    return_audioPlayer;

}

AVAudioPlayer 初始化的时候 需要使用播放的网址,就只之前录音存储的文件地址


用到的协议为AVAudioPlayerDelegate 里面的方法可以自己看一下

我使用了 播放完成这个方法

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag

{ //如果成功,就停止播放

    if (flag) {

        [player stop];

    }

}

目前,既可以录音有可以播放录制的声音了。


二、录制视频

录制的视频的话有两种方法

一种是使用相机来录制UIImagePickerController

获取相机权限,设置代理,在设置来源为摄像头,重要的一点 就是设置媒体类型为视频,设置摄像头捕获的模式为视频


直接上代码:

_picker = [[UIImagePickerControlleralloc]init];

  _picker.delegate =self;

 if ([UIImagePickerControllerisSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {

                _picker.sourceType =UIImagePickerControllerSourceTypeCamera;//来源为摄像头

_picker.mediaTypes = @[(NSString *)kUTTypeMovie];// 重点 是设置媒体类型为视频 电影 类型为数组

//这个设置需要导入#import <MobileCoreServices/MobileCoreServices.h> 或者你也可以不导入直接设置为_picker.mediaTypes = @[@"public.movie"];

  _picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;//设置为录制模式

//下面为默认设置

                _picker.videoMaximumDuration =10;//录制时间

                _picker.videoQuality =UIImagePickerControllerQualityTypeMedium;//质量

                _picker.showsCameraControls =YES;//显示摄像头控制面板 设置为NO 使用cameraOverlayView 自定义界面

// picker.cameraOverlayView摄像头上覆盖的视图,可用通过这个视频来自定义拍照或录像界面


                //摄像头 前置/后置

                _picker.cameraDevice =UIImagePickerControllerCameraDeviceRear;

                //闪光灯模式自动

                _picker.cameraFlashMode =UIImagePickerControllerCameraFlashModeAuto;

}

[selfpresentViewController:_pickeranimated:YEScompletion:nil];



#pragma mark UIImagePickerControllerDelegate 代理方法

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info

{

    

    [picker dismissViewControllerAnimated:YEScompletion:nil];

    

    NSString *mediaType =  [infoobjectForKey:UIImagePickerControllerMediaType];

    

    if ([mediaTypeisEqualToString:@"public.image"]) {//如果媒体类型为图片

        //裁剪后的图片

        //    UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];

        //原始图片

        UIImage *image2 = [infoobjectForKey:UIImagePickerControllerOriginalImage];

      

    }elseif ([mediaType isEqualToString:@"public.movie"]){//如果媒体类型为视频

        _movieUrl = [infoobjectForKey:UIImagePickerControllerMediaURL];//获取视频的地址

    }

    NSLog(@"拍照,相片完成");

}

-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

{

    [picker dismissViewControllerAnimated:YEScompletion:nil];

}

一个简易的视频录制就完成了,当然这只是完成功能了,在项目中的需求肯定要求高了。


三、下面就说一个可定制的录制视频


事先声明,我这个是自定义了一个UIView 把定义的录制视频 放到里面去了。可以在外面定义这个UIView 的大小。

AVCaptureSession 捕获的会话

AVCaptureDeviceInput 捕获的设备输入(两个一个声音audio,一个视频video)

AVCaptureMovieFileOutput 捕获的视频文件输出

AVCaptureConnection 视频的链接(大概或者就是这个意思)

AVCaptureVideoPreviewLayer 摄像头的实时界面

UIBackgroundTaskIdentifier 后台任务标识符


@interface RecordView ()<AVCaptureFileOutputRecordingDelegate>

//捕捉会话

@property (nonatomic,strong) AVCaptureSession *captureSession;

//视频音频是设备输入

@property (nonatomic,strong) AVCaptureDeviceInput *videoInput;

@property (nonatomic,strong) AVCaptureDeviceInput *audioInput;

//音频视频数据输出

@property (nonatomic,strong) AVCaptureMovieFileOutput *movieFileOutput;//保存到相簿电影文件输出

//音频视频连接

@property (nonatomic,strong) AVCaptureConnection *videoConnection;

@property (nonatomic,strong) AVCaptureConnection *audioConnection;

//展示的摄像头界面

@property (nonatomic,strong) AVCaptureVideoPreviewLayer *capturePreviewLayer;

//后台任务标示符

@property (nonatomic,assign) UIBackgroundTaskIdentifier backgroundTaskIdentifier;



首先需要请求权限 ,接下来就是设置上面定义的属性了

[selfrequestState:AVMediaTypeVideo];

  [selfrequestState:AVMediaTypeAudio];


#pragma mark 请求权限

- (BOOL)requestState:(NSString *)mediaType

{

    __blockint tip = 0;

    dispatch_semaphore_t sema =dispatch_semaphore_create(0);

 

    [AVCaptureDevicerequestAccessForMediaType:mediaTypecompletionHandler:^(BOOL granted) {

        if (!granted) {

            tip = 1;

        }

        dispatch_semaphore_signal(sema);

    }];

    dispatch_semaphore_wait(sema,DISPATCH_TIME_FOREVER);

    

    if (tip) {

        //YES  输出 1  NO输出0

        NSLog(@"没有权限");

        returnNO;

    }

    returnYES;

}


//初始化 属性

- (void)initSubViews

{

    //初始化会话

    self.captureSession  = [[AVCaptureSessionalloc]init];

    [self.captureSessionsetSessionPreset:AVCaptureSessionPresetHigh];


    //获得输入设备后置摄像头和麦克风 一般情况下使用默认的就可以了

    AVCaptureDevice *videoDevice  = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];

    AVCaptureDevice *audioDevice = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeAudio];

    

    //根据输入设备初始化设备输入对象,用于获得输入数据

    NSError *error =nil;

    self.videoInput = [[AVCaptureDeviceInputalloc]initWithDevice:videoDeviceerror:&error];

    self.audioInput= [[AVCaptureDeviceInputalloc]initWithDevice:audioDeviceerror:&error];

    

     //将设备输入添加到会话中

    if ([self.captureSessioncanAddInput:self.videoInput]) {

        [self.captureSessionaddInput:self.videoInput];

    }

    if ([self.captureSessioncanAddInput:self.audioInput]) {

        [self.captureSessionaddInput:self.audioInput];

    }


    //初始化设备输出对象,用于获得输出数据

    self.movieFileOutput = [[AVCaptureMovieFileOutputalloc]init];

     //将设备输出添加到会话中

    if ([self.captureSessioncanAddOutput:self.movieFileOutput]) {

        [self.captureSessionaddOutput:self.movieFileOutput];

    }


//    连接输出设备

    self.videoConnection = [self.movieFileOutputconnectionWithMediaType:AVMediaTypeVideo];

    if ([self.videoConnectionisVideoStabilizationSupported]) {//录制的稳定

        self.videoConnection.preferredVideoStabilizationMode =AVCaptureVideoStabilizationModeAuto;

    }

  

     //创建视频预览层,用于实时展示摄像头状态

    self.capturePreviewLayer = [[AVCaptureVideoPreviewLayeralloc]initWithSession:self.captureSession];

    self.capturePreviewLayer.frame =self.layer.bounds;//设置预览界面等于自定义UIView 大小

    self.layer.masksToBounds =YES;

    [self.capturePreviewLayersetVideoGravity:AVLayerVideoGravityResizeAspectFill];//设置为

    //将视频预览视图添加到界面中

    [self.layerinsertSublayer:self.capturePreviewLayeratIndex:0];

}


准备录制视频


- (void)startRecordVideo

{

    AVCaptureConnection *connection = [self.movieFileOutputconnectionWithMediaType:AVMediaTypeVideo];

    if (![self.captureSessionisRunning]) {//如果捕获会话没有运行

        [self.captureSessionstartRunning];

    }

     //根据连接取得设备输出的数据

    if (![self.movieFileOutputisRecording]) {//如果输出 没有录制

        //如果支持多任务则则开始多任务

        if ([[UIDevicecurrentDevice] isMultitaskingSupported]) {

            self.backgroundTaskIdentifier = [[UIApplicationsharedApplication] beginBackgroundTaskWithExpirationHandler:nil];

        }

        //预览图层和视频方向保持一致

        connection.videoOrientation = [self.capturePreviewLayerconnection].videoOrientation;

    //开始录制视频使用到了代理 AVCaptureFileOutputRecordingDelegate 同时还有录制视频保存的文件地址的

        [self.movieFileOutputstartRecordingToOutputFileURL:self.localMovieUrlrecordingDelegate:self];

    }

}


停止录制

-(void)stopRecordVideo

{

    if ([self.movieFileOutputisRecording]) {

        [self.movieFileOutputstopRecording];

    }//把捕获会话也停止的话,预览视图就停了

    if ([self.captureSessionisRunning]) {

        [self.captureSessionstopRunning];

    }

}


#pragma mark    AVCaptureFileOutputRecordingDelegate 实现代理

- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections

{

    NSLog(@"开始录制");

}

-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error

{

    NSLog(@"完成录制");

 

        //视频录入完成之后在后台将视频存储到相簿

        UIBackgroundTaskIdentifier backgroundTask =self.backgroundTaskIdentifier;

        self.backgroundTaskIdentifier =UIBackgroundTaskInvalid;

        

//这个是保存视频到相簿 需要导入#import<AssetsLibrary/AssetsLibrary.h>

        ALAssetsLibrary *assetLibrary = [[ALAssetsLibraryalloc]init];

        [assetLibrary writeVideoAtPathToSavedPhotosAlbum:outputFileURLcompletionBlock:^(NSURL *assetURL,NSError *error) {

            if (error) {

                NSLog(@"保存到相簿失败");

            }

            if (backgroundTask !=UIBackgroundTaskInvalid) {

                [[UIApplicationsharedApplication] endBackgroundTask:backgroundTask];

            }

        }];

}


#pragma mark 设置视频保存地址

- (NSURL *)localMovieUrl

{

    if (_localMovieUrl ==nil) {

        //一个临时的地址  如果使用NSUserDefault 存储的话,重启app还是能够播放

        NSString *outputFilePath=[NSTemporaryDirectory()stringByAppendingString:@"myMovie.mov"];

        NSURL *fileUrl=[NSURLfileURLWithPath:outputFilePath];

        _localMovieUrl = fileUrl;

    }

    return_localMovieUrl;

}


说一下我在外面调用的这个吧

@property (nonatomic,strong) RecordView *revordView; //我自定义的界面


self.revordView = [[RecordViewalloc]initWithFrame:CGRectMake(0,kRecordTopSpaceHeight, kScreenWidth,kRecordViewHeight)];

    [self.revordView.captureSessionstartRunning];

    [selfaddSubview:self.revordView];

这只是我任意设置的

#define kScreenWidth            CGRectGetWidth([UIScreen mainScreen].bounds)

#define kScreenHeight           CGRectGetHeight([UIScreen mainScreen].bounds)

#define kRecordViewHeight       250

#define kRecordTopSpaceHeight   20



至此录制视频完成了,当然只是功能,具体还要根据实际情况设置。


下面就该说播放视频了

播放视频的方式同样有两个

MPMoviePlayerController 以及 AVPlayer


MPMoviePlayerController 需要导入#import<MediaPlayer/MediaPlayer.h>

- (MPMoviePlayerController *)player

{

    

    //设置播放器的大小跟预览视图的大小一样,模式也一样

    if (_player ==nil) {

        _player = [[MPMoviePlayerControlleralloc]init];

        _player.controlStyle =MPMovieControlStyleEmbedded;//嵌入 还有其他模式

        _player.shouldAutoplay =YES;//自动播放

        _player.scalingMode =MPMovieScalingModeAspectFill;//方向满足

        _player.movieSourceType =MPMovieSourceTypeFile;

        _player.view.backgroundColor = [UIColorwhiteColor];

        _player.view.frame =CGRectMake(0,400, kScreenWidth,kRecordViewHeight);

//这个需要添加一个通知MPMoviePlayerPlaybackDidFinishNotification 播放完成

        [[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(playFinish)name:MPMoviePlayerPlaybackDidFinishNotificationobject:_player];

    }

    return_player;

}

- (void)playFinish

{ //播放完成 我设置文件地址为Nil

    [self.playersetContentURL:nil];

}

//这个播放的路径 开始播放 播放器同样有 play pause stop 等类似方法

[self.playersetContentURL:self.localMovieUrl];

        [self.playerplay];


下面说 AVPlayer

AVPlayer 本身并不能播放视频,需要用到一个类 去完成AVPlayerLayer

@property (nonatomic,strong) AVPlayer *avPlayer;

@property (nonatomic,strong) UIView *accordingView;//这个只是我显示播放器的界面

@property (nonatomic,strong) AVPlayerLayer *playerLayer;


- (UIView *)accordingView

{

    if (_accordingView ==nil) {

        _accordingView = [[UIViewalloc]initWithFrame:CGRectMake(0,70, kScreenWidth,kRecordViewHeight)];

        _accordingView.backgroundColor = [UIColorgrayColor];

    }

    return_accordingView;

}

 [self.viewaddSubview:self.accordingView];


AVPlayer 没有代理方法 只有通知 通过AVPlayerItemDidPlayToEndTimeNotification 了解播放完成

 [[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(playerFinish)name:AVPlayerItemDidPlayToEndTimeNotificationobject:nil];


- (void)playerFinish

{

    NSLog(@"avplayer播放完成");

    [self.avPlayerpause];//先暂停

    [self.avPlayerseekToTime:kCMTimeZero];//设置时间为开始

    [self.avPlayerplay];//播放

}



//这个是初始化播放器的方法用到的参数,可以设置不同的 AVPlayerItem 去播放不同的视频

//可以使用replaceCurrentItemWithPlayerItem 方法更新播放的视频

AVPlayerItem *playerItem = [AVPlayerItemplayerItemWithURL:self.videoRecord.localMovieUrl];

        if (!self.avPlayer) {

            self.avPlayer = [AVPlayerplayerWithPlayerItem:playerItem];

        }else{

            [self.avPlayerreplaceCurrentItemWithPlayerItem:playerItem];

        }

        

        if (!self.playerLayer) {

            self.playerLayer = [AVPlayerLayerplayerLayerWithPlayer:self.avPlayer];

            self.playerLayer.videoGravity =AVLayerVideoGravityResizeAspectFill;

            self.playerLayer.frame =self.accordingView.bounds;

            [self.accordingView.layerinsertSublayer:self.playerLayeratIndex:0];

        }

        [self.avPlayerplay];


下面附带一个
























0 0