在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
2018年05月16日 15:22:44 msmwncx阅读数:548 https://blog.csdn.net/msmwncx/article/details/80336973 版权声明:本文为博主原创文章,未经博主允许不得转载。如有问题,请联系QQ547394765 https://blog.csdn.net/msmwncx/article/details/80336973 距离上次写博客已经好久好久了ZZZzzzzzzz。 首先交代下用处,做的IM项目,需要语音聊天,研究了下AVAudioRecorder。
其实挺简单的,主要步骤就是 创建一个recorder -> recorder.record() -> recorder.stop() 不多说 上代码
func createRecord(path: String) { if self.recorder != nil { self.resetRecorder() } let url = URL(fileURLWithPath: path) self.cafPathStr = path self.mp3PathStr = self.recordFileCaf2Mp3(cafPath: path) let setting = self.recordSetting() do { self.recorder = try AVAudioRecorder(url: url, settings: setting) self.recorder?.delegate = self self.recorder?.isMeteringEnabled = true } catch { XMPPAudioLog("create recorder error:") } } func startRecord(path: String) { guard self.recorder == nil else { EdoAssertionFailure("should reset recorder before start record") return } if self.recorder == nil { self.createRecord(path: path) } guard let _ = self.recorder else { assertionFailure("ChatAudio: recorder could not be nil") return } //if isRecording, should stop first if let _ = self.recorder?.isRecording { self.recorder?.stop() } //stop all player self.stopAllMusic() let audioSession = AVAudioSession.sharedInstance() do { try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord) if let isRecorder = self.recorder?.isRecording, isRecorder == false { self.recorder?.record() } } catch { } } 这里的mp3PathStr是转换成MP3格式的路径 这里是一些配置还有大小以及mp3路径的转换方法 func recordSetting() -> [String: Any] { var recordSetting = [String: Any]() //format of record /**** kAudioFormatMPEG4AAC压缩格式能在显著减小文件的同时,保证音频的质量。 ****/ recordSetting[AVFormatIDKey] = NSNumber(value: kAudioFormatLinearPCM) //sampling rate of record /****** 采样率越高,文件越大,质量越好,反之,文件小,质量相对差一些,但是低于普通的音频,人耳并不能明显的分辨出好坏。最终选取哪一种采样率,由我们的耳朵来判断。建议使用标准的采样率,8000、16000、22050、44100。 *****/ recordSetting[AVSampleRateKey] = NSNumber(value: 8000) //The quality of record recordSetting[AVEncoderAudioQualityKey] = NSNumber(value: AVAudioQuality.high.rawValue) //线性采样位数 8、16、24、32 recordSetting[AVLinearPCMBitDepthKey] = NSNumber(value: 8) //录音通道数 1 或2 /**** AVNumberOfChannelsKey用于指定记录音频的通道数。1为单声道,2为立体声。 ***/ recordSetting[AVNumberOfChannelsKey] = NSNumber(value: 2) return recordSetting } func fileSizeAtPath(path: String) -> String { if FileManager.default.fileExists(atPath: path) { let attributes = try? FileManager.default.attributesOfItem(atPath: path) if let attrs = attributes, let size = attrs[FileAttributeKey(rawValue:"NSFileSize")] as? Int64 { return ByteCountFormatter.string(fromByteCount: size, countStyle: ByteCountFormatter.CountStyle.file) } } return "0 KB" } func recordFileCaf2Mp3(cafPath: String) -> String { var mp3Path = cafPath if cafPath.hasSuffix(".caf") { mp3Path = cafPath.replacingOccurrences(of: "caf", with: "mp3", options: NSString.CompareOptions.caseInsensitive, range: Range(cafPath.index(cafPath.startIndex, offsetBy: cafPath.count - 3)..<cafPath.endIndex)) } return mp3Path } 由于我这边是要做语音聊天,所以每次结束都会把recorder销毁掉 func deleteRecording() { guard let recorder = self.recorder, recorder.isRecording == false else { assertionFailure("ChatAudio: recorder must be stopped") return } self.recorder?.deleteRecording() self.resetRecorder() } func resetRecorder() { self.recorder?.stop() self.recorder = nil self.mp3PathStr = "" self.cafPathStr = "" } emmmm 好像就这么多了 具体一些缘由 为什么这么写什么的 可以参考一下apple的官方资料 然后就是转MP3 转mp3我是用的lame.h 和 libmp3lame.a 然后遇到一个什么 libmp3lame.a 不支持bitcode什么的问题 于是用以下解决 1.http://sourceforge.net/projects/lame/files/lame/3.99/ 下载lame的最新版本并解压 2.https://github.com/kewlbear/lame-ios-build 下载build的脚本 下载之后得到lame-build.sh拷贝到刚才解压后的文件夹 3.用一些编辑器按照注释修改lame-build.sh 如下图 4.cd 到1解压的目录下 执行脚本 chmod 777 lame-build.sh 等待1分钟左右就编译完成了 5.里边生成fat-lame目录和thin-lame目录,分别存放合并所有指令集的静态库,以及各指令集的静态库. 具体用哪个里边的lame.h和libmp3lame.a 我就忘记了。。。试一下吧。 然后就是转MP3文件了 我查了下资料,前人大部分都是用的OC写的 于是我用了一个OC文件转译了一下 + (BOOL)audio_PCMtoMP3:(NSString *)cafPath mp3Path:(NSString *)mp3Path { @try { int read, write; FILE *pcm = fopen([cafPath cStringUsingEncoding:1], "rb"); //source 被转换的音频文件位置 fseek(pcm, 4*1024, SEEK_CUR); //skip file header FILE *mp3 = fopen([mp3Path cStringUsingEncoding:1], "wb"); //output 输出生成的Mp3文件位置 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(); //should be equle with AVSampleRateKey lame_set_in_samplerate(lame, 8000.0); lame_set_VBR(lame, vbr_default); lame_init_params(lame); do { read = fread(pcm_buffer, 2*sizeof(short int), 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]); return NO; } @finally { NSLog(@"MP3生成成功: %@",mp3Path); return YES; } } 注意里边有一句 lame_set_in_samplerate(lame, 8000.0); 这里的8000要与recorder设置里的采样率一致,否则会变声。(我感觉一些app的变音就是这么来的,有兴趣可以试试,开始我设置的采样率是8000,这里写的是44100,然后声音特别细) |
请发表评论