iOS录音、播放、WAV以及caf转成MP3上传后台

2023-05-16

录音、播放、转码

    • 录音
    • 播放
    • 转成MP3
    • base64转码
    • caf转码MP3
    • 调用
    • 分享心得:

录音

#import <AVFoundation/AVFoundation.h>
#import "lame.h" // 转成MP3需要该文件

@interface RecorderTestController ()<AVAudioRecorderDelegate,AVAudioPlayerDelegate>
{
  AVAudioPlayer * player;// 音频播放
}
@property (nonatomic,strong) AVAudioRecorder * audioRecorder; // 录音工具

开始录音,下面这部分代码可以直接复制使用

-(void)startRecordcase{
    //删除上次生成的文件,保留最新文件
   NSFileManager *fileManager = [NSFileManager defaultManager];
   //默认就是wav格式,是无损的
    if ([fileManager fileExistsAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"testRecorder.WAV"]]) {
        [fileManager removeItemAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"testRecorder.WAV"] error:nil];
    
    }
    //录音设置
    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
   //设置录音格式 AVFormatIDKey==kAudioFormatLinearPCM
    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
   //设置录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量), 采样率必须要设为11025才能使转化成mp3格式后不会失真
     [recordSetting setValue:[NSNumber numberWithFloat:8000] forKey:AVSampleRateKey];
     //录音通道数 1 或 2 ,要转换成mp3格式必须为双通道
     [recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
    //线性采样位数 8、16、24、32
    [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    //录音的质量
    [recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityMax] forKey:AVEncoderAudioQualityKey];
    [recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsNonInterleaved]; //交叉的
    // 设置录制音频采用高位优先的记录格式
    [recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
    // 设置采样信号采用浮点数
    [recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
    //存储录音文件
    NSURL * recordUrl = [NSURL URLWithString:[NSTemporaryDirectory()stringByAppendingPathComponent:@"testRecorder.WAV"]];
    //初始化录音对象
    NSError * error;
    self.audioRecorder = [[AVAudioRecorder alloc] initWithURL:recordUrl settings:recordSetting error:&error];

    if (error) {
        NSLog(@"%@",error.description);
        return;
    }
    self.audioRecorder.delegate = self;
    //开启音量检测
    self.audioRecorder.meteringEnabled = YES;
    AVAudioSession * audioSession = [AVAudioSession sharedInstance];//得到音频会话单例对象
    //如果不是正在录音
    if (![self.audioRecorder isRecording]) {
        [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//设置类别,表示该应用同时支持播放和录音
        [audioSession setActive:YES error:nil];//激活当前应用的音频会话,此时会阻断后台音乐的播放.
        [self.audioRecorder prepareToRecord];//准备录音
        [self.audioRecorder record];//开始录音
    }
}
//结束录音
- (void)endRecord
{
    [self.audioRecorder stop];  //录音停止
}
//录音结束后代理
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{
    [[AVAudioSession sharedInstance] setActive:NO error:nil];//一定要在录音停止以后再关闭音频会话管理(否则会报错),此时会延续后台音乐播放
    if (!flag) return;
}

播放

- (void)playWav{
//获取录音数据
NSData * wavData = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingPathComponent:@"testRecorder.WAV"]];
NSError * error;

player = [[AVAudioPlayer alloc]initWithData:wavData error:&error];
    player.delegate = self;
    if (error) {
    NSLog(@"语音播放失败,%@",error);
    return;

}

//播放器的声音会自动切到receiver,所以听起来特别小,如果需要从speaker出声,需要自己设置。
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
// 单独设置音乐的音量(默认1.0,可设置范围为0.0至1.0,两个极端为静音、系统音量):
player.volume = 1.0;
//    修改左右声道的平衡(默认0.0,可设置范围为-1.0至1.0,两个极端分别为只有左声道、只有右声道):
player.pan = -1;
//    设置播放速度(默认1.0,可设置范围为0.5至2.0,两个极端分别为一半速度、两倍速度):
player.rate = 2.0;
//    设置循环播放(默认1,若设置值大于0,则为相应的循环次数,设置为-1可以实现无限循环):
player.numberOfLoops = 0;
//调用prepareToPlay方法,这样可以提前获取需要的硬件支持,并加载音频到缓冲区。在调用play方法时,减少开始播放的延迟。
[player prepareToPlay];
//    开始播放音乐:
[player play];
}

//播放完成代理
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    if (flag) {
		//调用pause或stop来暂停播放,这里的stop方法的效果也只是暂停播放,不同之处是stop会撤销prepareToPlay方法所做的准备。
		[player stop];
		player = nil;
    }
}

