iOS 录音和视频录制播放
2016-09-01 17:22
183 查看
提供一个全面具体的学习网址:http://www.cnblogs.com/kenshincui/p/4186022.html#uiImagePickerController
使用框架 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 *accordingView;
//这个只是我显示播放器的界面
@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];
下面附带一个
使用框架 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 *accordingView;
//这个只是我显示播放器的界面
@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];
下面附带一个
相关文章推荐
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列之二--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS -- 音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制