iOS录音使用AVAudioRecorder,播放用 AVPlayer 就可以很好的解决,网上也有很多的教程。这里就不细讲,后面会附上代码。

先说一下demo内容,现在项目要求做一个录音、上传、播放的功能。细节:录音前需要提示音,录音时会有一个根据声音强度来展示的相应动态效果,还有个计时功能。

我们来说一下我在制作此功能时所遇到的坑!!

这里先呈现音频录制的代码,这里面引用了SpectrumView,点击打开链接。这是一个根据声强来显示声音录制的效果,如果不需要可以去除。

录制音频代码:

1.首先说一下录制音频的格式。

经验证,这里博主建议各位使用AAC的录制格式。AAC(Advanced Audio Coding),中文称为“高级音频编码”,所占内存小,音质也不错,最重要的是可以与android兼容。

2.这里用的是7牛云的上传。这里我遇到的大问题就是上传音频到7牛云后,发现格式不能识别,显示为application/octet-stream。我最开始用.mp4的格式,的确上传上去后,能够识别为video/mp4,并且能正常播放。 但是后来发现不能播放android的录音。于是就想办法解决,经过一下午的各种博客浏览,。。。无果!! 好吧,最后想到先本地存储,再来播放的方式,解决问题。(这里的录音文件都比较小,不超过30s)

这里附上部分demo片段,有需要自取。

