总体内容
1、录音实现

2、录音的编辑 (拼接音频:可以设置多段,音频的剪切:按照时间段剪切)

3、lame静态库进行压缩转码

一、录音实现
1.1、导入 AVFoundation 框架,多媒体的处理, 基本上都使用这个框架

#import <AVFoundation/AVFoundation.h>

1.2、使用 AVAudioRecorder 进行录音,定义一个JKAudioTool 管理录音的类

(1)、定义一个录音对象,懒加载

@property (nonatomic, strong) AVAudioRecorder *audioRecorder;

-(AVAudioRecorder *)audioRecorder
{
if (!_audioRecorder) {

   // 0. 设置录音会话/**AVAudioSessionCategoryPlayAndRecord: 可以边播放边录音(也就是平时看到的背景音乐)*/[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];// 启动会话[[AVAudioSession sharedInstance] setActive:YES error:nil];// 1. 确定录音存放的位置NSURL *url = [NSURL URLWithString:self.recordPath];// 2. 设置录音参数NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];// 设置编码格式/**kAudioFormatLinearPCM: 无损压缩,内容非常大kAudioFormatMPEG4AAC*/[recordSettings setValue :[NSNumber numberWithInt: kAudioFormatLinearPCM] forKey: AVFormatIDKey];// 采样率(通过测试的数据,根据公司的要求可以再去调整),必须保证和转码设置的相同[recordSettings setValue :[NSNumber numberWithFloat:11025.0] forKey: AVSampleRateKey];// 通道数(必须设置为双声道, 不然转码生成的 MP3 会声音尖锐变声.)[recordSettings setValue :[NSNumber numberWithInt:2] forKey: AVNumberOfChannelsKey];//音频质量,采样质量(音频质量越高,文件的大小也就越大)[recordSettings setValue:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey];// 3. 创建录音对象_audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:nil];_audioRecorder.meteringEnabled = YES;}

return _audioRecorder;
}

提示:设置 AVAudioSessionCategoryPlayAndRecord: 可以边播放边录音(也就是平时看到的背景音乐)

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

AVSampleRateKey 必须保证和转码设置的相同.

AVNumberOfChannelsKey 必须设置为双声道, 不然转码生成的 MP3 会声音尖锐变声.

(2)、开始录音

  • (void)beginRecordWithRecordPath: (NSString *)recordPath {
    // 记录录音地址
    _recordPath = recordPath;
    // 准备录音
    [self.audioRecorder prepareToRecord];
    // 开始录音
    [self.audioRecorder record];
    }

(3)、结束录音

  • (void)endRecord {
    [self.audioRecorder stop];
    }

(4)、暂停录音

  • (void)pauseRecord {
    [self.audioRecorder pause];
    }

(5)、删除录音

  • (void)deleteRecord {
    [self.audioRecorder stop];
    [self.audioRecorder deleteRecording];
    }

(6)、重新录音

  • (void)reRecord {

    self.audioRecorder = nil;
    [self beginRecordWithRecordPath:self.recordPath];
    }

(7)、更新音频测量值

-(void)updateMeters
{
[self.audioRecorder updateMeters];
}

提示:更新音频测量值,注意如果要更新音频测量值必须设置meteringEnabled为YES,通过音频测量值可以即时获得音频分贝等信息 @property(getter=isMeteringEnabled) BOOL meteringEnabled:是否启用音频测量,默认为NO,一旦启用音频测量可以通过updateMeters方法更新测量值

(8)、获得指定声道的分贝峰值

  • (float)peakPowerForChannel0{

    [self.audioRecorder updateMeters];
    return [self.audioRecorder peakPowerForChannel:0];
    }

提示:获得指定声道的分贝峰值,注意如果要获得分贝峰值必须在此之前调用updateMeters方法

二、录音的编辑
2.1、理论基础

AVAsset:音频源

AVAssetTrack:素材的轨道

AVMutableComposition :一个用来合成视频的"合成器"

AVMutableCompositionTrack :"合成器"中的轨道,里面可以插入各种对应的素材

2.2、拼接录音

#pragma mark 音频的拼接:追加某个音频在某个音频的后面
/**
音频的拼接

@param fromPath 前段音频路径
@param toPath 后段音频路径
@param outputPath 拼接后的音频路径
*/
+(void)addAudio:(NSString *)fromPath toAudio:(NSString *)toPath outputPath:(NSString *)outputPath{

// 1. 获取两个音频源
AVURLAsset *audioAsset1 = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:fromPath]];
AVURLAsset *audioAsset2 = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:toPath]];// 2. 获取两个音频素材中的素材轨道
AVAssetTrack *audioAssetTrack1 = [[audioAsset1 tracksWithMediaType:AVMediaTypeAudio] firstObject];
AVAssetTrack *audioAssetTrack2 = [[audioAsset2 tracksWithMediaType:AVMediaTypeAudio] firstObject];// 3. 向音频合成器, 添加一个空的素材容器
AVMutableComposition *composition = [AVMutableComposition composition];
AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:0];// 4. 向素材容器中, 插入音轨素材
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset2.duration) ofTrack:audioAssetTrack2 atTime:kCMTimeZero error:nil];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset1.duration) ofTrack:audioAssetTrack1 atTime:audioAsset2.duration error:nil];// 5. 根据合成器, 创建一个导出对象, 并设置导出参数
AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A];
session.outputURL = [NSURL fileURLWithPath:outputPath];
// 导出类型
session.outputFileType = AVFileTypeAppleM4A;// 6. 开始导出数据
[session exportAsynchronouslyWithCompletionHandler:^{AVAssetExportSessionStatus status = session.status;/**AVAssetExportSessionStatusUnknown,AVAssetExportSessionStatusWaiting,AVAssetExportSessionStatusExporting,AVAssetExportSessionStatusCompleted,AVAssetExportSessionStatusFailed,AVAssetExportSessionStatusCancelled*/switch (status) {case AVAssetExportSessionStatusUnknown:NSLog(@"未知状态");break;case AVAssetExportSessionStatusWaiting:NSLog(@"等待导出");break;case AVAssetExportSessionStatusExporting:NSLog(@"导出中");break;case AVAssetExportSessionStatusCompleted:{NSLog(@"导出成功,路径是:%@", outputPath);}break;case AVAssetExportSessionStatusFailed:NSLog(@"导出失败");break;case AVAssetExportSessionStatusCancelled:NSLog(@"取消导出");break;default:break;}   }];

}

