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上传后台 的相关文章

  • Phonegap - navigator.app.backHistory() 不适用于 HTML 后退按钮

    在我的应用程序中 我使用phonegap 2 6 对于后退按钮 我使用以下函数 document addEventListener backbutton onBackKeyDown false function onBackKeyDown
  • iOS UIView子类,将透明文本绘制到背景

    我想将文本绘制到 UIView 上的子类上 以便文本从形状中切出 并且视图后面的背景显示出来 就像在 OSX Mavericks 徽标中找到的那样here http www n3rdabl3 co uk wp content uploads
  • 如何在松开按钮后立即看到新的视频层?

    我有一个应用程序 用户可以按住按钮来拍摄视频 然而 当他们这样做时 带有视频播放的新图层不会立即出现 相反 有一个非常短的延迟 在用户松开按钮后 您可以看到相机仍然显示相机所看到的内容 延迟结束后 视频立即显示并开始播放 但是 我怎样才能使
  • GCD 和线程

    我想了解一些有关 GCD 和线程的知识 我的视图控制器中有一个 for 循环 它要求我的模型执行一些异步网络请求 因此 如果循环运行 5 次 模型将发出 5 个网络请求 考虑到我正在使用 NSURLConnection 的 sendAsyn
  • 在 Flurry 中记录比错误 ID 更多信息的方法?

    我目前使用 iOS 版 Flurry 5 4 0 我担心在方法方面是否能够记录更多信息 而不仅仅是错误 ID void logError NSString errorID message NSString message error NSE
  • 如何从 GMSPlace 地址组件中提取街道、城市等

    我正在使用适用于 iOS 的 Google Places API 可以成功检索附近的地点并将地址显示为字符串 我想做的是提取地址组件 例如城市 以存储在数据库中 文档表明 GMSPlace 有一个 addressComponents 属性
  • 如何获取核心数据中现有实体(表)的列表

    如何获取核心数据中特定模式 托管对象模型 的现有实体 表 列表 我刚刚开始实施核心数据概念并坚持这些要点 就像是 SELECT COUNT FROM information schema tables WHERE table schema
  • 只有根级导航目的地对于具有同质路径的导航堆栈有效

    我正在尝试整合NavigationStack在我的 SwiftUI 应用程序中 我有四个看法 CealUIApp OnBoardingView UserTypeView and RegisterView 我想从OnBoardingView
  • 使用 AVMutableVideoCompositionLayerInstruction 旋转视频

    我正在 iPhone 4 上使用前置摄像头拍摄视频 并将视频与其他一些媒体资源结合起来 我希望该视频为纵向 所有视频的默认方向都是横向 在某些情况下 您必须手动管理 我正在使用 AVFoundation 特别是 AVAssetExportS
  • 在 iOS 上的 OpenGL ES 2.0 中创建 16 位亮度纹理

    我的文件中有 16 位数据 我正在尝试将其加载到 iOS 上的 OpenGL 亮度纹理中 如果我手动将 16 位值重新调整为 8 位 我可以按如下方式加载和显示数据 glTexImage2D GL TEXTURE 2D 0 GL LUMIN
  • 在完成块中保留循环

    在我的课堂上 我创建了这个方法 void refreshDatasourceWithSuccess CreateDataSourceSuccessBlock successBlock failure CreateDataSourceFail
  • 如何使用 iOS 可达性

    我正在开发一个使用网络的 iPhone 应用程序 iPhone 通过 HTTP 请求与我的服务器通信 并且应该可以在 WiFi 和 3G 上运行 我目前使用NSURLConnection initWithRequest向我的服务器发送异步请
  • 使用 UItableviewCell 实现 Google 地图

    我正在尝试在 UItableviewCell 组件内实现谷歌地图 我这样做的方法是在原型单元中定义 GMSMapView 然后使用 dequeueReusableCell 方法配置地图单元 但是 我尝试应用的任何更改都会失败 例如添加标记
  • 使用远程图像创建 MSSticker

    我正在尝试找出使用网络上托管的图像创建 MSStickers 的方法 我可以使用本地图像创建 MSStickers 例如 NSString imagePath NSBundle mainBundle pathForResource imag
  • mgwt - 以编程方式改变方向

    是否可以在 gwt mgwt 应用程序中更改强制执行特定的屏幕方向 可以说我希望用户始终以横向模式使用应用程序 这取决于 是作为phonegap应用程序 而不是在浏览器内部 如果您作为 Web 应用程序运行 则不需要t get any co
  • UIStackView分布均匀填充

    所以 我有一个UIStackView其中包含四 4 UIViews 如果我删除其中一 1 个UIViews 其他三 3 个将填满UIStackView 我的问题 如何添加最大高度UIView这样它就不会填满整个空间UIStackView即使
  • Admob 广告无法快速显示

    您好 我正在尝试将 admob 广告添加到已使用 swift 上传到应用商店的应用程序中 我在 admob 中制作了一个应用程序并复制了 appid 和广告 id 并显示了各自的横幅广告和插页式广告 这里的问题是当我写这行时 request
  • UITableView:显示 tableFooterView 时运行代码?

    我正在使用 UIView表页脚视图 http developer apple com library ios documentation uikit reference UITableView Class Reference Referen
  • 如何在 Swift 中将文件名与文件扩展名分开?

    给定包中文件的名称 我想将该文件加载到我的 Swift 应用程序中 所以我需要使用这个方法 let soundURL NSBundle mainBundle URLForResource fname withExtension ext 无论
  • 使用 NSString 进行 UTF8 解码

    我是 Objective C 新手 尝试使用以下示例将格式错误的 UTF8 编码 NSString 转换为格式良好的字符串苹果文档 http developer apple com library mac documentation Coc

随机推荐

  • 计算机网络七层模型(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