iOS 通过lame将录制音频转换成Mp3

下载

1、下载编译脚本:https://github.com/kewlbear/lame-ios-build
2、下载lame:http://lame.sourceforge.net
3、新建文件夹用来存放下载下来的lame和脚本文件
4、在新建的文件夹下运行:./build-lame.sh,运行结果如下图

编译完成后生成fat-lame文件夹,将fat-lame文件夹中的lame.hlibmp3lame.a导入工程即可

使用

将编译完成后的lame库加入到工程中

注意:
1、初始化lame的时候,要设置1为单通道。设置单声道会更大程度减少压缩后文件的体积。
lame_set_num_channels(lame,1); //设置1为单通道,默认为2双通道
2、lame_close(lame); 之前需要添加:
lame_mp3_tags_fid(lame, mp3);// 可解决获取时长不准的问题

引入库头文件

//ConvertAudioFile.m
#import "lame.h"

录制完成后转码

//这是录完再转码的方法, 如果录音时间比较长的话,会要等待几秒...
+ (void)conventToMp3WithCafFilePath:(NSString *)cafFilePath
                        mp3FilePath:(NSString *)mp3FilePath
                         sampleRate:(int)sampleRate
                           callback:(void(^)(BOOL result))callback
{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        @try {
            int read, write;

            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 mp3_buffer[MP3_SIZE];

            lame_t lame = lame_init();
            lame_set_num_channels(lame,1);//设置1为单通道,默认为2双通道
            lame_set_in_samplerate(lame, sampleRate);
            lame_set_VBR(lame, vbr_default);
            lame_init_params(lame);

            do {

                read = (int)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_mp3_tags_fid(lame, mp3);

            lame_close(lame);
            fclose(mp3);
            fclose(pcm);
        }
        @catch (NSException *exception) {
            NSLog(@"%@",[exception description]);
            if (callback) {
                callback(NO);
            }
        }
        @finally {
            NSLog(@"-----\n  MP3生成成功: %@   -----  \n", mp3FilePath);
            if (callback) {
                callback(YES);
            }
        }
    });

调用

[ConvertAudioFile conventToMp3WithCafFilePath:self.cafPathmp3FilePath:self.mp3Path

{

sampleRate:ETRECORD_RATE callback:^(BOOL result)

NSLog(@"---- 转码完成 --- result %d ---- ", result);}];

边录制边转码

通常我们是在录制结束之后, 再进行转码; 当录制的时间较长 , 会消耗的时间比较长,用户需要等待转码结束后,才能操作; 但是如果我们使用边录制,边转码的方式, 开另外开个线程同时进行转码,则几乎没有等待的时间。

具体实现方法:当录音进行中时, 会持续读取到指定大小文件来进行编码,读取不到,则线程休眠在while的条件中, 我们收到录音结束的条件,则会结束do while的循环。我们需要在录制结束后发送个信号, 让 do while跳出循环。

- (void)conventToMp3WithCafFilePath:(NSString *)cafFilePath
                        mp3FilePath:(NSString *)mp3FilePath
                         sampleRate:(int)sampleRate
                           callback:(void(^)(BOOL result))callback
{
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        @try {
            int read, write;
            
            FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1], "rb");  //source 被转换的音频文件位置
            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 mp3_buffer[MP3_SIZE];
            
            //这里要注意,lame的配置要跟AVAudioRecorder的配置一致,否则会造成转换不成功
            lame_t lame = lame_init();
            lame_set_num_channels(lame,1);//设置1为单通道,默认为2双通道 设置单声道会更大程度减少压缩后文件的体积
            lame_set_in_samplerate(lame, sampleRate);//采样率
            lame_set_VBR(lame, vbr_default);
            lame_init_params(lame);
            
            BOOL isSkipPCMHeader = NO;
            
            __weak typeof(self) weakSelf = self;
            
            do {
                long curpos = ftell(pcm);
                long startPos = ftell(pcm);
                fseek(pcm, 0, SEEK_END);
                long endPos = ftell(pcm);
                long length = endPos - startPos;
                fseek(pcm, curpos, SEEK_SET);
                
                if (length > PCM_SIZE * 2 * sizeof(short int)) {
                    
                    if (!isSkipPCMHeader) {
                        //Uump audio file header, If you do not skip file header
                        //you will heard some noise at the beginning!!!
                        fseek(pcm, 4 * 1024, SEEK_CUR);
                        isSkipPCMHeader = YES;
                        NSLog(@"skip pcm file header !!!!!!!!!!");
                    }
                    
                    read = (int)fread(pcm_buffer, 2 * sizeof(short int), PCM_SIZE, pcm);
                    write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer,
                                                           MP3_SIZE);
                    fwrite(mp3_buffer, write, 1, mp3);
                    
                    NSLog(@"read %d bytes", write);}
                
                else {
                        
                        [NSThread sleepForTimeInterval:0.05];
                        
//                        MyLog(@"sleep");
                    
                }
                
            } while (! weakSelf.stopRecord);
            
            lame_mp3_tags_fid(lame, mp3);// 解决获取时长不准的问题
            
            lame_close(lame);
            fclose(mp3);
            fclose(pcm);
        }
        @catch (NSException *exception) {
            MyLog(@"%@",[exception description]);
            if (callback) {
                callback(NO);
            }
        }
        @finally {
            MyLog(@"-----\n  MP3生成成功: %@   -----  \n", mp3FilePath);
            if (callback) {
                callback(YES);
            }
        }
    });
}

调用

[[ConvertAudioFile sharedInstance] conventToMp3WithCafFilePath:self.cafPathmp3FilePath:self.mp3Path

sampleRate:ETRECORD_RATE callback:^(BOOL result)

{
NSLog(@"---- 转码完成 --- result %d ---- ", result);

}];

参考:
https://blog.csdn.net/u011270282/article/details/77483359
https://blog.csdn.net/lovechris00/article/details/79034036
https://blog.csdn.net/ysy441088327/article/details/7392842
https://blog.csdn.net/lovechris00/article/details/52033555

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容