提供一个全面具体的学习网址:

使用框架 AVFoundation

一、录音

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

直接上代码:

if (_recoder == nil) {
        NSError *error = nil;
        _recoder = [[AVAudioRecorder alloc]initWithURL:[self setLocalRecordSoundsFile]  settings:[self setRecordSetting] error:&error];
        [_recoder prepareToRecord];
    }
 

 
#pragma mark 设置录音
- (void)setAudioSession
{
    NSError *error = nil;
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
    [session setActive:YES error:&error];
    
}
//设置本地文件路径
- (NSURL *)setLocalRecordSoundsFile
{
    NSString *urlPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    urlPath = [urlPath stringByAppendingString:kRecordFile];
    return [NSURL fileURLWithPath:urlPath];
}
//设置配置
- (NSDictionary *)setRecordSetting
{
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    //设置录音格式
    [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 = [[AVAudioPlayer alloc]initWithContentsOfURL:[self setLocalRecordSoundsFile]  error:&error];
        _audioPlayer.delegate = self;
        [_audioPlayer prepareToPlay];
    }
    return _audioPlayer;
}
AVAudioPlayer 初始化的时候 需要使用播放的网址,就只之前录音存储的文件地址

 用到的协议为AVAudioPlayerDelegate 里面的方法可以自己看一下 
我使用了 播放完成这个方法
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{ //如果成功,就停止播放
    if (flag) {
        [player stop];
    }
}
 目前,既可以录音有可以播放录制的声音了。 

二、录制视频
 
录制的视频的话有两种方法 
一种是使用相机来录制UIImagePickerController
获取相机权限,设置代理,在设置来源为摄像头,重要的一点 就是设置媒体类型为视频,设置摄像头捕获的模式为视频

直接上代码:
_picker = [[UIImagePickerController alloc]init];
  _picker.delegate = self;

 if ([UIImagePickerController isSourceTypeAvailable: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;
}
 
 
[self presentViewController:_picker animated:YES completion:nil];



#pragma mark UIImagePickerControllerDelegate 代理方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
    
    [picker dismissViewControllerAnimated:YES completion:nil];
    
    NSString *mediaType =  [info objectForKey:UIImagePickerControllerMediaType];
    
    if ([mediaType isEqualToString:@"public.image"]) { //如果媒体类型为图片
        //裁剪后的图片
        //    UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
        //原始图片
        UIImage *image2 = [info objectForKey:UIImagePickerControllerOriginalImage];
       
    }else if ([mediaType isEqualToString:@"public.movie"]){//如果媒体类型为视频
        _movieUrl = [info objectForKey:UIImagePickerControllerMediaURL];//获取视频的地址
    }
    NSLog(@"拍照,相片完成");
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [picker dismissViewControllerAnimated:YES completion: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;
 


首先需要请求权限 ,接下来就是设置上面定义的属性了
[self requestState:AVMediaTypeVideo];
  [self requestState:AVMediaTypeAudio];


#pragma mark 请求权限
- (BOOL)requestState:(NSString *)mediaType
{
    __block int tip = 0;
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
 
    [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) {
        if (!granted) {
            tip = 1;
        }
        dispatch_semaphore_signal(sema);
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    
    if (tip) {
        //YES  输出 1  NO 输出0
        NSLog(@"没有权限");
        return NO;
    }
    return YES;
}

//初始化 属性
- (void)initSubViews
{
    //初始化会话
    self.captureSession  = [[AVCaptureSession alloc]init];
    [self.captureSession setSessionPreset:AVCaptureSessionPresetHigh];

    //获得输入设备 后置摄像头和麦克风 一般情况下使用默认的就可以了
    AVCaptureDevice *videoDevice  = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    
    //根据输入设备初始化设备输入对象,用于获得输入数据
    NSError *error = nil;
    self.videoInput = [[AVCaptureDeviceInput alloc]initWithDevice:videoDevice error:&error];
    self.audioInput= [[AVCaptureDeviceInput alloc]initWithDevice:audioDevice error:&error];
    
     //将设备输入添加到会话中
    if ([self.captureSession canAddInput:self.videoInput]) {
        [self.captureSession addInput:self.videoInput];
    }
    if ([self.captureSession canAddInput:self.audioInput]) {
        [self.captureSession addInput:self.audioInput];
    }

    //初始化设备输出对象,用于获得输出数据
    self.movieFileOutput = [[AVCaptureMovieFileOutput alloc]init];
     //将设备输出添加到会话中
    if ([self.captureSession canAddOutput:self.movieFileOutput]) {
        [self.captureSession addOutput:self.movieFileOutput];
    }

//    连接输出设备
    self.videoConnection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    if ([self.videoConnection isVideoStabilizationSupported]) {//录制的稳定
        self.videoConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
    }
   
     //创建视频预览层,用于实时展示摄像头状态
    self.capturePreviewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.captureSession];
    self.capturePreviewLayer.frame = self.layer.bounds; //设置预览界面等于自定义UIView 大小
    self.layer.masksToBounds = YES;
 [self.capturePreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];//设置为
    //将视频预览视图 添加到界面中
    [self.layer insertSublayer:self.capturePreviewLayer atIndex:0];
}
 

 准备录制视频 

- (void)startRecordVideo
{
    AVCaptureConnection *connection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    if (![self.captureSession isRunning]) { //如果捕获会话没有运行
        [self.captureSession startRunning];
    }
     //根据连接取得设备输出的数据
    if (![self.movieFileOutput isRecording]) { //如果输出 没有录制
        //如果支持多任务则则开始多任务
        if ([[UIDevice currentDevice] isMultitaskingSupported]) {
            self.backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
        }
        //预览图层和视频方向保持一致
        connection.videoOrientation = [self.capturePreviewLayer connection].videoOrientation;
    //开始录制视频使用到了代理 AVCaptureFileOutputRecordingDelegate 同时还有录制视频保存的文件地址的
        [self.movieFileOutput startRecordingToOutputFileURL:self.localMovieUrl recordingDelegate:self];
    }
 } 

停止录制
-(void)stopRecordVideo
{
    if ([self.movieFileOutput isRecording]) {
        [self.movieFileOutput stopRecording];
    }//把捕获会话也停止的话,预览视图就停了 
    if ([self.captureSession isRunning]) {
        [self.captureSession stopRunning];
    }
}
 

#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 = [[ALAssetsLibrary alloc]init];
        [assetLibrary writeVideoAtPathToSavedPhotosAlbum:outputFileURL completionBlock:^(NSURL *assetURL, NSError *error) {
            if (error) {
                NSLog(@"保存到相簿失败");
            }
            if (backgroundTask != UIBackgroundTaskInvalid) {
                [[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
            }
        }];
}
 

#pragma mark 设置视频保存地址
- (NSURL *)localMovieUrl
{
    if (_localMovieUrl == nil) {
        //一个临时的地址   如果使用NSUserDefault 存储的话,重启app还是能够播放 
        NSString *outputFilePath=[NSTemporaryDirectory() stringByAppendingString:@"myMovie.mov"];
        NSURL *fileUrl=[NSURL fileURLWithPath:outputFilePath];
        _localMovieUrl = fileUrl;
    }
    return _localMovieUrl;
}
 

说一下我在外面调用的这个吧
@property (nonatomic, strong) RecordView *revordView; //我自定义的界面
 

self.revordView = [[RecordView alloc]initWithFrame:CGRectMake(0, kRecordTopSpaceHeight, kScreenWidth, kRecordViewHeight)];
    [self.revordView.captureSession startRunning];
    [self addSubview: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 = [[MPMoviePlayerController alloc]init];
        _player.controlStyle = MPMovieControlStyleEmbedded;//嵌入 还有其他模式
        _player.shouldAutoplay = YES; //自动播放
        _player.scalingMode = MPMovieScalingModeAspectFill;//方向满足
        _player.movieSourceType = MPMovieSourceTypeFile;
        _player.view.backgroundColor = [UIColor whiteColor];
        _player.view.frame = CGRectMake(0, 400, kScreenWidth, kRecordViewHeight);
//这个需要添加一个通知MPMoviePlayerPlaybackDidFinishNotification 播放完成
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinish) name:MPMoviePlayerPlaybackDidFinishNotification object:_player];
    }
    return _player;
}

