承接APP,小程序,公众号开发. 性价比高.+V信:17723566468 有单子的也可找我一起开发哦! 在很多地方用到语音功能. 网上千篇一律的文章针对录音以及播放.录音以及播放在此不做重点讲解(后面贴有代码).主要是将录音文件格式转成MP3上传到服务器,然后拿到地址播放. 代码将贴在最后,大家直接复制粘贴即可使用. 亲测有效:
拿到录音文件之后如何转换成MP3. 在收集相关资料之后发现现在都是用一个库就是lame
这是编译[lame](https://www.jianshu.com/p/ef5192f41de8)库详解文章
上面这边文章并没有讲解如何进行编译.很简单最后只需要将脚本文件拖拉至终端后即可.
编译出来之后将下面两个文件拖拉至项目中
Snip20181031_1.png
//将语音格式转换成MP3
- (void)transformCAFToMP3 {
NSURL * mp3FilePath = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"myselfRecord.mp3"]];
@try {
int read, write;
FILE *pcm = fopen([[self.recordFileUrl absoluteString] cStringUsingEncoding:1], "rb"); //source 被转换的音频文件位置
fseek(pcm, 4*1024, SEEK_CUR); //skip file header
FILE *mp3 = fopen([[mp3FilePath absoluteString] 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, 11025.0);
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_close(lame);
fclose(mp3);
fclose(pcm);
}
@catch (NSException *exception) {
NSLog(@"%@",[exception description]);
}
@finally {
NSLog(@"MP3生成成功");
// base64Str = [self mp3ToBASE64];
NSData *mp3Data = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingString:@"myselfRecord.mp3"]];
[[YGDZViewModel shareViewModel] updateVoice:mp3Data Success:^(NSDictionary *resDic) {
NSLog(@"当前的数据是%@",resDic);
self.voiceUrlStr=resDic[@"URL"];
}];
}
}
//上传语音的方法 其实就是上传一个文件, 替换一下上传地址即可
-(void)updateVoice:(NSData *)data Success:(void (^)(NSDictionary *resDic))success
{
YGDZUserInfoModel *model=[YGDZUserInfoModel getUseData];
NSString *tempUrl = [NSString stringWithFormat:@"%@api/Doc/Upload/UserPost/%@/0/%@/0/1",uploadFlsq,model.UserCode,model.OrgID];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:tempUrl parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:data name:@"file" fileName:@"Mp3File.mp3"mimeType:@"mp3"];
}progress:^(NSProgress * _Nonnull uploadProgress) {
}success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSError *errorJSON = [[NSError alloc] init];
NSDictionary *tempDict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:&errorJSON];
NSLog(@"responseObject=%@",tempDict);
[SVProgressHUD dismiss];
BOOL result = YES;
if(tempDict){
NSInteger Status = [[tempDict objectForKey:@"Status"] integerValue];
if(Status == 1){
NSString *tempUrl = [tempDict objectForKey:@"URL"];
success(tempDict);
}else
{
//失败处理
}
}
}failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
亲测有效.
//完整代码 直接复制粘贴即可.拉入项目即可使用.
.h文件
//
// YGDZVoiceTool.h
// gjpt
//
// Created by 刘耀宗 on 2018/10/19.
// Copyright © 2018年 CQYGKJ. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface YGDZVoiceTool : NSObject
+(instancetype)shareViewModel;
@property (nonatomic, strong) AVAudioSession *session;
@property (nonatomic, strong) AVAudioRecorder *recorder;//录音器
@property (nonatomic, strong) AVAudioPlayer *player; //播放器
@property (nonatomic, strong) NSURL *recordFileUrl; //文件地址
@property (nonatomic, strong) NSString *voiceUrlStr; //文件地址
//开始录音
- (void)startRecordNew;
//停止录音
- (void)endRecord;
- (void)PlayRecord;//播放录音
@end
NS_ASSUME_NONNULL_END
.m文件
//
// YGDZVoiceTool.m
// gjpt
//
// Created by 刘耀宗 on 2018/10/19.
// Copyright © 2018年 CQYGKJ. All rights reserved.
//
#import "YGDZVoiceTool.h"
#import <AVFoundation/AVFoundation.h>
#import "lame.h"
@interface YGDZVoiceTool (){
NSTimer *_timer; //定时器
NSInteger countDown; //倒计时
NSString *filePath;
UIButton* _playBtn;
UIButton* _encodeBtn;
UIButton* _recordBtn;
UIButton* _playMp3Btn;
UILabel* _cafFileSize;
UILabel* _mp3FileSize;
UILabel* _duration;
UILabel* _format;
UISegmentedControl* _sampleRateSegment;
UISegmentedControl* _qualityRateSegment;
UIPickerView* _picker;
AVAudioRecorder* _recorder;
AVAudioPlayer* _player;
AVAudioPlayer* _mp3Player;
UIProgressView* _progress;
UIProgressView* _mp3Progress;
BOOL _hasCAFFile;
BOOL _recording;
BOOL _playing;
BOOL _hasMp3File;
BOOL _playingMp3;
NSURL* _recordedFile;
CGFloat _sampleRate;
AVAudioQuality _quality;
NSInteger _formatIndex;
UIAlertView* _alert;
NSDate* _startDate;
}
@property (nonatomic, strong) UILabel* cafFileSize;
@property (nonatomic, strong) UILabel* mp3FileSize;
@property (nonatomic, strong) UILabel* duration;
@property (nonatomic, strong) UILabel* format;
@property (nonatomic, strong) UIButton* recordBtn;
@property (nonatomic, strong) UIButton* playBtn;
@property (nonatomic, strong) UIButton* encodeBtn;
@property (nonatomic, strong) UIButton* playMp3Btn;
@property (nonatomic, strong) UISegmentedControl* sampleRateSegment;
@property (nonatomic, strong) UISegmentedControl* qualityRateSegment;
@property (nonatomic, strong) UIProgressView* progress;
@property (nonatomic, strong) UIProgressView* mp3Progress;
@property (nonatomic, copy) NSString *filePath;
@property (nonatomic, strong) AVAudioSession* audioSession ;
@end
@implementation YGDZVoiceTool
+(instancetype)shareViewModel{
static id instance;
static dispatch_once_t once;
dispatch_once(&once, ^{
instance=[[self alloc] init];
});
return instance;
}
- (void)PlayRecord {
NSLog(@"播放录音");
[self.recorder stop];
if ([self.player isPlaying])return;
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:self.recordFileUrl error:nil];
NSLog(@"%li",self.player.data.length/1024);
//放外音
[self.session setCategory:AVAudioSessionCategoryPlayback error:nil];
[self.session setActive:YES error:nil];
[self.player play];
}
//开始录音
- (void)startRecordNew
{
//删除上次生成的文件,保留最新文件
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([NSTemporaryDirectory() stringByAppendingString:@"myselfRecord.mp3"]) {
[fileManager removeItemAtPath:[NSTemporaryDirectory() stringByAppendingString:@"myselfRecord.mp3"] error:nil];
}
if ([NSTemporaryDirectory() stringByAppendingString:@"selfRecord.wav"]) {
[fileManager removeItemAtPath:[NSTemporaryDirectory() stringByAppendingString:@"selfRecord.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:11025.0] 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:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
//存储录音文件
self.recordFileUrl = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"selfRecord.wav"]];
//初始化
_recorder = [[AVAudioRecorder alloc] initWithURL:self.recordFileUrl settings:recordSetting error:nil];
//开启音量检测
_recorder.meteringEnabled = YES;
_audioSession = [AVAudioSession sharedInstance];//得到AVAudioSession单例对象
if (![_recorder isRecording]) {
[_audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//设置类别,表示该应用同时支持播放和录音
[_audioSession setActive:YES error:nil];//启动音频会话管理,此时会阻断后台音乐的播放.
[_recorder prepareToRecord];
[_recorder peakPowerForChannel:0.0];
[_recorder record];
}
}
//停止录音
- (void)endRecord
{
[_recorder stop];
// AVAudioSession *session = [AVAudioSession sharedInstance];
[_audioSession setCategory:AVAudioSessionCategoryPlayback error:NULL];
[_audioSession setActive:YES error:NULL];
// [_audioSession setActive:NO error:nil]; //一定要在录音停止以后再关闭音频会话管理(否则会报错),此时会延续后台音乐播放
[self.session setCategory:AVAudioSessionCategoryPlayback error:nil]; //此处需要恢复设置回放标志,否则会导致其它播放声音也会变小
[self transformCAFToMP3];
}
- (void)transformCAFToMP3 {
NSURL * mp3FilePath = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"myselfRecord.mp3"]];
@try {
int read, write;
FILE *pcm = fopen([[self.recordFileUrl absoluteString] cStringUsingEncoding:1], "rb"); //source 被转换的音频文件位置
fseek(pcm, 4*1024, SEEK_CUR); //skip file header
FILE *mp3 = fopen([[mp3FilePath absoluteString] 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, 11025.0);
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_close(lame);
fclose(mp3);
fclose(pcm);
}
@catch (NSException *exception) {
NSLog(@"%@",[exception description]);
}
@finally {
NSLog(@"MP3生成成功");
// base64Str = [self mp3ToBASE64];
NSData *mp3Data = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingString:@"myselfRecord.mp3"]];
[[YGDZViewModel shareViewModel] updateVoice:mp3Data Success:^(NSDictionary *resDic) {
NSLog(@"当前的数据是%@",resDic);
self.voiceUrlStr=resDic[@"URL"];
}];
}
}
@end
网友评论