录音、播放音频(本地、在线)

#import “VoiceInputCell.h”
#import
#define kRecordAudioFile @“myRecord.wav”

@interface VoiceInputCell ()

@property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音频录音机
@property (nonatomic,strong) NSTimer *timer;///录音时长
///录音时长
@property (nonatomic,assign) NSInteger record_time;

///提示文字
@property (nonatomic,strong) UILabel *placeholder_normal;
///右侧图标
@property (nonatomic,strong) UIImageView *imageView_normal;

///删除
@property (nonatomic,strong) UIButton *delete_button;
///有录音时灰色背景
@property (nonatomic,strong) UIView *backView_small;

///底部白色背景
@property (nonatomic,strong) UIView *backView_normal;

#pragma mark—播放
///本地文件播放
@property (nonatomic,strong) AVAudioPlayer *player;

#pragma mark—回显 以及播放在线音频文件
#pragma mark—回显 以及播放在线音频文件
#pragma mark—回显 以及播放在线音频文件
@property (nonatomic, strong) AVPlayer *avPlayer;
///是否是详情
@property (nonatomic,assign) BOOL isDetailView;

@end

@implementation VoiceInputCell

  • (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
    }

  • (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
    }

-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.backgroundColor = [UIColor clearColor];
self.contentView.backgroundColor = [UIColor clearColor];
if ([reuseIdentifier isEqualToString:@“VoiceInputCell_Detail”]){
self.isDetailView = YES;
}
[self createView];
}
return self;
}

-(void)createView{
//正常状态-未录入语音
self.backView_normal = [[UIView alloc] init];
[self.contentView addSubview:self.backView_normal];
[self.backView_normal mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(0);
make.height.mas_equalTo(WMAKENEW(68));
make.bottom.mas_equalTo(0);
make.top.mas_equalTo(Cell_Spacing);
}];
self.backView_normal.backgroundColor = UIColor.whiteColor;
self.backView_normal.layer.cornerRadius = WMAKENEW(4);
UITapGestureRecognizer *tapOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapClickAction)];
[self.backView_normal addGestureRecognizer:tapOne];

//有录音时灰色背景
self.backView_small = [[UIView alloc] init];
[self.backView_normal addSubview:self.backView_small];
[self.backView_small mas_makeConstraints:^(MASConstraintMaker *make) {
    make.right.mas_equalTo(-WMAKENEW(16));
    make.top.mas_equalTo(WMAKENEW(12));
    make.bottom.mas_equalTo(-WMAKENEW(12));
    make.width.mas_equalTo(WMAKENEW(80));
}];
self.backView_small.backgroundColor = rgba(244, 246, 248, 1);
self.backView_small.layer.cornerRadius = WMAKENEW(4);
self.backView_small.hidden = YES;

//右侧图标
self.imageView_normal = [[UIImageView alloc] init];
[self.backView_normal addSubview:self.imageView_normal];
[self.imageView_normal mas_makeConstraints:^(MASConstraintMaker *make) {
    make.right.mas_equalTo(-WMAKENEW(16));
    make.width.height.mas_equalTo(20);
    make.centerY.equalTo(self.backView_normal);
}];

//时长、提示语
self.placeholder_normal = [Support_ControlSet createLabelTextColor:rgba(151, 151, 151, 0.44) textFont:12 textAligment:NSTextAlignmentLeft addToView:self.backView_normal];
self.placeholder_normal.font = FONT_SizeAndWight(12, UIFontWeightMedium);
[self.placeholder_normal mas_makeConstraints:^(MASConstraintMaker *make) {
    make.right.equalTo(self.imageView_normal.mas_left).mas_offset(-WMAKENEW(10));
    make.centerY.equalTo(self.backView_normal);
}];
self.placeholder_normal.userInteractionEnabled = NO;
self.imageView_normal.userInteractionEnabled = NO;
self.backView_normal.userInteractionEnabled = YES;

