目前因项目需要,接触到有关音频文件的录制,上传,下载,播放等功能,并且遇到过一些不能播放,不能下载等问题。
一、功能:录音,播放 问题:录音成功之后文件不能播放
#import <AVFoundation/AVFoundation.h>
1、主要使用自带的AVFoundation类库,在.h文件中导入头文件
2、.h 声明
{
AVAudioSession *session;
AVAudioPlayer *player;
AVAudioRecorder *recorder;
}
@property(nonatomic,retain)NSURL *recordedFile;
@property(nonatomic,retain)AVAudioPlayer *player;
@property(nonatomic,retain)AVAudioRecorder *recorder;
3、.m 实现
void)touchDown
{
session = [AVAudioSessionsharedInstance];
// session.delegate = self;
NSError
[sessionsetCategory:AVAudioSessionCategoryPlayAndRecorderror:&sessionError];
if(session ==nil)
NSLog(@"Error creating session: %@", [sessionErrordescription]);
else
session setActive:YESerror:nil];
//录音设置
NSMutableDictionary *settings = [[NSMutableDictionaryalloc]init];
//录音格式 无法使用
[settings setValue :[NSNumbernumberWithInt:kAudioFormatLinearPCM]forKey:AVFormatIDKey];
//采样率
[settings setValue :[NSNumbernumberWithFloat:11025.0]forKey:AVSampleRateKey];//44100.0
//通道数
[settings setValue :[NSNumbernumberWithInt:2]forKey:AVNumberOfChannelsKey];
//线性采样位数
//[recordSettings setValue :[NSNumber numberWithInt:16] forKey: AVLinearPCMBitDepthKey];
//音频质量,采样质量
[settings setValue:[NSNumbernumberWithInt:AVAudioQualityMin]forKey:AVEncoderAudioQualityKey];
recorder = [[AVAudioRecorderalloc]initWithURL:self.recordedFilesettings:settingserror:nil];
recorder.meteringEnabled=YES;//如果要监控声波则必须设置为YES
BOOL isRecording = [recorderisRecording];
NSLog(@"isRecording%i",isRecording);
if
//首次使用应用时如果调用record方法会询问用户是否允许使用麦克风
[recorderprepareToRecord];
recorder record];
//设置定时检测
_audioTimer = [NSTimerscheduledTimerWithTimeInterval:0target:selfselector:@selector(audioPictureChange)userInfo:nilrepeats:YES];
}
}
4、将录音文件.mp3文件上传到服务器,所以需要设置录音格式为以上格式,接下来创建录音机。
5、将.caf 文件转成.mp3格式,主要使用三方的.a库 libmp3lame.a 静态库
void)audio_PCMtoMP3
{
NSString *cafFilePath = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/downloadFile.caf"];
NSString *mp3FilePath = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/downloadFile.mp3"];
NSFileManager* fileManager=[NSFileManagerdefaultManager];
if([fileManager removeItemAtPath:mp3FilePath error:nil])
{
NSLog(@"删除");
}
@try
int
FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1],"rb"); //source 被转换的音频文件位置
fseek(pcm, 4*1024, SEEK_CUR); //skip file header
FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1],"wb"); //output 输出生成的Mp3文件位置
const int PCM_SIZE =8192;
const int MP3_SIZE =8192;
short int pcm_buffer[PCM_SIZE*2];
unsigned char
//
lame_t lame = lame_init();
lame_set_in_samplerate(lame,11025.0);
lame_set_VBR(lame, vbr_default);
lame_init_params(lame);
do
fread(pcm_buffer, 2*sizeof(shortint), PCM_SIZE, pcm);
if (read == 0)
lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
else
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
NSLog(@"%@",[exceptiondescription]);
}
@finally {
NSError
AVAudioPlayer *audioPlayer = [[AVAudioPlayeralloc]initWithContentsOfURL:[[NSURLalloc]initFileURLWithPath:mp3FilePath]error:&playerError];
self.player
player.volume =1.0f;
if (player ==nil)
{
NSLog(@"ERror creating player: %@", [playerErrordescription]);
}
[[AVAudioSessionsharedInstance]setCategory:AVAudioSessionCategorySoloAmbienterror:nil];
self.player.meteringEnabled=YES;
player.delegate =self;
}
}
转换完成之后设置播放器,注意,播放器初始化的URL必须是录音文件的URL,保证路径存在录音数据,要不会出现播放器创建失败。
二、功能:上传录音文件 问题:上传文件之后不能播放
NSURLConnection
NSString * urlString=[NSStringstringWithFormat:@"http://%@%@.shtml",SERVER_IP_ADDRESS,path];
NSMutableURLRequest* request=[[NSMutableURLRequestalloc]initWithURL:[NSURLURLWithString:urlString]cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheDatatimeoutInterval:0];
// 设置请求类型为post请求
setHTTPMethod:@"POST"];
// 设置头部数据,指定了http post请求的编码方式为multipart/form-data(上传文件必须用这个)。
[request setValue:[NSStringstringWithFormat:@"multipart/form-data; boundary=%@",BOUNDARY]forHTTPHeaderField:@"Content-Type"];
NSMutableData * body=[NSMutableDatadata];
/** 遍历字典将字典中的键值对转换成请求格式:
--Boundary+72D4CD655314C423
Content-Disposition: form-data; name="empId"
254
--Boundary+72D4CD655314C423
Content-Disposition: form-data; name="shopId"
18718
*/
//设置请求体内容 遍历字典中的内容 设置成表单上传格式
enumerateKeysAndObjectsUsingBlock:^(id key,id obj,BOOL
NSMutableString *fieldStr = [NSMutableStringstring];
[fieldStr appendString:[NSStringstringWithFormat:@"--%@\r\n",BOUNDARY]];
[fieldStr appendString:[NSStringstringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key]];
appendString:[NSStringstringWithFormat:@"%@\r\n", obj]];
appendData:[fieldStr dataUsingEncoding:NSUTF8StringEncoding]];
// NSLog(@"表单数据:%@",fieldStr);
}];
[body appendData:[[NSStringstringWithFormat:@"--%@\r\n",BOUNDARY]dataUsingEncoding:NSUTF8StringEncoding]];
NSString * contentdis = [NSStringstringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",@"fileMap",@""];
NSString * contentType = [NSStringstringWithFormat:@"Content-Type: image/jpeg\r\n\r\n" ];
appendData:[contentdis dataUsingEncoding:NSUTF8StringEncoding]];
appendData:[contentType dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSStringstringWithFormat:@"\r\n"]dataUsingEncoding:NSUTF8StringEncoding]];
/**拼装成格式:
--Boundary+72D4CD655314C423--
*/
NSString *endString = [NSStringstringWithFormat:@"--%@--\r\n",BOUNDARY];
[body appendData:[endStringdataUsingEncoding:NSUTF8StringEncoding]];
// 设置request的请求体
setHTTPBody:body];
NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueuemainQueue]completionHandler:^(NSURLResponse *response,NSData *data,NSError
[SVProgressHUDdismiss];
if (data!=nil) {
// NSLog(@"data:%@",data);
NSDictionary *dic = [NSJSONSerializationJSONObjectWithData:dataoptions:NSJSONReadingMutableContainerserror:nil];
// NSLog(@"dic:%@",response);
nil);
else{
nil,connectionError);
}
}];
三、 从服务器下载录音文件
void)loading:(NSString
{
receivedData=[[NSMutableDataalloc]init];
NSString *fileName = [fileUrlString lastPathComponent];
NSLog(@"fileName == %@",fileName);
self.Mp3Name=fileName;
NSURL *url =[NSURLURLWithString:fileUrlString];
//创建NSURLRequest和NSURLConnection,并立即启动连接
NSURLRequest *request = [[NSURLRequestalloc]initWithURL:urlcachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheDatatimeoutInterval:5.0f];
NSURLConnection *connection = [[NSURLConnectionalloc]initWithRequest:requestdelegate:selfstartImmediately:YES];
if
{
self.receivedData = [NSMutableDatadata];//初始化接收数据的缓存
}
else
{
NSLog(@"Bad Connection!");
SHOW_ALERT(@"网络连接失败");
}
}
void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse
{
[receivedData setLength:0];//置空数据
long long mp3Size = [responseexpectedContentLength];//获取要下载的文件的长度
NSLog(@"%lld",mp3Size);
}
//接收NSMutableData数据
void)connection:(NSURLConnection *)connection didReceiveData:(NSData
{
// NSLog(@"下载的data :%@",data);
receivedData appendData:data];
}
//接收完毕
void)connectionDidFinishLoading:(NSURLConnection
{
cancel];
//在保存文件和播放文件之前可以做一些判断,保证程序的健壮行:例如:文件是否存在,接收的数据是否完整等处理,此处没加,使用时注意
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(@"mp3 path=%@",documentsDirectory);
NSString *filePath = [documentsDirectorystringByAppendingPathComponent:self.Mp3Name];//mp3Name:你要保存的文件名称,包括文件类型。如果你知道文件类型的话,可以指定文件类型;如果事先不知道文件类型,可以在- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response中获取要下载的文件类型
//在document下创建文件
NSFileManager *fileManager = [NSFileManagerdefaultManager];
// if([fileManager removeItemAtPath:filePath error:nil])
// {
// NSLog(@"删除");
// }
[fileManager createFileAtPath:filePathcontents:nilattributes:nil];
NSLog(@"mp3 createFileAtPath path=%@",filePath);
//将下载的数据,写入文件中
[receivedDatawriteToFile:filePathatomically:YES];
//播放下载下来的mp3文件
self playVoice:filePath];
//如果下载的是图片则可以用下面的方法生成图片并显示 create image from data and set it to ImageView
/*
UIImage *image = [[UIImage alloc] initWithData:recvData];
[imgView setImage:image];
*/
}
四、下载文件之后,创建播放器,播放下载的文件
#pragma mark 播放录音
void)toPlayAudio:(NSNotification
{
NSString *filePath=[text.userInfoobjectForKey:@"filePath"];
NSError
// NSData *audioData = [NSData dataWithContentsOfURL:[NSURL URLWithString:filePath]];
NSData *audioData=[NSDatadataWithContentsOfFile:filePathoptions:0error:&error];
// NSLog(@"sudioData:%@",audioData);
NSError
//创建音频 播放器
AVAudioPlayer * voicePlayer = [[AVAudioPlayeralloc]initWithData:audioDataerror:&audiError];
self.chatPlayer
[chatPlayer setVolume:1];//设置音量大小
self.chatPlayer.meteringEnabled=YES;
self.chatPlayer.delegate=self;
//显示录音时间
float cTime=chatPlayer.duration;
int time=(int)cTime;
if (chatPlayer ==nil)
{
NSLog(@"ERror creating player: %@", [audiErrordescription]);
else{
//If the track is playing, pause and achange playButton text to "Play"
if([chatPlayerisPlaying])
{
chatPlayer pause];
if (markFromme) {
_recordAudioImageV.image=[UIImageimageNamed:@"ic_bubble_normalr(1).png"];
else{
_recordLeftImageV.image=[UIImageimageNamed:@"ic.png"];
}
}
//If the track is not player, play the track and change the play button to "Pause"
else
{
chatPlayer prepareToPlay];
chatPlayer play];
//播放时 打开定时器
//开启定时器
_chatTimer = [NSTimerscheduledTimerWithTimeInterval:0target:selfselector:@selector(playerPicChange)userInfo:nilrepeats:YES];
_chatTimer fire];
}
}
}
AVAudioSession 为AVAudioSessionCategoryPlayAndRecord 状态。
2、创建播放器的时候必须保证是已存在录音data数据的路径,或者是完整的录音data数据。[[AVAudioPlayer alloc] initWithData:audioData error:&audiError];
3、表单上传数据要注意表单格式