2.3、音频的剪切

/**
音频的剪切

@param audioPath 要剪切的音频路径
@param fromTime 开始剪切的时间点
@param toTime 结束剪切的时间点
@param outputPath 剪切成功后的音频路径
*/
+(void)cutAudio:(NSString *)audioPath fromTime:(NSTimeInterval)fromTime toTime:(NSTimeInterval)toTime outputPath:(NSString *)outputPath{

 // 1. 获取音频源AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:audioPath]];// 2. 创建一个音频会话, 并且,设置相应的配置AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetAppleM4A];session.outputFileType = AVFileTypeAppleM4A;session.outputURL = [NSURL fileURLWithPath:outputPath];
CMTime startTime = CMTimeMake(fromTime, 1);
CMTime endTime = CMTimeMake(toTime, 1);
session.timeRange = CMTimeRangeFromTimeToTime(startTime, endTime);// 3. 导出[session exportAsynchronouslyWithCompletionHandler:^{AVAssetExportSessionStatus status = session.status;if (status == AVAssetExportSessionStatusCompleted)        {NSLog(@"导出成功");}}];

}
三、lame静态库
3.1、lame 静态库简介

LAME 是一个开源的MP3音频压缩软件。LAME是一个递归缩写,来自LAME Ain’t an MP3 Encoder(LAME不是MP3编码器)。它自1998年以来由一个开源社区开发,目前是公认有损品质MP3中压缩效果最好的编码器。

Lame 的转码压缩, 是把录制的 PCM 转码成 MP3, 所以录制的 AVFormatIDKey 设置成 kAudioFormatLinearPCM(无损压缩,内容非常大) , 生成的文件可以是 caf 或者 wav.

3.2、如何使用lame

第一步: 下载 lame 的最新版本并解压

第二步: 把下载的 lame 生成静态库,我们使用脚本

下载 build 的脚本

创建一个文件夹放 脚本 与 下载的lame

修改脚本里面的 SOURCE=“lame” 名字与 下载的lame名字一致,也可以把 下载的lame名字 改为 lame,那么就不需要改脚本的内容

1550802366890392.png

修改脚本里面的 SOURCE="lame" 名字与 下载的lame名字一致,也可以把 下载的lame名字 改为 lame,那么就不需要改脚本的内容

改脚本为可执行脚本

chmod +x build-lame.sh

执行脚本

./build-lame.sh

执行脚本的结果如下:生成三个文件

执行脚本的结果如下:生成三个文件

提示:我们要的是支持多种架构的 fat-lame 文件,把 fat-lame 里面的 lame.h 与 libmp3lame.a 拖走即可

第三步: 导入静态库到工程, 开始使用,我们把代码都写在 JKLameTool 类里面,具体的分析放在 3.3

3.3、lame 的使用,代码都在 JKLameTool 里面