//删除
self.delete_button = [[UIButton alloc] init];
[self.backView_normal addSubview:self.delete_button];
[self.delete_button setImage:ImageName(@"delete") forState:UIControlStateNormal];
[self.delete_button mas_makeConstraints:^(MASConstraintMaker *make) {
    make.right.mas_equalTo(self.backView_small.mas_left);
    make.top.bottom.mas_equalTo(0);
    make.width.mas_equalTo(16+WMAKENEW(24));
}];
[self.delete_button addTarget:self action:@selector(deleteButtonClick) forControlEvents:UIControlEventTouchUpInside];
self.delete_button.userInteractionEnabled = YES;



UILabel *leftLabel = [Support_ControlSet createLabelTextColor:[Support_Color rebuildColor_Left_withType:ViewShowTypeAdd] textFont:14 textAligment:NSTextAlignmentLeft addToView:self.contentView];
[leftLabel mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.mas_equalTo(WMAKENEW(20));
    make.width.mas_equalTo(WMAKENEW(90));
    make.centerY.equalTo(self.backView_normal);
}];


if (self.isDetailView){
    leftLabel.text = @"语音";
    
    self.delete_button.hidden = YES;
    self.backView_small.hidden = NO;
    self.placeholder_normal.text = @"点击开始播放";
    self.placeholder_normal.textColor = rgba(151, 151, 151, 1);
    self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@"\U0000E66B", 20)];
    [self.imageView_normal mas_updateConstraints:^(MASConstraintMaker *make) {
        make.right.mas_equalTo(-WMAKENEW(32));
    }];
}else{
    leftLabel.text = @"上传语音";
    [self deleteButtonClick];
}

}

#pragma mark—创建
/**

  • 设置音频会话
    */
    -(void)setAudioSession:(BOOL)isRecord{
    AVAudioSession *audioSession=[AVAudioSession sharedInstance];
    //设置为 录音状态
    [audioSession setCategory:isRecord ? AVAudioSessionCategoryRecord:AVAudioSessionCategoryPlayback error:nil];
    [audioSession setActive:YES error:nil];
    }

/**

  • 取得录音文件保存路径
  • @return 录音文件路径
    */
    -(NSURL *)getSavePath{
    NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    urlStr=[urlStr stringByAppendingPathComponent:kRecordAudioFile];
    NSURL *url=[NSURL fileURLWithPath:urlStr];
    return url;
    }