- (void)playFinish
{ //播放完成 我设置文件地址为Nil
    [self.player setContentURL:nil];
}
//这个播放的路径 开始播放 播放器同样有 play pause stop 等类似方法

[self.player setContentURL:self.localMovieUrl];
        [self.player play];

下面说

AVPlayer

AVPlayer 本身并不能播放视频,需要用到一个类 去完成 AVPlayerLayer
@property (nonatomic, strong) AVPlayer *avPlayer;
@property (nonatomic, strong) UIView //这个只是我显示播放器的界面
@property (nonatomic, strong) AVPlayerLayer *playerLayer;
 


- (UIView *)accordingView
{
    if (_accordingView == nil) {
        _accordingView = [[UIView alloc]initWithFrame:CGRectMake(0, 70, kScreenWidth, kRecordViewHeight)];
        _accordingView.backgroundColor = [UIColor grayColor];
    }
    return _accordingView;
}
 [self.view addSubview:self.accordingView];
 

AVPlayer 没有代理方法 只有通知 通过AVPlayerItemDidPlayToEndTimeNotification 了解播放完成
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerFinish) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
 

- (void)playerFinish
{
    NSLog(@"avplayer 播放完成");
    [self.avPlayer pause]; //先暂停
    [self.avPlayer seekToTime:kCMTimeZero];//设置时间为开始
    [self.avPlayer play]; //播放
}
 


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

AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:self.videoRecord.localMovieUrl];
        if (!self.avPlayer) {
            self.avPlayer = [AVPlayer playerWithPlayerItem:playerItem];
        }else{
            [self.avPlayer replaceCurrentItemWithPlayerItem:playerItem];
        }
        
        if (!self.playerLayer) {
            self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
            self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
            self.playerLayer.frame = self.accordingView.bounds;
            [self.accordingView.layer insertSublayer:self.playerLayer atIndex:0];
        }
        [self.avPlayer play];

下面附带一个