总体内容

1、录音实现

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

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

一、录音实现

1.1、导入 AVFoundation 框架,多媒体的处理, 基本上都使用这个框架#import

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,那么就不需要改脚本的内容

修改脚本里面的 `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 header

fseek(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);

else

write = 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:沙盒路径的一些操作

最后:测试的 demo

推荐博客如下:作者:IIronMan

链接:https://www.jianshu.com/p/1a752b92070b

ios 边录音边放_iOS 录音、音频的拼接剪切以及边录边压缩转码相关推荐

  1. iOS -录音-音频的拼接剪切以及边录边压缩转码

    总体内容 1.录音实现 2.录音的编辑 (拼接音频:可以设置多段,音频的剪切:按照时间段剪切) 3.lame静态库进行压缩转码 一.录音实现 1.1.导入 AVFoundation 框架,多媒体的处理 ...

  2. ios 边录音边放_iOS开发 - AVPlayer实现流音频边播边存

    边播边下有三套左右实现思路,本文使用AVPlayer + AVURLAsset实现. 概述 1. AVPlayer简介 AVPlayer存在于AVFoundation中,可以播放视频和音频,可以理解为 ...

  3. ios 边录音边放_iOS开发:AVPlayer实现流音频边播边存

    概述 1. AVPlayer简介AVPlayer存在于AVFoundation中,可以播放视频和音频,可以理解为一个随身听 AVPlayer的关联类:AVAsset:一个抽象类,不能直接使用,代表一个 ...

  4. ios 边录音边放_iOS 音频视频播放器实现边下载边播放缓存视频

    框架整体介绍 功能介绍 KJPlayer 是一款视频播放器,AVPlayer的封装,继承UIView 1.支持播放网络和本地视频 ☑️ 2.播放多种格式mp4 ☑️ m3u8.3gp.mov等等暂未完 ...

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

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

  6. 使用iphone的remote io unit来录音和放音.

    此文的参考价值越来越小了,新版的xcode默认要求arc开发,此类是mrc.AudioSessionAddPropertyListener...这些c函数在ios7也提示过时了.用上AVAudioSe ...

  7. matlab 播放声音,用matlab录音和放音

    用matlab录音和放音 利用matlab的音频信号处理工具箱,可以实现声音的录制和播放. 录音函数wavrecord语法为: y=wavrecord(n,fs,channel,dataType); ...

  8. MATLAB同时录音播放,用matlab录音和放音

    用matlab录音和放音 利用matlab的音频信号处理工具箱,可以实现声音的录制和播放. 录音函数wavrecord语法为: y=wavrecord(n,fs,channel,dataType); ...

  9. linux alsa 录音程序,转 alsa录音放音执行流程详解

    前言: linux中,无论是oss还是alsa体系,录音和放音的数据流必须分析清楚.先分析alsa驱动层,然后关联到alsa库层和应用层. 链接分析: core/pcm_native.c文件中.mma ...

  10. 通过dsp设备实现录音与放音编程实例

    今日诗词欣赏: 柳永   <雨霖铃> 寒蝉凄切,对长亭晚,骤雨初歇.都门帐饮无绪,留恋处,兰舟催发.执手相看泪眼,竟无语凝噎.念去去,千里烟波,暮霭沉沉楚天阔.     多情自古伤离别,更 ...

最新文章

  1. 谷歌语音转录背后的神经网络
  2. Mycat社区出版: 分布式数据库架构及企业实践——基于Mycat中间件
  3. python制作软件封面_用python给MP3加封面图片,修改作者,专辑等信息
  4. Activiti源码 ProcessEngineConfiguration
  5. apache camel_Apache Camel –从头开始开发应用程序(第1部分/第2部分)
  6. python正则表达式findall_正则表达式 re.findall 用法
  7. NYOJ题目289/456/49-01背包问题汇总
  8. php postgresql 数组,8.14. 数组 - [ PostgreSQL 手册 ] - 在线原生手册 - php中文网
  9. 12 经络的走向图和说明
  10. ArcGIS API For JavaScript 利用GP服务生成等值线、等值面(二)之生成等值面
  11. 让迁移不再开盲盒,让云也能省钱丨Hackathon 项目背后的故事第一期回顾
  12. 第二章 Qt窗体应用------修改标题栏图标
  13. pion:rtc-to-webrtc示例
  14. 欧拉系统搭建k8s网络
  15. Go语言中的字符串拼接方法介绍
  16. pandas 向已有的excel指定的行和列添加数据
  17. 线程池自定义拒绝策略
  18. c语言中char16_t是什么类型,错误[Pe167]:类型为“uint16_t *”的参数与类型为“unsigned char *”的参数不兼容...
  19. 在有赞做java有发展吗_有赞响应式架构与 RxJava 实践
  20. 微信小程序自定义组件--对话框

热门文章

  1. 计算机控制技术课后题答案,计算机控制技术课后习题答案
  2. 软件测试的四个阶段【单元测试、集成测试、系统测试、验证测试】
  3. 流量宝刷流量怎么操作不会被搜索引擎惩罚
  4. 三种方式实现Java对象转json下划线格式
  5. 基于SSM的社区宠物信息管理系统
  6. densepose的IUV图像I通道数字与身体部分对应关系
  7. 7月29日绝地求生服务器维护,绝地求生7月29日维护到几点 7.29吃鸡更新维护公告...
  8. java中Map集合的四种遍历方式
  9. Java面试题日积月累(jsp/Servlet面试题20道)
  10. CPDA数据分析师认证,大数据分析的综合型人才