/**

  • 取得录音文件设置
  • @return 录音设置
    */
    -(NSDictionary *)getAudioSetting{
    NSMutableDictionary *dicM=[NSMutableDictionary dictionary];
    //设置录音格式
    [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
    //设置录音采样率,8000是电话采样率,对于一般录音已经够了
    [dicM setObject:@(8000) forKey:AVSampleRateKey];
    //设置通道,这里采用单声道
    [dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
    //每个采样点位数,分为8、16、24、32
    [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
    //是否使用浮点数采样
    [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
    //…其他设置等
    return dicM;
    }

/**

  • 获得录音机对象
  • @return 录音机对象
    */
    -(AVAudioRecorder *)audioRecorder{
    if (!_audioRecorder) {
    //创建录音文件保存路径
    NSURL *url=[self getSavePath];
    //创建录音格式设置
    NSDictionary *setting=[self getAudioSetting];
    //创建录音机
    NSError *error=nil;
    _audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
    _audioRecorder.delegate=self;
    _audioRecorder.meteringEnabled=YES;//如果要监控声波则必须设置为YES
    if (error) {
    NSLog(@“创建录音机对象时发生错误,错误信息:%@”,error.localizedDescription);
    return nil;
    }
    }
    return _audioRecorder;
    }

/**

  • 录音声波监控定制器
  • @return 定时器
    */
    -(NSTimer *)timer{
    if (!_timer) {
    _timer=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    }
    return _timer;
    }
    -(void)timerAction{
    self.record_time ++;
    self.placeholder_normal.text = NSIntegerToString(self.record_time);
    if (self.record_time == 2){
    self.backView_normal.userInteractionEnabled = YES;
    }
    if(self.record_time >= 60){
    [self record_Stop];
    }
    }
    #pragma mark—删除录音
    -(void)deleteButtonClick{
    self.record_time = 0;
    self.delete_button.hidden = self.backView_small.hidden = YES;
    self.placeholder_normal.text = @“点击开始录音”;
    self.placeholder_normal.textColor = rgba(151, 151, 151, 0.44);
    self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E63E”, 20)];
    [self.imageView_normal mas_updateConstraints:^(MASConstraintMaker *make) {
    make.right.mas_equalTo(-WMAKENEW(16));
    }];
    if (_player){
    [_player stop];
    }
    _record_info = nil;
    }
    #pragma mark—录音
    ///录音 开始
  • (void)tapClickAction{
    NSLog(@“tapClickAction”);
    if(self.isDetailView){
    [self playNetRecord];
    return;
    }
    if ([self.audioRecorder isRecording]) {
    //停止录音 录音最少大于2秒
    [self record_Stop];
    }else{
    if (self.record_time != 0){
    //有录音
    if ([self.player isPlaying]){
    //停止播放
    [self.player stop];
    self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E66B”, 20)];
    }else{
    //播放录音
    [self playVoiceAction];
    }
    }else{
    NSInteger havePower = [[Support_PowerCheck shareCheckPower] checkIsHavePower_Microphone:^(bool IsAllow) {
    if (IsAllow){
    [self record_Start];
    }
    }];
    if (havePower == PowerStateAllow) {
    [self record_Start];
    }
    }
    }
    }
    -(void)record_Start{
    self.backView_normal.userInteractionEnabled = NO;
    [self setAudioSession:YES];
    #warning 模拟首次使用
    self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E632”, 20)];
    self.placeholder_normal.textColor = rgba(151, 151, 151, 1);
    self.record_time = 0;
    self.placeholder_normal.text = NSIntegerToString(self.record_time);
    [self.audioRecorder record];//首次使用应用时如果调用record方法会询问用户是否允许使用麦克风
    self.timer.fireDate=[NSDate distantPast];
    }
    ///录音 结束
  • (void)record_Stop{
    if(self.isDetailView){
    [self.avPlayer pause];
    return;
    }
    [self.audioRecorder stop];
    self.timer.fireDate = [NSDate distantFuture];
    [self.timer invalidate];
    _timer = nil;
    }
    #pragma mark - 录音机代理方法
    /**
  • 录音完成,录音完成后播放录音

  • @param recorder 录音机对象

  • @param flag 是否成功
    */
    -(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{
    NSLog(@“录音完成!”);

    self.backView_small.hidden = NO;
    self.delete_button.hidden = NO;
    self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E66B”, 20)];
    self.backView_normal.userInteractionEnabled = YES;
    [self.imageView_normal mas_updateConstraints:^(MASConstraintMaker *make) {
    make.right.mas_equalTo(-WMAKENEW(32));
    }];

    self.record_info = [NSMutableDictionary new];
    NSData *ddd = [NSData dataWithContentsOfURL:[self getSavePath]];
    [self.record_info setValue:ddd forKey:@“fileData”];
    [Support_Function getUploadFileName:@“record” fileType:@“.wav”];
    [self.record_info setValue:[Support_Function getUploadFileName:@“record” fileType:@“.wav”] forKey:@“fileName”];
    [self.record_info setValue:self.record_info[@“fileName”] forKey:@“name”];
    }