<1>、录完音频 统一 caf 转 mp3,核心代码如下

/**
caf 转 mp3
如果录音时间比较长的话,会要等待几秒…
@param sourcePath 转 mp3 的caf 路径
@param isDelete 是否删除原来的 caf 文件,YES:删除、NO:不删除
@param success 成功的回调
@param fail 失败的回调
*/

  • (void)audioToMP3:(NSString *)sourcePath isDeleteSourchFile: (BOOL)isDelete withSuccessBack:(void(^)(NSString *resultPath))success withFailBack:(void(^)(NSString *error))fail{

    dispatch_async(dispatch_get_global_queue(0, 0), ^{

      // 输入路径NSString *inPath = sourcePath;// 判断输入路径是否存在NSFileManager *fm = [NSFileManager defaultManager];if (![fm fileExistsAtPath:sourcePath]){if (fail) {fail(@"文件不存在");}return;}// 输出路径NSString *outPath = [[sourcePath stringByDeletingPathExtension] stringByAppendingString:@".mp3"];@try {int read, write;//source 被转换的音频文件位置FILE *pcm = fopen([inPath cStringUsingEncoding:1], "rb");  //skip file headerfseek(pcm, 4*1024, SEEK_CUR);                                   //output 输出生成的Mp3文件位置FILE *mp3 = fopen([outPath cStringUsingEncoding:1], "wb");  const int PCM_SIZE = 8192;const int MP3_SIZE = 8192;short int pcm_buffer[PCM_SIZE*2];unsigned char mp3_buffer[MP3_SIZE];lame_t lame = lame_init();lame_set_in_samplerate(lame, 11025.0);lame_set_VBR(lame, vbr_default);lame_init_params(lame);do {size_t size = (size_t)(2 * sizeof(short int));read = (int)fread(pcm_buffer, size, PCM_SIZE, pcm);if (read == 0)write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);elsewrite = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);fwrite(mp3_buffer, write, 1, mp3);} while (read != 0);lame_close(lame);fclose(mp3);fclose(pcm);}@catch (NSException *exception) {NSLog(@"%@",[exception description]);}@finally {if (isDelete) {NSError *error;[fm removeItemAtPath:sourcePath error:&error];if (error == nil){// NSLog(@"删除源文件成功");}}if (success) {success(outPath);}}
    

    });
    }

<2>、caf 转 mp3 : 录音的同时转码,这个是学习iOS 使用 Lame 转码 MP3 的最正确姿势,代码结构上在此基础上进行了封装和改进,具体的请看 JKLameTool 类,在此不再重复,核心思想如下:

边录边转码, 只是我们在可以录制后,重新开一个线程来进行文件的转码

当录音进行中时, 会持续读取到指定大小文件,进行编码, 读取不到,则线程休眠

在 while 的条件中, 我们收到 录音结束的条件,则会结束 do while 的循环.

我们需要在录制结束后发送一个信号, 让 do while 跳出循环

四、上面那么的内容封装之后使用方式如下
4.1、导入 #import “JKRecorderKit.h”,录音都存在 /Library/Caches/JKRecorder 里面

4.2、使用 JKAudioTool 类进行调用 录音的一系列操作,如下

开始录音

// 目前使用 caf 格式, test2:录音的名字 caf:录音的格式
[[JKAudioTool shareJKAudioTool]beginRecordWithRecordName:@“test2” withRecordType:@“caf” withIsConventToMp3:YES];

完成录音

[[JKAudioTool shareJKAudioTool]endRecord];

暂停录音

[[JKAudioTool shareJKAudioTool]pauseRecord];

删除录音

[[JKAudioTool shareJKAudioTool]deleteRecord];

caf 转 mp3,第一个参数是原音频的路径,第二个参数是转换为 MP3 后是否删除原来的路径

[JKLameTool audioToMP3:[cachesRecorderPath stringByAppendingPathComponent:@“test2.caf”] isDeleteSourchFile:YES withSuccessBack:^(NSString * _Nonnull resultPath) {

NSLog(@"转为MP3后的路径=%@",resultPath);

} withFailBack:^(NSString * _Nonnull error) {
NSLog(@“转换失败:%@”,error);

}];

提示:更多的内容请看demo里面的封装

补充:封装类的说明

JKLameTool:对 lame静态库的使用

JKSingle:单利的封装

JKAudioTool:录音的封装

JKAudioFileTool:录音文件的操作,音频拼接,剪切,m4a格式转caf格式,caf格式转m4a格式

JKAudioPlayerTool:音频的简单播放封装

JKAudioFilePathTool:沙盒路径的一些操作

最后:测试的https://github.com/JoanKing/JKRecorderKit