录音部分:#import "AudioRecorderVC.h"
#import <AVFoundation/AVFoundation.h>
#define kRecordAudioFile @"myRecord.aac"@interface AudioRecorderVC ()<AVAudioRecorderDelegate>
@property (strong,nonatomic) SpectrumView *spectrumView;
@property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音频录音机
@property (nonatomic, strong) AVAudioPlayer *bellplayer;
@property (nonatomic, assign) int sCountup;
@property (nonatomic, strong) NSTimer *mTimer;
@end@implementation AudioRecorderVC#pragma mark - 控制器视图方法
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self.naView setHidden:YES];
[self.statusTip setHidden:YES];
[self.view createBordersWithColor:[UIColor clearColor] withCornerRadius:6 andWidth:1];
[self.labReminder createBordersWithColor:[UIColor clearColor] withCornerRadius:4 andWidth:1];
[self.labReminder setTextColor:MCOLOR_FFFFFF];
[self addTapGesture];
[self addSpectrumView];
[self labToSize];
}-(void)addSpectrumView{
if (!self.spectrumView) {
__weak AudioRecorderVC *weakSelf = self;
self.spectrumView = [[SpectrumView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.bounds)-150,240,300, 60.0)];
self.spectrumView.hidden = YES;
self.spectrumView.text = [NSString stringWithFormat:@"%d",0];
__weak SpectrumView * weakSpectrum = self.spectrumView;
self.spectrumView.itemLevelCallback = ^() {[weakSelf.audioRecorder updateMeters];
//取得第一个通道的音频,音频强度范围是-160到0
float power= [weakSelf.audioRecorder averagePowerForChannel:0];
weakSpectrum.level = power;
};
[self.view addSubview:self.spectrumView];
}
}-(void)addTapGesture{
//添加手势
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickPop)];
//将手势添加到需要相应的view中去
[self.view addGestureRecognizer:tapGesture];
}-(void)clickPop{
if (_Block) {
_Block(nil);
}
}#pragma mark - getter 懒加载
- (UIButton *)btnRecorder {
// 开始
[_btnRecorder addTarget:self action:@selector(recordStart:) forControlEvents:UIControlEventTouchDown];
// 取消
// [_btnRecorder addTarget:self action:@selector(recordCancel:) forControlEvents: UIControlEventTouchUpOutside];
//完成
[_btnRecorder addTarget:self action:@selector(recordFinish:) forControlEvents:UIControlEventTouchUpInside];
/*
//移出
[_btnRecorder addTarget:self action:@selector(recordTouchDragExit:) forControlEvents:UIControlEventTouchDragExit];
//移入
[_btnRecorder addTarget:self action:@selector(recordTouchDragEnter:) forControlEvents:UIControlEventTouchDragEnter];
*/
return _btnRecorder;
}/**
* 获得录音机对象
*
* @return 录音机对象
*/
- (AVAudioRecorder *)audioRecorder {
if (!_audioRecorder) {
[self setAudioSession];
//创建录音文件保存路径
NSURL *url=[self getSavePath];
//创建录音格式设置
NSDictionary *setting=[self getAudioSetting];
//创建录音机
NSError *error=nil;
_audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
_audioRecorder.delegate= self;
_audioRecorder.meteringEnabled=YES;//如果要监控声波则必须设置为YES
if (error) {
NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);
return nil;
}
}
return _audioRecorder;
}#pragma mark - layout- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGFloat width = self.view.bounds.size.width;
CGFloat height = self.view.bounds.size.height;
self.btnRecorder.frame = CGRectMake(width / 2.f - 50.f, height - 180.f, 100.f, 100.f);
[self.audioRecorder record];
[self.audioRecorder stop];
[self removeFile];
}#pragma mark - ControlEvents
/*
- (void)recordCancel:(UIButton *)button {if ([self.audioRecorder isRecording]) {
NSLog(@"取消");
[self.audioRecorder stop];
self.spectrumView.hidden = NO;
}
}
*/
- (void)recordStart:(UIButton *)button {
if (![self.audioRecorder isRecording]) {
NSLog(@"录音开始");
[self startScount];
[self playthebell];
[self.audioRecorder record];
[self startAnimate];
self.labReminder.hidden = YES;
self.spectrumView.hidden = NO;}
}- (void)recordFinish:(UIButton *)button {if ([self.audioRecorder isRecording]) {
NSLog(@"完成");
[self.audioRecorder stop];
[self stopAnimate];
self.spectrumView.hidden = NO;
[self judgePushAudio];
}
}
/*
- (void)recordTouchDragExit:(UIButton *)button {
if([self.audioRecorder isRecording]) {
[self stopAnimate];
}
}- (void)recordTouchDragEnter:(UIButton *)button {
if([self.audioRecorder isRecording]) {
[self startAnimate];
}
}
*/
- (void)startAnimate {
[self.spectrumView start];
}- (void)stopAnimate {
[self.spectrumView stop];
[self.mTimer invalidate];
self.mTimer = nil;
}- (void)setAudioSession {
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *sessionError;
//AVAudioSessionCategoryPlayAndRecord用于录音和播放
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
if(session == nil)
NSLog(@"Error creating session: %@", [sessionError description]);
else
[session setActive:YES error:nil];
}/**
* 取得录音文件设置
*
* @return 录音设置
*/
- (NSDictionary *)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;
}/**
* 取得录音文件保存路径
*
* @return 录音文件路径
*/
- (NSURL *)getSavePath {// 在Documents目录下创建一个名为FileData的文件夹
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"AudioData"];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDir = FALSE;
BOOL isDirExist = [fileManager fileExistsAtPath:path isDirectory:&isDir];
if(!(isDirExist && isDir)) {
BOOL bCreateDir = [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
if(!bCreateDir){
NSLog(@"创建文件夹失败!");
}
NSLog(@"创建文件夹成功,文件路径%@",path);
}
path = [path stringByAppendingPathComponent:kRecordAudioFile];
NSLog(@"file path:%@",path);
NSURL *url=[NSURL fileURLWithPath:path];return url;
}- (void)removeFile{
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"AudioData"];
NSFileManager *fileManager = [NSFileManager defaultManager];
path = [path stringByAppendingPathComponent:kRecordAudioFile];
NSError *error;
if ([fileManager removeItemAtPath:path error:&error] != YES)
NSLog(@"Unable to delete file: %@", [error localizedDescription]);}- (void)judgePushAudio{
if (_sCountup < 1) {
[self showToast:@"录音时间太短,请重试!"];
[self removeFile];}else if(_sCountup >= 1 && _sCountup <= 30){
if (_Block) {
_Block([self getSavePath]);
}
}
}- (void)labToSize{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self.labReminder.text];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:20.0f];//调整行间距
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [self.labReminder.text length])];
self.labReminder.attributedText = attributedString;
[self.labReminder sizeToFit];
}#pragma --提示音
- (void)playthebell{
NSString *mp3Str;
mp3Str = @"talkroom_begin";
NSString *filePath = [[NSBundle mainBundle] pathForResource:mp3Str ofType:@"mp3"];
self.bellplayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:nil];
self.bellplayer.volume = 1.0;
self.bellplayer.numberOfLoops = -1;
[self.bellplayer prepareToPlay];
[self.bellplayer play];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, ( 0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.bellplayer stop];
});
}#pragma --计时器
- (void)startScount{
self.sCountup = 0;
[UIView animateWithDuration:0.5 animations:^{
self.mTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(startCountUp) userInfo:nil repeats:YES];
}];
}- (void)startCountUp{
_sCountup++;
self.spectrumView.timeLabel.text = [NSString stringWithFormat:@"%ds", _sCountup];
if (_sCountup == 30) {
[self recordFinish:nil];
}
}@end