#pragma mark—已经录音,播放还是停止播放
///播放本地录音
-(void)playVoiceAction{
self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E632”, 20)];
[self setAudioSession:NO];
NSErrorerror;
self.player= [[AVAudioPlayer alloc] initWithContentsOfURL:[self getSavePath] error:&error];
//设置播放循环次数
[self.player setNumberOfLoops:0];
[self.player setVolume:1];//音量,0-1之间
//分配播放所需的资源,并将其加入内部播放队列
[self.player setDelegate:self];
[self.player prepareToPlay];
[self.player play];
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer
)player successfully:(BOOL)flag{
NSLog(@“播放完成”);
self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E66B”, 20)];
}
#pragma mark—回显 以及播放在线音频文件
#pragma mark—回显 以及播放在线音频文件
#pragma mark—回显 以及播放在线音频文件
///播放在线文件
-(void)playNetRecord{
[self setAudioSession:NO];
if (self.avPlayer.timeControlStatus == 2){
[self.avPlayer pause];
self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E66B”, 20)];
}else{
self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E632”, 20)];
[self.avPlayer seekToTime:CMTimeMakeWithSeconds(0, 1.0)];//设置开始播放时间
[self.avPlayer play];
}
}
///设置音频文件路径
-(void)setRecord_net_name:(NSString *)record_net_name{
_record_net_name = record_net_name;
//获取音频时长
NSURL *url= [Support_Special returnImageUrlStr:record_net_name];
NSDictionary *dic = @{AVURLAssetPreferPreciseDurationAndTimingKey:@(YES)};
AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:url options:dic];
CMTime audioDuration = audioAsset.duration;
Float64 audioDurationSeconds = CMTimeGetSeconds(audioDuration);

self.placeholder_normal.text = [NSString stringWithFormat:@"%0.f",audioDurationSeconds];
self.avPlayer=[[AVPlayer alloc] initWithURL:url];
self.avPlayer.volume = 1;

// //监控状态属性,注意AVPlayer也有一个status属性,通过监控它的status也可以获得播放状态
// [self.avPlayer.currentItem addObserver:self forKeyPath:@“status” options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:nil];

//监控播放完成通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished) name:AVPlayerItemDidPlayToEndTimeNotification object:self.avPlayer.currentItem];

}
-(void)playbackFinished{
//监控播放完成通知
NSLog(@“播放完成”);
self.imageView_normal.image = [UIImage iconWithInfo:TBCityIconInfoMakeNoColor(@“\U0000E66B”, 20)];
}
//-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// NSLog(@“监控状态属性”);
// if([keyPath isEqualToString:@“status”]){
// AVPlayerItemStatus status = [change[@“new”] integerValue];
// switch (status) {
// case AVPlayerItemStatusReadyToPlay:
// {
// // 开始播放
// NSLog(@“开始播放”);
// }
// break;
// case AVPlayerItemStatusFailed:
// {
// NSLog(@“加载失败”);
// }
// break;
// case AVPlayerItemStatusUnknown:
// {
// NSLog(@“未知资源”);
// }
// break;
// default:
// break;
// }
// }else if ([keyPath isEqualToString:@“loadedTimeRanges”]){
AVPlayerItem *playerItem = object;
NSArray *array=playerItem.loadedTimeRanges;
//本次缓冲时间范围
CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];
float startSeconds = CMTimeGetSeconds(timeRange.start);
float durationSeconds = CMTimeGetSeconds(timeRange.duration);
//缓冲总长度
NSTimeInterval totalBuffer = startSeconds + durationSeconds;
NSLog(@“共缓冲:%.2f”,totalBuffer);
// }
//}

@end

.h文件

#import

NS_ASSUME_NONNULL_BEGIN

@interface VoiceInputCell : UITableViewCell

///录音 结束

  • (void)record_Stop;
    ///录音信息
    @property (nonatomic,strong) NSMutableDictionary *record_info;
    ///回显时的 录音文件
    @property (nonatomic,strong) NSString *record_net_name;
    ///播放在线文件
    -(void)playNetRecord;

@end

NS_ASSUME_NONNULL_END

你可能感兴趣的:(音视频,ios)