转成MP3

-(void)convertToMp3SouceFilePathName:(NSString *)sourcePath isDeleteSourchFile:(BOOL)isDelete
{
    // 输入路径
    NSString *inPath = sourcePath;
    // 判断输入路径是否存在
    NSFileManager *fm = [NSFileManager defaultManager];
    if (![fm fileExistsAtPath:sourcePath]) {
        NSLog(@"文件不存在");
    }
    // 输出路径
    NSString *outPath = [[sourcePath stringByDeletingPathExtension] stringByAppendingString:@".MP3"];
    @try {
        int read, write;
        
        FILE *pcm = fopen([inPath cStringUsingEncoding:1], "rb");  //source 被转换的音频文件位置
        fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header
        FILE *mp3 = fopen([outPath 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_in_samplerate(lame, 8000);// 采样率
        lame_set_num_channels(lame, 2);//通道
        lame_set_quality(lame, 0);//质量 质量范围0~9。0最好。9最差
        lame_set_VBR(lame, vbr_default);
        lame_set_brate(lame, 8); //设置压缩比例 默认压缩比例是11
        lame_init_params(lame);
        do {
            size_t size = (size_t)(2 * sizeof(short int));
            read = (int)fread(pcm_buffer, size, 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]);
    }
    @finally {
        NSLog(@"MP3生成成功:");
        if (isDelete) {
            
            NSError *error;
            [fm removeItemAtPath:sourcePath error:&error];
            if (error == nil) {
                NSLog(@"删除源文件成功");
            }
        }
        return outPath;
    }
}

base64转码

-(NSString *)recordmp3ToBASE64; // mp3格式 base64转码
{
    NSString *strdatamp3 = [self convertToMp3SouceFilePathName:[NSTemporaryDirectory() stringByAppendingPathComponent:@"testRecorder.WAV"] isDeleteSourchFile:YES]; // 调用转码方法 转成MP3
    NSData *mp3Data = [[NSData dataWithContentsOfFile:strdatamp3] base64EncodedDataWithOptions:0];
    
    NSString * encodedRecordStr = [[NSString alloc]initWithData:mp3Data encoding:NSUTF8StringEncoding];
    
    return encodedRecordStr;
}

caf转码MP3

以上就是整个录音的过程,其中录音文件的名称以及后缀是可以更改的,后缀可以更改为caf格式。

testRecorder.WAV可以更改为testRecorder.caf。更改之后就是caf转MP3,可以根据项目要求进行格式更换。

调用

完成以上工作之后,就可以在使用的地方直接调用了。必须完成以上代码!!!
比如开始录音:

[self startRecordcase];

结束录音:

[self endRecord];

播放录音:

[self playWav];

通过接口上传录音:

[self recordmp3ToBASE64];

分享心得:

以上就是我在项目上使用的方法。其实在第一次写转码的时候出现了转码之后的文件全部是杂音的问题。找了很长时间才找到原因。
第一:

[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsNonInterleaved]; //交叉的录制
// 设置录制音频采用高位优先的记录格式
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
// 设置采样信号采用浮点数
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];

以上三种参数必须设置为No,转码之后的MP3文件就都是杂音。

第二:转成MP3需要lame文件。所以必须下载lame文件。这个在网上是都可以搜到。下载下来的lame文件包含了两个,如下图所示:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS录音、播放、WAV以及caf转成MP3上传后台 的相关文章

随机推荐

  • 计算机网络七层模型(OSI)

    1 网络模型 1 1 七层模型 xff08 OSI xff09 7层模型大而全 xff0c 但是比较复杂 xff0c 是有模型理论 xff0c 而没有实际应用 1 2 TCP IP 四层模型 四层模型 xff0c 是由实际应用发展总结出来的
  • 嵌入式Linux串口root用户自动登录

    修改 lib systemd system serial getty 64 service内容 将 ExecStart span class token operator 61 span span class token operator
  • ubuntu18.04.4安装mysql8.0

    ubuntu18 04 4中源仓库MySQL的默认版本是5 7 xff0c 不能直接sudo apt get install mysql server安装 1 下载安装包wget c https dev mysql com get mysq
  • Ubuntu下一步一步安装nginx,make: *** No rule to make target `build', needed by `default'. Stop.

    第一步 xff1a 搭建nodejs环境 注意 xff1a 阿里云Ubuntu服务器进入系统后的默认文件夹是 root xff0c 个人建议先进入 root文件夹的上层文件夹后再进行下面的操作 xff0c 输入cd 回车 如果你的服务器是全
  • 远程桌面不显示桌面一片空白

    1 Ctrl 43 Shift 43 Esc 打开任务管理器 2 在点击任务管理器左上角的 文件 xff0c 然后选择 新建任务 3 输入 explorer exe 就好了
  • C++ 提高教程 STL -string字符串拼接

    include lt iostream gt include lt string gt using namespace std string字符串拼接 void test01 string str1 61 34 我 34 str1 43 6
  • ubuntu远程控制局域网不稳定解决方法

    继之前给ubuntu配置开机自启动远程控制开启 xff08 可参考https blog csdn net qq 40234479 article details 110007052 spm 61 1001 2014 3001 5501 xf
  • vm虚拟机安装以及镜像和网路配置

    文章目录 前言一 vm虚拟机工具安装vm虚拟机工具下载 xff1a vm虚拟机安装步骤 xff1a 二 vm镜像配置vm镜像下载路径 xff1a vm镜像配置步骤 xff1a 三 vm虚拟机NAT模式上网设置 前言 vm虚拟机安装 镜像配置
  • 史上最全安装proxmox教程(基于vmware workstation)

    安装Proxmox 使用vmware workstation新建虚拟机 选择install Proxmox VE 选择 ok 选择 iagree 选择系统安装的磁盘 xff0c 可以选择 option 分区 xff0c 新手不建议 修改时区
  • 记录:matlab 转C++和Opencv,用到的函数

    Mat和vector的相互转化 转https blog csdn net guyuealian article details 80253066 Mat转vector template lt typename Tp gt vector lt
  • 安装Anaconda3后缺失大量文件的解决方法

    从Anaconda3的官网上下载最新的python3 xff0c 用管理员身份安装 xff0c 选择All Users xff0c 安装到非默认路径 xff0c 安装完毕后发现有大量文件缺失 xff0c 只有三个文件夹 xff1a cond
  • VS2017修改文件编码格式为utf-8

    对于国内用户来说 xff0c 大多设置Windows操作系统语言为简体中文 编码为GBK或GB2312 xff0c 由此导致Visual Studio 2017默认采用GBK GB2312编码格式 xff0c 其创建的项目文件 cpp js
  • 初识Godot(1)--初步使用Godot创建结点并使用脚本

    偶然间发现Godot这样一个强大的开源游戏引擎 xff0c 它十分友好的中文学习文档 xff0c 让我立刻抛弃了unity xff0c 虽然unity也没有学习多久 x1f602 今天简单的使用了一下Godot xff0c 了解了它的场景和
  • SOLIDWORKS 二次开发 VC++

    需要理解的知识 com组件原理及应用 1 IUnknown IDiapatch 2 接口的指针指向接口这个结构 xff0c 接口里面保存一个虚函数表指针 xff0c 指向接口里的函数 3 接口的使用 43 通过queryInterface
  • 关于C++父子类转换问题

    原则 xff1a 父类指针和引用可以指向子类对象 xff0c 而子类对象指针不能直接指向父类 xff0c 但是可以通过强制转换来把父类指针转换为子类指针 子类转父类后能访问的函数是父类非虚函数和子类虚函数 xff0c 父类转子类后能访问到的
  • Windows下安装wsl

    手动下载ubuntu并安装到其他盘 1 从下面这个网址下载压缩包 链接 link 2 解压压缩包 3 打开解压后的文件夹里面的ubuntu exe 如果提示系统找不到指定的路径可以 打开cmd依次输入 便可打开ubuntu exe进行安装
  • Git常见问题

    1 关于本地库和远程库main和master的问题 刚开始使用github和git时 xff0c 你可能会按以下 xff08 错误 xff09 步骤操作 xff1a 创建一个仓库 xff0c 命名 xff0c 描述 xff0c 然后添加RE
  • visual studio 编译项目生成不了pdb文件,无法调试

    解决方法 xff1a 保证项目属性设置了导出调试信息情况下 xff0c 检查此目录下的这个文件是否有改动 还原即可
  • C++ 继承中的内存布局

    今天在网上看到了一篇写得非常好的文章 xff0c 是有关c 43 43 类继承内存布局的 看了之后获益良多 xff0c 现在转在我自己的博客里面 xff0c 作为以后复习之用 谈VC 43 43 对象模型 xff08 美 xff09 简 格
  • iOS录音、播放、WAV以及caf转成MP3上传后台

    录音 播放 转码 录音播放转成MP3base64转码caf转码MP3调用分享心得 xff1a 录音 span class token macro property span class token directive hash span s