3

#pragma --播放录音
- (void)addVoiceButton:(DoorVoucherCell *)cell{UIButton *voiceBtn = [[UIButton alloc]initWithFrame:CGRectMake(cell.contentValue.left, 0, 150, 50)];[voiceBtn addTarget:self action:@selector(playRecoderVoice) forControlEvents:UIControlEventTouchUpInside];voice = [[UIImageView alloc]initWithFrame:CGRectMake(0, 12, 25, 25)];//动画未开始前的图片voice.image = [UIImage imageNamed:@"chat_animation_white3"];//进行动画效果的3张图片(按照播放顺序放置)voice.animationImages = [NSArray arrayWithObjects:[UIImage imageNamed:@"chat_animation_white1"],[UIImage imageNamed:@"chat_animation_white2"],[UIImage imageNamed:@"chat_animation_white3"],nil];//设置动画间隔voice.animationDuration = 1;voice.animationRepeatCount = 0;voice.userInteractionEnabled = NO;voice.backgroundColor = [UIColor clearColor];[voiceBtn addSubview:voice];[cell addSubview:voiceBtn];
}- (NSURL *)writeRecoderToFile{//播放NSURL *url = [NSURL URLWithString:self.dataModel.voice];//把音频文件保存到本地NSData *audioData = [NSData dataWithContentsOfURL:url];NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"AudioData"];path = [path stringByAppendingPathComponent:@"myRecord.aac"];//  DDLogWarn(@" 从网络拿到的音频数据写入的本地路径  %@",filePath);[audioData writeToFile:path atomically:YES];NSURL *fileURL = [NSURL fileURLWithPath:path];return fileURL;
}- (void)playRecoderVoice{[self setAudioPlayer];[self.audioPlayer play];dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{[voice startAnimating];});
}- (void)playerItemDidReachEnd{[self playthebell];[voice stopAnimating];voice.image = [UIImage imageNamed:@"chat_animation_white3"];
}- (AVPlayer *)setAudioPlayer{NSError *error=nil;AVPlayerItem * songItem = [[AVPlayerItem alloc]initWithURL:[self writeRecoderToFile]];AVAudioSession *session = [AVAudioSession sharedInstance];[session setActive:YES error:nil];[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];[session setCategory:AVAudioSessionCategoryPlayback error:nil];_audioPlayer = [[AVPlayer alloc] initWithPlayerItem:songItem];// 监听音乐是否播放完成[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(playerItemDidReachEnd)name:AVPlayerItemDidPlayToEndTimeNotificationobject:nil];if (error) {NSLog(@"创建播放器过程中发生错误,错误信息:%@",error.localizedDescription);return nil;}return _audioPlayer;
}#pragma --提示音
- (void)playthebell{NSString *mp3Str;mp3Str = @"talkroom_up";NSString *filePath = [[NSBundle mainBundle] pathForResource:mp3Str ofType:@"mp3"];self.bellplayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:nil];self.bellplayer.volume = 1.0;self.bellplayer.numberOfLoops = -1;[self.bellplayer prepareToPlay];[self.bellplayer play];dispatch_after(dispatch_time(DISPATCH_TIME_NOW, ( 0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{[self.bellplayer stop];});
}

有问题欢迎提问,喜欢请点赞,Star。谢谢。

ios 音频录音、上传至7牛、播放及其与android兼容的问题相关推荐

  1. pyaudio:基于pyaudio利用Python编程从电脑端录制音频保存到指定文件夹+将录音上传服务器+录音进行识别并转为文本保存

    pyaudio:基于pyaudio利用Python编程从电脑端录制音频保存到指定文件夹+将录音上传服务器+录音进行识别并转为文本保存 目录 输出结果 代码实现 输出结果 代码实现 # -*- codi ...

  2. 基于WT2605C-32N音频蓝牙语音芯片的实时录音上传技术方案介绍

    现代社会,信息技术的发展尤其迅速,信息和数据的重要性和安全性日渐深刻,在某些特殊场合,因为工作上的需要,或者日常生活的需求,往往需要记录和保留一些重要的声音.在某些时刻,录音成为记录生活,保存证据的重 ...

  3. 【无标题】音频蓝牙语音芯片,WT2605C-32N实时录音上传技术方案介绍

    基于WT2605C-32N音频蓝牙语音芯片的实时录音上传技术方案介绍 现代社会,信息技术的发展尤其迅速,信息和数据的重要性和安全性日渐深刻,在某些特殊场合,因为工作上的需要,或者日常生活的需求,往往需 ...

  4. 微信开发之录音上传、下载、转码

    原文是在我自己博客中,小伙伴也可以点 阅读原文进行跳转查看,还有好听的背景音乐噢~ 一年的时间里,前前后后都在搞微信开发的相关模块,这不前一阵子,公司又开了个新项目,其中有一个就是类似于微信朋友圈的功 ...

  5. 上传声音 微信小程序_SpringBoot开发案例之微信小程序录音上传

    前言 书接上回的<SpringBoot开发案例之微信小程序文件上传>,正常的业务流程是,口语测评需要学生通过前端微信小程序录入一段音频,通过调用第三方音频处理服务商进行评分,然后服务端对原 ...

  6. 微信语音(录音,上传,下载,播放,停止)

    1.api:微信:JSSDK    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 (1)初始化微信:一般在 ...

  7. js代码实现录音上传

    js代码实现录音上传 1.html页面 2.Recorder.js内容 3.flask写法 1.html页面 <!DOCTYPE html> <html lang="en& ...

  8. 微信小程序录音上传功能

    微信小程序录音上传 录音弹窗wxml代码: <!-- 录音弹窗 --> <view class="cui-record" hidden="{{isHid ...

  9. 微信小程序录音上传php代码,小程序实现录音上传功能

    本文实例为大家分享了小程序录音上传的具体代码,供大家参考,具体内容如下 首先我们可以先看一下微信小程序的API 这里有关于小程序录音的一些基本配置 index.wxml: index.wxss: .t ...

  10. H5实现实时音频MP3上传至服务端

    H5实现实时音频MP3上传至服务端 背景 实现方法 音频采集 服务器端 源码 前端页面源码如下: 服务端源码 背景 最近由于项目需求,需要对接广播,实现在业务平台上集成话筒的实时喊话功能.没问题,很简 ...

最新文章

  1. 堆、栈、方法区、静态代码块---Java
  2. 判断一个字符串在另一个字符串中出现的次数
  3. Salt-Minion配置文件详解
  4. docker hive nagasuga_制作一个用来调试hive的docker镜像
  5. 关于文件中的0D、0A
  6. [转载] python笔记:4.1.2.1统计量_离散程度_方差和标准差
  7. Linux XZ压缩格式学习
  8. 干货 | 万字长文带你复习线性代数!
  9. Grup加密(使其不能强制更改密码)
  10. 2019-数学建模美赛-B题翻译
  11. 海康威视ivms-4200图文说明
  12. 如何解决PDF图片字体未嵌入的问题
  13. 无人机飞行控制逻辑以及不稳定原因分析
  14. 计算机用几个字节储存,一个文字在计算机中用两个字节来储存。()
  15. sublime text 3 php 语法错误检查
  16. Fortify代码扫描问题及修复
  17. 最后采用加权求和的方式得到样本的_论文阅读笔记《Principal characteristic networks for few-shot...
  18. 坚果云 android 操作历史,坚果云怎样将文件恢复到某一个历史版本?两招轻松搞定!...
  19. 视频教程-PHP零基础七天入门视频课程(免费50章)-PHP
  20. Mac快速文字处理软件:Mellel

热门文章

  1. java内嵌浏览器插件
  2. 解决MAC系统字体发虚,更换默认字体为微软雅黑
  3. html生物代码,方块方舟全物品代码 生物召唤代码大全
  4. 一连三问 !!! 什么是内存对齐?内存对齐的原因是什么?内存对齐的好处是什么?
  5. android stub,Android:ViewStub
  6. zotero文献管理工具的下载安装
  7. android获取root代码,Android获取ROOT权限的实例代码
  8. 基于Java的TCP Socket通信详解
  9. ALTRUN 工具使用笔记
  10. 基于javaweb的宠物管理系统