版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.01.11 |
前言
以前我写过关于声音和视频的多媒体文件的播放,接下来几篇,我们就讲述一下有关声音的录制工作。希望能帮助大家,下面我们开始。
功能需求
实现对声音的录制。
功能实现
下面我们就看一下相关代码。
1. ViewController.m
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>
#define kViewControllerAudioDirectoryName ("Audio")
@interface ViewController () <AVAudioRecorderDelegate>
@property (weak, nonatomic) IBOutlet UIButton *recordButton;
@property (nonatomic, strong) AVAudioRecorder *recorder;
@property (nonatomic, copy) NSString *recordStorePathStr;
@property (nonatomic, copy) NSString *dirPath;
@end
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadStoreDirPath];
[self loadFilePath];
}
#pragma mark - Object Private Function
//创建文件夹
- (void)loadStoreDirPath
{
NSString *cacheStr = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSString *dirPath = [cacheStr stringByAppendingPathComponent:@kViewControllerAudioDirectoryName];
NSError *dirError;
self.dirPath = dirPath;
if ([[NSFileManager defaultManager] fileExistsAtPath:dirPath])
{
NSLog(@"文件夹已经存在,不需要创建");
}
else
{
if ([[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:&dirError]) {
NSLog(@"常见文件夹成功,目录 = %@", dirPath);
}
else {
NSLog(@"创建文件夹失败,原因是 = %@", dirError);
}
}
}
//创建文件
- (void)loadFilePath
{
//创建文件
// NSString *timeStampStr = [NSString stringWithFormat:@"%lf.mp3", [[NSDate date] timeIntervalSince1970]];
NSString *filePath = [self.dirPath stringByAppendingPathComponent:@"demo.aac"];
self.recordStorePathStr = filePath;
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
BOOL isSuccess = [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
if (isSuccess) {
NSLog(@"创建文件成功,路径 = %@", filePath);
}
else {
NSLog(@"创建文件失败");
}
}
}
/**
* 取得录音文件设置
*
* @return 录音设置
*/
- (NSMutableDictionary *)getAudioSetting
{
NSMutableDictionary *dicM = [NSMutableDictionary dictionary];
//设置录音格式
[dicM setObject:@(kAudioFormatMPEG4AAC) forKey:AVFormatIDKey];
//设置录音采样率,8000是电话采样率,对于一般录音已经够了
[dicM setObject:@(8000) forKey:AVSampleRateKey];
//设置通道,这里采用单声道
[dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
//每个采样点位数,分为8、16、24、32
[dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
//是否使用浮点数采样
[dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
//....其他设置等
return dicM;
}
#pragma mark - Action && Notification
- (IBAction)recordButtonDidClick:(UIButton *)sender
{
sender.selected = !sender.selected;
if (sender.selected) {
NSURL *pathURL = [NSURL fileURLWithPath:self.recordStorePathStr];
NSError *error;
self.recorder = [[AVAudioRecorder alloc] initWithURL:pathURL settings:[self getAudioSetting] error:&error];
// 以下代码让设备开启录音模式
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setActive:YES error:nil];
if (error) {
NSLog(@"创建失败,原因是 = %@", error);
/**
2018-01-11 16:32:59.004348+0800 JJAudio_demo1[40108:8220593] 创建失败,原因是 = Error Domain=NSOSStatusErrorDomain Code=1718449215 "(null)"
2018-01-11 16:32:59.004706+0800 JJAudio_demo1[40108:8222727] XPC connection interrupted
*/
}
else {
NSLog(@"创建成功");
}
self.recorder.delegate = self;
[self.recorder prepareToRecord];
[self.recorder record];
}
else {
[self.recorder stop];
}
}
#pragma mark - AVAudioRecorderDelegate
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
NSLog(@"结束录制,存储地址是%@", self.recordStorePathStr);
}
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError * __nullable)error;
{
NSLog(@"出现了错误 = %@", error);
}
@end
下面看一下输出结果
2018-01-11 21:50:45.012017+0800 JJAudio_demo1[40157:8295697] 文件夹已经存在,不需要创建
2018-01-11 21:50:58.720493+0800 JJAudio_demo1[40157:8295697] 创建成功
2018-01-11 21:51:01.027892+0800 JJAudio_demo1[40157:8295697] 结束录制,存储地址是/var/mobile/Containers/Data/Application/DA652CF0-BA9C-4B52-93FE-B731FBEAB702/Library/Caches/Audio/demo.aac
小插曲
下面和大家说一下小插曲。
如果我们像下面这样设置录音格式的话:
//设置录音格式
// [dicM setObject:@(kAudioFormatMPEG4AAC) forKey:AVFormatIDKey];
[dicM setObject:@(kAudioFormatMPEGLayer3) forKey:AVFormatIDKey];
然后,就会发现
self.recorder = [[AVAudioRecorder alloc] initWithURL:pathURL settings:[self getAudioSetting] error:&error];
这个实例化是失败的,self.recorder打印就是nil,并给出下面这个提示。
2018-01-11 21:56:44.820363+0800 JJAudio_demo1[40161:8297302] 创建失败,原因是 = Error Domain=NSOSStatusErrorDomain Code=1718449215 "(null)"
研究了一会才发现是录音格式的问题。后来修改了格式,解决了这个问题。
功能效果
下面我们就看一下需求效果。
后记
未完,待续~~~