iOS -录音-音频的拼接剪切以及边录边压缩转码相关推荐

  1. ios android mid音频文件,iOS 录音 音频 视频 控制中心

    录音 最近项目中需要录音功能,为此在写了一个录音的小模块. 首先需要添加AVFoundation.framework lame.h 帮助链接 下面直接上代码 #import #import #impo ...

  2. iOS开发--音频播放、录音、视频播放、拍照、视频录制

    概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像 ...

  3. iOS录音和音频播放

    文章目录 简介 `AVAudioRecorder`录音 `AVAudioPlayer`播放音频文件. 简介 最近公司研发了一个语音识别的框架,但这个框架是后端识别,所以需要手机端录音,录音后将音频文件 ...

  4. Swift实现iOS录音与播放音频功能

    Swift实现iOS录音与播放音频功能 作用 AVPLayer:可以用来播放在线及本地音视频 AVAudioSession:音频会话,主要用来管理音频设置与硬件交互 使用时需要导入 #import & ...

  5. iOS音频开发(录音+播放+剪辑+合成+压缩转码)

    录音: //音频会话 AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *sessionError; /* AVAu ...

  6. iOS 9音频应用播放音频之音量设置与声道设置

    iOS 9音频应用播放音频之音量设置与声道设置 iOS 9音频应用音量设置 音量又称响度.音强,是指人耳对所听到的声音大小强弱的主观感受,其客观评价尺度是声音的振幅大小.在iOS 9音频应用的应用中, ...

  7. iOS 9音频应用开发基础教程(大学霸内部资料)

    iOS 9音频应用开发基础教程(大学霸内部资料) 介绍:iOS 9音频应用开发基础教程(内部资料)是iOS 9音频应用开发专向教程.本书采用Swift 2.0语言开发基于iOS 9的音频应用.实现的功 ...

  8. ios录音文件路径_iOS中录音功能

    应用场景 在即时通讯APP中,例如微信,QQ,等都有语音发送功能,一般都要先将录音录制下来才能发送录音. 音频相关知识介绍: 1. 文件格式(不同的文件格式,可保存不同的编码格式的文件) 1.1 WA ...

  9. iOS录音转码:amr转wav,wav转amr

    iOS 录音转码:amr到wav,wav到am: 这里就把iOS录制的wav文件转成amr,我们采用的是libopencore框架. 关于libopencore,大家可以搜索:iOS音频格式AMR和W ...

最新文章

  1. 跟我学Springboot开发后端管理系统4:数据库连接池Druid和HikariCP
  2. 国产GPU为何“一夜杀到老黄城下”?
  3. 有关于近期大量数据库暴光的分析
  4. WSDM Cup 2020 引用意图识别赛道冠军解决方案(附答辩视频、PPT和代码)
  5. LeetCode 215 数组中的第K个最大元素
  6. 什么是Protocol Buffers / protobuf / protobuffer?一种服务器和客户端的消息交互方式
  7. php可逆加密解密函数,php 好用可逆的 加密解密 函数。
  8. 3dmax安全工具3ds Max Scene Security Tools
  9. 零界之痕服务器维护,零界之痕测试服
  10. 记一次失败的机械键盘拆机换轴经历(含失败的经验总结)
  11. 【愚公系列】2021年12月 Redis数据库-主从的搭建
  12. java 压缩jar_Java基础之实现解压和压缩jar、zip、rar等源码分享
  13. 姿态和位置,四旋翼的控制流程
  14. 机器学习 --- 4. 大内密探HMM(隐马尔可夫)围捕赌场老千
  15. 如何获得最新的太阳神三国杀 自己Qt编译
  16. dmg写入u盘_轻松教大家用U盘安装Mac OS10.14.1双系统
  17. 集合4:方法-仅适用于set
  18. 怎么交c语言课堂作业,C语言第四次作业课堂
  19. 嵌入式开发(四):海思Hi3559AV100交叉编译ffmpeg
  20. gazebo学习时遇到的问题(PX4篇)

热门文章

  1. 1070 结绳 (25 分) (C++)
  2. jieba使用自定义词典_如何在Word 2013中使用自定义词典
  3. 北京CBD将建十余个公交车港湾 缓解交通拥堵
  4. iOS 筛选视图的隐藏方案
  5. H5类似淘宝头条垂直滚动效果
  6. Anton and School - 2 CodeForces - 785D 范德蒙恒等式
  7. 前后端分离后各自职责
  8. 因远程计算机不能及时反应 此连接已被终止,l联想p612手机怎么不能及时收到短信啊...
  9. 解决d3dx10_41.dll丢失
  10. 服务器 监控信息,服务器 监控信息 怎么看