iOS开发音频、视频
来源:互联网 发布:mac收藏网页 编辑:程序博客网 时间:2024/05/16 18:56
播放音频可以使用框架:AVFoundation.framework
1、音效播放
又称“短音频”,通常在程序中的播放时长为30秒以内
在应用程序中起到点缀效果,提升整体用户体验
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //1、设置播放音效的地址 NSURL *url = [[NSBundle mainBundle] URLForResource:@"buyao.wav" withExtension:nil]; //2、定义系统音效文件的id,根据该id查找到音效文件 SystemSoundID soundID; //3、创建音效文件 AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID); //4、播放音效文件 //4.1、不带震动的播放 AudioServicesPlaySystemSound(soundID); //4.2、带震动的播放// AudioServicesPlayAlertSound(soundID); //5、释放音效所占的内存// AudioServicesDisposeSystemSoundID(soundID); }//在AppDelegate中进行音效文件的释放- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { }
音效播放工具类的封装
#import <Foundation/Foundation.h>#import <AVFoundation/AVFoundation.h>@interface ZMAudioTools : NSObject//不带震动的播放+ (void)playSystemSoundWithURL:(NSURL *)url;//带震动的播放+ (void)playAlertSystemSoundWithURL:(NSURL *)url;//清空音效文件,在控制器收到内存警告时调用+ (void)ClearMemory;@end
#import "ZMAudioTools.h"//缓存字典static NSMutableDictionary *soundIDDict;@implementation ZMAudioTools//只要头文件参与了编译,就会调用//+ (void)load {// //}+ (void)initialize { //缓存字典初始化 soundIDDict = [NSMutableDictionary dictionary];}//不带震动的播放+ (void)playSystemSoundWithURL:(NSURL *)url{ AudioServicesPlaySystemSound([self loadSoundIDWithURL:url]);}//带震动的播放+ (void)playAlertSystemSoundWithURL:(NSURL *)url { AudioServicesPlayAlertSound([self loadSoundIDWithURL:url]);}+ (void)ClearMemory{ [soundIDDict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { SystemSoundID soundID = [obj intValue]; AudioServicesDisposeSystemSoundID(soundID); }]; }+ (SystemSoundID)loadSoundIDWithURL:(NSURL *)url { NSString *urlStr = url.absoluteString; //从缓存字典中取出soundID //2、定义系统音效文件的id,根据该id查找到音效文件 SystemSoundID soundID = [soundIDDict[urlStr] intValue]; if (soundID == 0) { //3、创建音效文件 AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID); soundIDDict[urlStr] = @(soundID); } else { } return soundID;}@end
2、音乐播放
一般播放时间较长,音乐播放用到一个叫做AVAudioPlayer的类
- (void)viewDidLoad { [super viewDidLoad]; //1、设置音乐文件的URL路径 NSURL *url = [[NSBundle mainBundle] URLForResource:@"爱.mp3" withExtension:nil]; //2、创建音乐播放器 NSError *error; self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; if (error) { NSLog(@"%@", error.localizedDescription); }}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { /***< 播放音乐 **/ //1、准备播放,把音频文件加载到内存中,默认会隐式被调用,可以省略 [self.player prepareToPlay]; //2、开始播放 [self.player play]; /***< 暂停播放 **/ [self.player pause]; /***< 停止播放 **/ [self.player stop]; //把播放时刻归零 self.player.currentTime = 0;}
3、录音
3.1、录音的简单使用
- (void)viewDidLoad { [super viewDidLoad]; //1、定义录音文件的存放地址,不改变录音文件的位置,重复录音会覆盖 NSString *path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"1.wav"]; NSURL *url = [NSURL fileURLWithPath:path]; //2、录音参数设置字典,如果传值为空默认就是高质量录音 NSDictionary *settings = [NSDictionary dictionary]; //3、创建录音对象 //NSError的标准定义 __autoreleasing NSError *error; _recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error]; }- (void)prepareRecorder { //1、准备录音 [self.recorder prepareToRecord]; //2、开始录音 [self.recorder record];}- (void)pauseRecorder { //暂停录音,不会保存录音文件,需要进行停止 [self.recorder pause];}- (void)stopRecorder { //停止录音,会产生最终的录音文件 [self.recorder stop];}
3.2、检测自动停止录音
- (void)viewDidLoad { [super viewDidLoad]; //1、定义录音文件的存放地址,不改变录音文件的位置,重复录音会覆盖 NSString *path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"1.wav"]; NSURL *url = [NSURL fileURLWithPath:path]; //2、录音参数设置字典,如果传值为空默认就是高质量录音 NSDictionary *settings = [NSDictionary dictionary]; //3、创建录音对象 //NSError的标准定义 __autoreleasing NSError *error; _recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error]; //4、打开录音分贝检测 self.recorder.meteringEnabled = YES; //5、在真机上需要 AVAudioSession *session = [AVAudioSession new]; [session setCategory:AVAudioSessionCategoryRecord error:nil];}- (void)prepareRecorder { //1、准备录音 [self.recorder prepareToRecord]; //2、开始录音 [self.recorder record]; //3、添加计时器,对录音分贝进行循环检测 [self updateMetering];}- (void)updateMetering{ if (self.displayLink == nil) { //1、创建录音计时器 self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateMeterSay)]; //2、把计时器加入到运行循环中 [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } //如果录音计时器暂停了,就打开 if (self.displayLink.isPaused) { self.displayLink.paused = NO; }}//录音计时器循环调用的方法- (void)updateMeterSay { //根据分贝的大小,来自动停止录音 //1、更新分贝信息 [self.recorder updateMeters]; //2、获取分贝信息 //取值为:0(大)~-160 CGFloat power = [self.recorder averagePowerForChannel:0]; //3、若2秒没有声音,自动停止录音 static NSInteger number; //4、displayLink,一秒默认60次 if (power < -30) { //判断是否很安静 number++; if (number/120 > 2) { [self stopRecorder]; } }}- (void)pauseRecorder { //暂停录音,不会保存录音文件,需要进行停止 [self.recorder pause]; //暂停循环 self.displayLink.isPaused = YES;}- (void)stopRecorder { //停止录音,会产生最终的录音文件 [self.recorder stop]; //暂停循环 self.displayLink.paused = YES;}
3.3、录音参数的设置
#import<AVFoundation/AudioSettings.h>//settings 设置参数 录音相关参数 声道 速率 采样率 NSMutableDictionary *setting = [NSMutableDictionary dictionary]; // 音频格式 setting[AVFormatIDKey] = @(kAudioFormatAppleIMA4); // 音频采样率 setting[AVSampleRateKey] = @(600.0); // 音频通道数 setting[AVNumberOfChannelsKey] = @(1); // 线性音频的位深度 setting[AVLinearPCMBitDepthKey] = @(8);
3.4、录音编码
1、编码是信息从一种形式转换为另一种形式的过程。 编码格式:
2、文件格式(不同的文件格式, 可保存不同的编码格式编码的文件):
.wav:特点: 音质最好的格式, 对应PCM编码;适用: 多媒体开发、保存音乐和音效素材。
.mp3:特点: 音质好,压缩比比较高,被大量软件和硬件支持;适用: 适合用于比较高要求的音乐欣赏。
.caf:特点: 适用于几乎iOS中所有的编码格式 注:caf 文件格式, 因为某些编码设置, 文件有可能会很大, 而且caf, 格式并不是很通用, 所以在开发过程中, 一般会进行压缩转码MP3;
二、视频
iOS提供了MPMoviePlayerController、MPMoviePlayerViewController两个类,可以用来轻松播放视频和网络流媒体/网络音频,MPMoviePlayerViewController只能全屏播放视频,这两个类都定义在了MediaPlayer框架中。
MPMoviePlayerController类的简介:继承自NSObject 内部有个view可以展示视频内容将该视图添加其他控制器的view上,即可显示视频内容 MPMoviePlayerController可以播放的视频格式包括:H.264、MPEG-4等支持的文件扩展名包括:avi,mkv,mov,m4v,mp4等
可以从苹果官网:http://support.apple.com/kb/HT1425下载一些用来测试的视频文件,文件都比较小
提示:MPMoviePlayerController并不支持所有的视频格式,如果要播放不支持的视频格式,需要借助第三方框架进行解码,如VLC https://github.com/videolan/vlc
1、视频播放 实现方案四种
1.1、AVPlayer
优点:
可以自定义UI, 进行控制
缺点:
单纯的播放, 没有控制UI, 而且如果要显示播放界面, 需要借助AVPlayerLayer, 添加图层到需要展示的图层上
//1、通过远程URL创建AVPlayer对象 NSURL *remoteURL = [NSURL URLWithString:@"http://xxx.com/e-b734-ac55ab528aa8/L.mp4"]; _player = [AVPlayer playerWithURL:remoteURL]; 开始播放 [self.player play]; //2、存在问题 //只能播放声音, 看不到图像 //解决方案: 需要借助AVPlayerLayer对象, 根据player创建图层, 添加到视图上 //3、 实现视频显示功能 AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:self.player]; layer.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height * 9 / 16); //添加到需要展示的视图上即可 [self.view.layer addSublayer:layer];
1.2、MPMoviePlayerController
优点:
自带的播放控制UI, 不需要手动添加
缺点:
不能自定义UI
只能将此控制器视图添加到其他视图进行展示
此控制器不是视图控制器, 不能弹出
#import <MediaPlayer/MediaPlayer.h>#import <AVKit/AVKit.h>- (IBAction)playNoViewMovie:(UIButton *)sender { //方式二:不带view的播放器的控制器 //1、获取视频文件的url地址NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:@"Cupid_高清.mp4" withExtension:nil]; //2、创建不带view的视频播放器 //ios9.0过期 _mpC = [[MPMoviePlayerController alloc] initWithContentURL:fileUrl]; //3、设置View.frame _mpC.view.frame = CGRectMake(0, 0, 300, 400); //4、添加到控制器view // [self.view addSubview:_mpC.view]; //5、准备播放,默认play隐式调用 [_mpC prepareToPlay]; //6、开始播放 [_mpC play]; //7、控制模式 self.mpC.controlStyle = MPMovieControlStyleNone;}
1.3、MPMoviePlayerViewController优点:
自带的播放控制UI, 不需要手动添加
此控制器是视图控制器, 可以弹出, 可以压栈
也可以手动调整视图大小, 添加到其他视图上
缺点:
不能自定义UI
#import <MediaPlayer/MediaPlayer.h>#import <AVKit/AVKit.h>- (IBAction)moviePlayer:(UIButton *)sender { //方式一:带view的播放器的控制器,播放完成会自动退出 //1、获取视频文件的url地址 NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:@"minion_01.mp4" withExtension:nil]; //2、创建带view的视频播放器 //ios9.0过期 MPMoviePlayerViewController *mpMV = [[MPMoviePlayerViewController alloc] initWithContentURL:fileUrl]; //3、模态跳出播放器 [self presentViewController:mpMV animated:YES completion:nil];}
1.4、MPMoviePlayerController、MPMoviePlayerViewController视频播放的通知监听
- (void)viewDidLoad { [super viewDidLoad]; //监听播放完成的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerPlaybackDidFinishNotification:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];}- (void)moviePlayerPlaybackDidFinishNotification:(NSNotification *)notif { MPMovieFinishReason reason = [notif.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] integerValue]; switch (reason) { case MPMovieFinishReasonPlaybackEnded: NSLog(@"播放结束"); //进行视频切换,更换播放视频的地址 break; case MPMovieFinishReasonPlaybackError: NSLog(@"播放错误"); break; case MPMovieFinishReasonUserExited: NSLog(@"播放退出"); break; default: break; }}
1.5、针对于第2种和第3种实现方案, 在iOS9.0之后, 统一使用AVPlayerViewController
优点:
自带的播放控制UI, 不需要手动添加
此控制器是视图控制器, 可以弹出, 可以压栈
也可以手动调整视图大小, 添加到其他视图上
缺点:
不能自定义UI
#import <AVKit/AVKit.h>#import <AVFoundation/AVFoundation.h>- (IBAction)playNoViewMovie:(UIButton *)sender { //1、获取视频文件的url地址 NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:@"Cupid_高清.mp4" withExtension:nil]; //2、创建播放器 AVPlayerViewController *playerVc = [AVPlayerViewController new]; //3、创建player playerVc.player = [AVPlayer playerWithURL:fileUrl]; //4、开始播放 [playerVc.player play]; //5、模态播放器 // [self presentViewController:playerVc animated:YES completion:nil]; //5、自定义播放器视图的大小 playerVc.view.frame = CGRectMake(0, 0, 300, 400); [self.view addSubview:playerVc.view];}
2、视频截图把视频中的某一帧作为视频的封面
#import <AVFoundation/AVFoundation.h>//点击屏幕开始截图- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //1、获取视频文件的url地址 NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:@"Cupid_高清.mp4" withExtension:nil]; //2、创建资源 AVAsset *asset = [AVAsset assetWithURL:fileUrl]; //3、创建资源图片生成器 AVAssetImageGenerator *imgGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; //4、开始生成图片 //要截取哪一帧 //参数1:视频每秒的帧数 //参数2:当前视频每秒的帧数 CMTime time = CMTimeMake(30, 1); NSValue *value = [NSValue valueWithCMTime:time]; [imgGenerator generateCGImagesAsynchronouslyForTimes:@[value] completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) { //线程同步 dispatch_sync(dispatch_get_main_queue(), ^{ self.image = [UIImage imageWithCGImage:image]; }); }];}
3、视频的录制
#import <MobileCoreServices/MobileCoreServices.h>#import <MediaPlayer/MediaPlayer.h>#import <AssetsLibrary/AssetsLibrary.h>//录制视频- (void)didClickMovie { //1、判断相机是否可用 if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { return; } //2、创建图片选择器 UIImagePickerController *picker = [UIImagePickerController new]; //3、设置类型 picker.sourceType = UIImagePickerControllerSourceTypeCamera; //4、设置媒体类型 picker.mediaTypes = @[(NSString *)kUTTypeMovie]; //5、设置相机的检测模式 picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo; //6、设置视频的质量 picker.videoQuality = UIImagePickerControllerQualityTypeHigh; //7、设置代理 picker.delegate = self; //8、模态弹出 [self presentViewController:picker animated:YES completion:nil];}#pragma mark - UIImagePickerControllerDelegate//选中视频时,进行播放- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{ //1、判断是否是视频媒体 NSString *mediaType = info[UIImagePickerControllerMediaType]; id url = info[UIImagePickerControllerMediaURL]; //2、播放视频 if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) { if (self.playerVc == nil) { self.playerVc = [MPMoviePlayerController new]; self.playerVc.view.frame = CGRectMake(0, 0, 300, 400); [self.view addSubview:self.playerVc.view]; } self.playerVc.contentURL = url; [self.playerVc play]; } //3、保存视频 if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { ALAssetsLibrary *assetsLibrary = [ALAssetsLibrary new]; //参数一:要保存视频的url [assetsLibrary writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error) { }]; } [self dismissViewControllerAnimated:YES completion:nil];}
4、视频压缩
#import "ViewController.h"#import <AVFoundation/AVFoundation.h>#import <MobileCoreServices/MobileCoreServices.h>@interface ViewController () <UINavigationControllerDelegate, UIImagePickerControllerDelegate> @end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad];}//录制视频- (void)didClickMovie { //1、相册是否可用 if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { return; } //2. 创建图像选择器 UIImagePickerController *picker = [UIImagePickerController new]; //3. 设置类型 picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; //4. 设置媒体类型 picker.mediaTypes = @[(NSString *)kUTTypeMovie]; //5. 设置代理 picker.delegate = self; //6. 模态弹出 [self presentViewController:picker animated:YES completion:nil]; }#pragma mark - UIImagePickerControllerDelegate//选中视频的时候进行压缩- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{ //1、判断是否是视频媒体 NSString *mediaType = info[UIImagePickerControllerMediaType]; id url = info[UIImagePickerControllerMediaURL]; //2、开始导出 --> 压缩 [self exportWithURL:url]; [self dismissViewControllerAnimated:YES completion:nil];}- (void)exportWithURL:(NSURL *)url { //1、获取资源 AVAsset *asset = [AVAsset assetWithURL:url]; //2、创建资源会话对象 AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality]; //3、设置导出路径 session.outputURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"123.mov"]]; //4、设置导出类型 session.outputFileType = AVFileTypeQuickTimeMovie; //5、开始导出 [session exportAsynchronouslyWithCompletionHandler:^{ NSLog(@"导出成功!"); }]; }
- iOS开发音频、视频
- IOS开发音频与视频
- ios 视频,音频,开发详解
- iOS开发----音频、视频的实现
- iOS开发 音频播放、录音、视频播放、拍照、视频录制
- iOS开发:音频播放、录音、视频播放、拍照、视频录制
- iOS开发--音频播放、录音、视频播放、拍照、视频录制
- iOS开发15-iOS SQLite存取图片、视频、音频
- iOS开发之音轨合成(音频与音频,音频与视频)
- iOS音频、视频播放
- iOS-音频 + 视频
- iOS 音频,视频
- iOS开发 简单实现视频音频的边下边播
- iOS开发 简单实现视频音频的边下边播
- iOS开发 简单实现视频音频的边下边播
- iOS开发 简单实现视频音频的边下边播
- iOS开发 简单实现视频音频的边下边播
- iOS开发系列-音频、视频以及摄像
- POJ3009 Curling 2.0【DFS】
- CentOS 7下安装UCSF Chimera
- Codeforces 235C : Cyclical Quest
- Web技术介绍和工作原理
- Ubuntu16_x64下安装docker及部署web应用
- iOS开发音频、视频
- oa实施顾问 要求
- C++ 顶层const与底层const总结
- 当元素种类远远小于数组长度的排序 | Python
- 安徽省2015年“京胜杯”大学生程序设计竞赛-数七问题
- Vue2.0权限树组件
- 二叉树之层次遍历(js)
- WinDbg-如何抓取dump文件
- 文件系统(2)