音视频
音效
-
1.iOS中音乐可以暂停,音效不能操作;而且音效可以立即播放,加载到本地,而音乐需要缓冲,边下边播.在iOS中只有小于30s的音乐才可以使用音效的方式进行播放.
-
2.播放音效的实现思路:初始化soundID -> 获取音频文件的本地路径(NSURL类型) ->创建soundID -> 进行播放.
音效播放的优化:以键值对的形式对音频文件和对应的soundID进行缓存,获取之前先判断对应的soundID是否已经在,存在的话直接在内存中取,不存在才创建: SystemSoundID systemSoundID; NSURL *url = [[NSBundle mainBundle] URLForResource:@"buyao.caf" withExtension:nil]; AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &systemSoundID); AudioServicesPlaySystemSound(systemSoundID); 在接收到内存警告的情况下:释放soundID对应的内存地址,清空内存缓存. //释放soundID对应的内存地址 for (NSNumber *soundIDNum in self.soundIDCache.allValues) { AudioServicesDisposeSystemSoundID([soundIDNum unsignedIntValue]); }
-
3.框架:AVFoundation.
-
4.关键类:SystemSoundID,每个音频文件使用音效方式处理时,会完整的添加到内存中,并被赋予一个声音ID.
-
5.C的对象和OC对象的转化中内存管理:
__bridge 用于Foundation中的类和CoreFoundation中的类相互转换,并且内存管理所有权不会改变。 __bridge_retained 只能用于Foundation对象转CoreFoundation引用,而且内存管理的所有权会移交给引CoreFoundation的引用(注意手动内存管理)。 __bridge_transfer 只能用于CoreFoundation引用转Foundation对象,而且内存管理的所有权会移交给引Foundation(会自动内存管理,不需要手动释放)。
音乐
1.框架:AVFoundation
2.关键类:AVAudioPlayer (只能播放本地音乐).
对象方法创建: _player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
3.音乐的播放.暂停和停止的实现:根据音频文件路径初始化播放器 -> 进行缓冲
[self.player prepareToPlay];
4.注意点:停止播放是音乐停止缓冲,但播放进度并不会清零.暂停音乐是暂时停止播放,但缓冲继续.音乐播放,隐式缓冲.
关键方法:
-(void)play;//播放
-(void)prepareToPlay;//缓存播放
-(void)pause;//暂停
-(void)stop;//停止
录音
-
1.录音功能的实现:
生成录音的存放路径(沙盒路径,拼接文件名:stringByAppendingPathComponent:@"音频名.caf") -> 设置采样率和位深 -> 对象方法创建录音机对象
-
2.框架:AVFoundation.
-
关键类:AVFoundationRecorder.
-
关键方法:
-(void)record;//录制 -(void)pause;//暂停 -(void)stop;//停止
-
-
3.设置采样率和位深:
NSDictionary *settings = @{AVSampleRateKey:@44100,AVLinearPCMBitDepthKey:@16};
-
4.注意点:
真机进行录音时,需要请求用户授权.在info.plist进行麦克风的授权说明.
-
5.检测录音音量变化(&静默2s停止录音)
//开启检测音量变化 self.recorder.meteringEnabled = YES; //开启定时器 [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; - (void)updateMeters{ //更新音量变化 [self.recorder updateMeters]; //获取瞬时音量 float power = [self.recorder peakPowerForChannel:0]; NSLog(@"%f", power); //静默两秒后就停止录音 if (power < -30) { //累计静默计数 self.muteCount++; if (self.muteCount >= 120) { //静默两秒钟 //停止录音 [self.recorder stop]; //停止定时器 [self.displayLink invalidate]; } } else { //有声音,就重新计数 self.muteCount = 0; } }
视频
- 1.播放视频的三个框架;
- AVFoundation:提供了相对底层的API,不带界面效果.
- MediaPlayer:对AVFoundation进行了封装,提供了较为简便的播放器使用.
- AVKit:ios9推出,集AVFoundation和MediaPlayer之大成.
-
2.播放器的创建
-
1> MPMoviewPlayerViewController(带界面的视频播放器):
获取视频文件的url路径 ->对象方法创建视频播放控制器 ->modal展示.
-
2> MPMoviewPlayerController(不带界面的视频播放器):
获取视频文件路径 ->创建控制器对象 ->将播放器的视图添加到要展示的界面上 ->[控制器对象 play];
-
3> AVPlayer,偏底层,既可以播放音频又可以播放视频,播放视频需要添加layer到父视图上.
//创建资源对象 获取文件信息 AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:@"http://baobab.wdjcdn.com/14676170652191(23).mp4"]]; //创建播放项目 曲目 AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset]; //AVPlayer既可以播音频也可以播视频,可以本地也可以播网络 self.avPlayer = [[AVPlayer alloc] initWithPlayerItem:item]; //设置视图layer AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; [self.view.layer addSublayer:layer]; layer.frame = [UIScreen mainScreen].bounds; //播放 [self.avPlayer play];
-
4> AVPlayerViewController
//带界面的播放器 AVPlayerViewController *playerVc = [[AVPlayerViewController alloc] init]; //设置播放器 //创建资源对象 获取文件信息 AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:@"http://baobab.wdjcdn.com/14676170652191(23).mp4"]]; //创建播放项目 曲目 AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset]; AVPlayer *avPlayer = [AVPlayer playerWithPlayerItem:item]; playerVc.player = avPlayer; //进行modal展示 [self presentViewController:playerVc animated:YES completion:nil]; [avPlayer play];
-
3.特殊功能:
-
1> 横屏全屏播放(视图旋转90度,frame设置为屏幕大小)
[UIView animateWithDuration:0.25 animations:^{ self.playerController.view.transform = CGAffineTransformRotate(self.playerController.view.transform, M_PI_2); self.playerController.view.frame = [UIScreen mainScreen].bounds; }];
-
2> 获取全屏的Down事件(viewDidLoad中用通知监听退出全屏事件) 退出全屏&暂停时,说明触发了Down事件
//监听通知 退出全屏时 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didExitFullScreen) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
-
3> 已经退出全屏后调用
- (void)didExitFullScreen{ //判断播放状态 if (self.playerController.playbackState == MPMoviePlaybackStatePaused) { NSLog(@"点击Down"); //移除视图 [self.playerController.view removeFromSuperview]; } }
-
视频截图(本质获取媒体文件中需求的关键帧图片)
-
1.实现思路:
根据文件路径,创建视频文件资源(AVAsset) -> 创建媒体文件图片生成器(AVAssetImageGenerator) -> 获取当前播放时间 -> 生成图片:[图片生成器对象 generateCGImageAsynchronouslyForTimes:...];
-
2.关键类:
AVAsset(资源) 媒体文件图片生成器(AVAssetImageGenerator)
-
3.关键方法:
创建媒体资源:AVAsset的类方法创建 创建媒体文件图片生成器对象: AVAssetImageGenerator(类方法创建). 获取当前媒体文件的播放时间:CMTime time = self.avplayer.currentTime. 生成图片:[媒体文件图片生成器对象 generateCGImagesAsynchronouslyForTimes...]; //死锁: 在某个线程中嵌套该线程的同步任务才会死锁
视频录制
-
1.框架:AVFoundation.
-
2.关键类:
AVCaptureDeviceInput(摄入设备) AVCaptureMoviewFileOutput(输出设备) AVCaptureSession(采集会话) AVCaptureVideoPreviewLayer(预览视图)
-
3.视频录制的实现思路:
输入设备(音频输入麦克风,视频输入摄像头) -> 输出设备(视频文件) ->管理输入设备和输出设备的会话 ->预览视图 ->开始录制 ->录制视频的保存路径,输出设备开始录制 ->停止录制.
-
输入音频设备:
AVCaptureDevice *video = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
-
输入视频设备:
self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:video error:nil];
-
输出设备:
self.output = [[AVCaptureMovieFileOutput alloc] init];
-
会话:
self.session = [[AVCaptureSession alloc] init]; //加入输入设备 if ([self.session canAddInput:self.videoInput]) { [self.session addInput:self.videoInput]; } if ([self.session canAddInput:self.audioInput]) { [self.session addInput:self.audioInput]; } //加入输出设备 if ([self.session canAddOutput:self.output]) { [self.session addOutput:self.output]; }
-
预览视图:
self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
-
开始采集:
[self.session startRunning];
-
开始录制:
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:@"录制.mp4"]; NSURL *url = [NSURL fileURLWithPath:path]; [self.output startRecordingToOutputFileURL:url recordingDelegate:self];
-
停止录制(三步:停止录制 停止采集和移除预览视图)
[self.output stopRecording]; [self.session stopRunning]; [self.previewLayer removeFromSuperlayer];
-
-
4.在访问麦克风和摄像头时应请求用户授权,在info,plist文件中对麦克风和摄像头进行描述.
视频转制(输出相册中的视频并压缩)
-
1.实现思路:
创建UIImagePickerController对象 ->设置代理,设置资源类型(获取图片)和媒体类型(获取视频) ->modal展示 ->在代理方法中获取路径获取媒体文件 ->创建媒体转制会话 ->设置输出的路径 ->设置可支持的输出格式 ->输出视频 ->销毁UIImagePickerController对象
-
2.步骤:
-
创建控制器:
UIImagePickerController *imgVc = [[UIImagePickerController alloc] init];
-
设置代理:
imgVc.delegate = self;
-
设置类型:
imgVc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
-
获取相册中视频 需要设置媒体类型:
imgVc.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
-
modal展示:
[self presentViewController:imgVc animated:YES completion:nil];
-
转制视频:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{ NSLog(@"%@", info); //获取媒体文件 NSURL *url = info[UIImagePickerControllerMediaURL]; AVAsset *asset = [AVAsset assetWithURL:url]; //创建媒体转制会话 AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetLowQuality]; //设置转出的路径 NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:@"转出的视频.mp4"]; session.outputURL = [NSURL fileURLWithPath:filePath]; //获取支持的转出格式 [session determineCompatibleFileTypesWithCompletionHandler:^(NSArray<NSString *> * _Nonnull compatibleFileTypes) { NSLog(@"%@", compatibleFileTypes); }]; //设置转出的格式 转出格式必须支持 session.outputFileType = @"public.mpeg-4"; //转出视频 [session exportAsynchronouslyWithCompletionHandler:^{ NSLog(@"完成转出"); //销毁控制器 [picker dismissViewControllerAnimated:YES completion:nil]; }]; }
-
谢谢观赏,喜欢的话就点一下!