最近做的一个项目,项目中有个录音功能,采用的录音方法是IOS下的AVAudioRecorder。录音效果不错,但是录制的原生.pcm文件太大,每分钟大约10M左右。

找了下相关的音频压缩方法,用speex的比较多。按照speex的示例文档折腾了半天,实现了转码压缩。speex压缩率还蛮高的,但是压缩之后的pcm文件不能播放,

需要解码回来,可是按照示例代码解码之后的pcm文件依旧不能播放。百思不得解,遂google之,未果。得到只言片语,说是没有添加wav头云云。个人感觉录音得

到的pcm文件是有wav头的,因为录制好的文件由AVAudioPlayer播放的时候并不受文件后缀名影响。由于不了解speex的编码原理,也没时间继续深究,只好寻求其他办法。

下了一个比较靠谱的speex转码demo,仔细研究了一下。感觉蛮复杂的(对于我这个音频编解码门外汉来说),大致是先要跳过pcm里的wav头,获取到单纯的

pcm文件之后再行编解码,中间需要分析pcm祯什么的,反正我是弄不来这个,看着头都大了。

继续寻找更简单的解决办法。。。看到一篇介绍使用lame来转码到mp3文件的博客(http://ikinglai.blog.51cto.com/6220785/1228309),感觉比较靠谱,从lame官网下了库文

件,在命令行里打包了.o文件,(如果不知道怎么打包,试试http://download.csdn.net/download/ixfly/4440512)导入到工程里,按照demo试了下,果然好使!编码实现非常简

单,得到的mp3文件大小大概是pcm文件的1/10左右。

接下来就是实现边录边转码了。上面博客里提供的demo实际上就是采用了边录边转码的实现。但是有两个问题,一个问题是编译通不过(把工程里lame相关的库文件都移除,

导入刚才打包的.o文件,在.o文件同目录下要有lame.h和lame.c文件,但是不要导入这两个文件,否则编译错误,具体原因还得再查一下)。另一个问题是这个demo的录音

功能不是基于AVAudioRecorder实现的,用的是AVAudioQueue,基于数据缓冲实现的,可以实时获取录音的buffer数据,做边录边转码很方便。而AVAudioRecorder则不能

实时获得录音数据。

于是只能是对AVAudioRecorder生成的pcm文件读取来实现实时转码了。主要的思路是:录音开始后开启转码线程,转码线程读取pcm文件,设定每次转码的frame大小,当

读入的文件小于frame大小,就等待,当文件大于这个值时,则读取frame大小的文件,并转码,添加至data中。直到录音停止。

  1. -(void)main
  2. {
  3. //mp3压缩参数
  4. lame = lame_init();
  5. lame_set_num_channels(lame, 2);
  6. lame_set_in_samplerate(lame, 88200);
  7. lame_set_brate(lame, 88);
  8. lame_set_mode(lame, 1);
  9. lame_set_quality(lame, 2);
  10. lame_init_params(lame);
  11. //这种方式初始化的NSData不需要手动释放
  12. NSMutableData *mp3Data = [[NSMutableData alloc] init];
  13. NSLog(@"record path: %@",_filePath);
  14. NSLog(@"out path: %@", _outFile);
  15. FILEFILE *fp;
  16. fp = fopen([_filePath cStringUsingEncoding:NSASCIIStringEncoding], "rb");
  17. long curpos;
  18. //if(fp) 这句得补上,但是还不确定是否有问题
  19. while (true)
  20. {
  21. //需要手动释放
  22. NSData *audioData = nil;
  23. curpos = ftell(fp);
  24. long startPos = ftell(fp);//文件当前读到的位置
  25. fseek(fp, 0, SEEK_END);
  26. long endPos = ftell(fp);//文件末尾位置
  27. long length = endPos - startPos;//剩下未读入文件长度
  28. fseek(fp, curpos, SEEK_SET);//把文件指针重新置回
  29. charchar *buff[frameSize] = {0};
  30. if(length > frameSize)
  31. {
  32. fread(buff, 1, frameSize, fp);
  33. audioData = [NSData dataWithBytes:buff length:frameSize];
  34. shortshort *recordingData = (shortshort *)audioData.bytes;
  35. int pcmLen = audioData.length;
  36. int nsamples = pcmLen / 2;
  37. unsigned char buffer[pcmLen];
  38. //执行encode
  39. int recvLen = lame_encode_buffer(lame, recordingData, recordingData, nsamples, buffer, pcmLen);
  40. [mp3Data appendBytes:buffer length:recvLen];
  41. }
  42. else
  43. {
  44. if (_setToStopped)
  45. {
  46. fread(buff, 1, length, fp);
  47. audioData = [NSData dataWithBytes:buff length:length];
  48. shortshort *recordingData = (shortshort *)audioData.bytes;
  49. int pcmLen = audioData.length;
  50. int nsamples = pcmLen / 2;
  51. unsigned char buffer[pcmLen];
  52. //执行encode
  53. int recvLen = lame_encode_buffer(lame, recordingData, recordingData, nsamples, buffer, pcmLen);
  54. [mp3Data appendBytes:buffer length:recvLen];
  55. break;
  56. }
  57. else
  58. {
  59. [NSThread sleepForTimeInterval:0.05];
  60. }
  61. }
  62. }
  63. //写入文件
  64. [mp3Data writeToFile:_outFile atomically:YES];
  65. //释放lame
  66. lame_close(lame);
  67. }

现在是一个初步的代码,好多东西没有优化,只是实现了功能。相关代码文件之后补上。

IOS 实现录音PCM转MP3格式(边录音边转码)的更多相关文章

  1. iOS: lame框架将PCM录音转成MP3格式

    lame框架将PCM录音转成MP3格式 1.lame下载地址:https://github.com/rbrito/lame,它是一个不可执行的文件,需要借助build-lame.sh脚本将其编译成.a ...

  2. 在java中使用ffmpeg将amr格式的语音转为mp3格式

    ffmpeg是一个非常强大的音视频处理工具,官网是:http://ffmpeg.org/. 由于ffmpeg在windows上和linux系统上的执行文件不一样(Windows上不需要安装ffmpeg ...

  3. lame,把ios录音转换为mp3格式

    在ios设备中进行录音,录音文件的格式为caf.但这种格式在很多设备中没法播放.为了适应终端的播放功能,特将caf转换为mp3格式文件来使用. 在录制caf文件时,需要使用双通道,否则在转换为MP3格 ...

  4. Swift iOS实现把PCM语音转成MP3格式

    最近折腾了swift的语音录制识别和转码,这块还是比较坑的,由于语音识别的准确度实测大概也就80%左右,所以还是需要上传录音文件啊.首先是用讯飞语音SDK实现语音录制和识别(语音听写),第一个坑是讯飞 ...

  5. 微信录音文件上传到服务器以及amr转化成MP3格式

    微信公众号音频接口开发 根据业务需求,我们可能需要将微信录音保存到服务器,而通过微信上传语音接口上传到微信服务器的语音文件的有效期只有3天,所以需要将文件下载到我们自己的服务器. 上传语音接口 wx. ...

  6. jav音频格式转换 ffmpeg 微信录音amr转mp3

    项目背景: 之前公司开发了一个微信公众号,要求把js-sdk录音文件在web网页也能播放.众所周知,html的<audio>标签ogg,mp3,wav,也有所说苹果safari支持m4a格 ...

  7. 微信录音文件上传到服务器以及amr转化成MP3格式,linux上转换简单方法

    微信公众号音频接口开发 根据业务需求,我们可能需要将微信录音保存到服务器,而通过微信上传语音接口上传到微信服务器的语音文件的有效期只有3天,所以需要将文件下载到我们自己的服务器. 上传语音接口 wx. ...

  8. Electron-vue中通过WebAudioApi实现录音功能,并转换为mp3格式,实时监测音频设备变化

    实现以下功能: 1.检测当前音频环境,是否支持录音(WebAudio Api): 2.获取输入.输出设备列表,获取电脑默认的音频设备: 3.试音功能,通过分析录音样本数据,判断是否录到声音: 4.实时 ...

  9. python进行mp3格式判断

    python进行mp3格式判断 项目中使用mp3格式进行音效播放,遇到一个mp3文件在程序中死活播不出声音,最后发现它是wav格式的文件,却以mp3结尾.要对资源进行mp3格式判断,那么如何判断呢,用 ...

随机推荐

  1. CPU profiling

    http://gernotklingler.com/blog/gprof-valgrind-gperftools-evaluation-tools-application-level-cpu-prof ...

  2. java 遍历Map的四种方式

      java 遍历Map的四种方式 CreationTime--2018年7月16日16点15分 Author:Marydon 一.迭代key&value 第一种方式:迭代entrySet 1 ...

  3. txt文件匹配脚本

    # -*- coding:utf-8 -*- import time start = time.clock() data=open("Data.txt","r" ...

  4. java中使用相对路径读取文件的写法总结 ,以及getResourceAsStream() (转)

    https://blog.csdn.net/my__sun_/article/details/74450241 读取文件的写法,相对路径 在当前的目录结构中读取test.txt的有四种写法 简单粗暴的 ...

  5. codevs 1013 求先序排列

    题目链接:http://codevs.cn/problem/1013/ 题目描述 Description 给出一棵二叉树的中序与后序排列.求出它的先序排列.(约定树结点用不同的大写字母表示,长度< ...

  6. Inno Setup入门(七)——提供安装语言选项

    Inno Setup安装目录下有一个Languages的文件夹,该文件夹提供了可供使用的语言,通过在脚本中加入[languages]段,可以实现该项功能,实现代码如下: [setup] ;全局设置,本 ...

  7. 简化版的SpringMVC框架的实现思路

    在SpringMVC基本统一Java web开发技术栈的环境下, 这是一个有点过时的话题了. SpringMVC的特点主要在于注解型的RequestMapping和参数机制非常灵活, 另外得益于Spr ...

  8. LeetCode——Combination Sum II

    Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...

  9. 【JS】移动端 好用的分享插件 soshm.js

    参考链接:https://www.cnblogs.com/milo-wjh/p/6796082.html 对于qq内置浏览器分享功能处理:https://www.cnblogs.com/xuzheng ...

  10. 总结一下关于mysql 5.6 新特性

    一直断断续续的看一些mysql特性,今天总结一下,以下是列表,网址 http://mariadb.org/ (也是类似的特性), http://mysql.com/ 最近在看关于mysql新特性的一些 ...