4-15 做1个播放视屏 同时录制音频的功能

2020-04-15  本文已影响0人  大也

郁闷 音频录制 哪里出了问题 文件有 就是不对

音频播放没问题

经过 再三深挖之后发现
音屏录制 没有问题
音频播放也没有问题
问题出现在 公司需求 边播放边录制
用的是第三方播放器ZFplayer
边录边播
所以修改了 ZFPlayer的底层文件
边录边播 会导致使用了听筒播放 然后占用了[AVAudioSession sharedInstance]是单例
原来录音的时候
[[AVAudioSession sharedInstance]setCategory: AVAudioSessionCategoryPlayAndRecord
error: &error];
设置category是AVAudioSessionCategoryPlayAndRecord
但是播放视频的时候
[[AVAudioSession sharedInstance]setCategory: AVAudioSessionCategoryPlayback
error: &error];
设置category为AVAudioSessionCategoryPlayback

导致边录边播 无法实现 只好修改 ZFPlayer 底层[AVAudioSession sharedInstance]setCategory 代码测试成功

最后找到方法

//边录边播   会导致使用了听筒播放  按照官方文档的说法通过重写audio route属性来重定向音频。
1.[[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
2.[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];//1-2两句效果相等

[[AVAudioSession sharedInstance]setActive:YES error:nil];//马上设置
[[AVAudioSession sharedInstance]setActive:NO error:nil];//交出音频会话

相比于播放器 ZFPlayer 其实已经很完善了
下面 附上完整可用的 音频录制播放 代码

//
//  VideoManager.h
//  House
//
//  Created by FMNet on 2020/4/15.
//  Copyright © 2020 fengwenxiao. All rights reserved.
//

#import <Foundation/Foundation.h>

#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface AudioManager : NSObject

+ (instancetype)sharedvideoManager ;

@property (nonatomic, strong) AVAudioRecorder* __nullable avAudioRecorder;
@property (nonatomic, strong) AVAudioPlayer* __nullable avAudioPlayer;

- (void)configRecording ;

- (void)startRecording ;

- (void)playRecording;

- (void)stopRecording;

- (void)continueRecording;

- (void)pauseRecording;

@end

NS_ASSUME_NONNULL_END
//
//  VideoManager.m
//  House
//
//  Created by FMNet on 2020/4/15.
//  Copyright © 2020 fengwenxiao. All rights reserved.
//

#import "AudioManager.h"

#define DOCUMENT_PATH                   [NSSearchPathForDirectoriesInDomains(   \
NSDocumentDirectory, NSUserDomainMask, \
YES) objectAtIndex: 0]
#define AUDIO_FOLDER_NAME               @"audios"
#define AUDIO_FOLDER_PATH               [DOCUMENT_PATH stringByAppendingPathComponent:  \
AUDIO_FOLDER_NAME]

@interface AudioManager (){
    NSString* _curWavFilePath;
    NSString* _curAmrFilePath;

    NSURL* _curWavFileUrl;

}

@property (nonatomic, strong) AVAudioSession* audioSession;

@end

@implementation AudioManager


+ (instancetype)sharedvideoManager {
    static AudioManager *videoManager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!videoManager) {
            videoManager = [[self alloc] init];
        }
    });
    return videoManager;
}

- (void)configRecording {
    AVAudioSession* audioSession = [AVAudioSession sharedInstance];
    NSError* error;
    
    [audioSession setCategory: AVAudioSessionCategoryPlayAndRecord
                        error: &error];
    
    [[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
    
    if (audioSession == nil) {
        UIAlertController* alertController = [UIAlertController
                                              alertControllerWithTitle: @"Error"
                                              message: error.description
                                              preferredStyle: UIAlertControllerStyleAlert];
        
        UIAlertAction* okAction = [UIAlertAction actionWithTitle: @"确定"
                                                           style: UIAlertActionStyleDefault
                                                         handler: nil];
        
        [alertController addAction: okAction];
        
        [[AudioManager currentViewController] presentViewController: alertController animated: YES
                         completion: nil];
        
        return ;
    }
    
    [audioSession setActive: YES
                      error: nil];
    
    self.audioSession = audioSession;
    
    NSDate* nowDate = [NSDate date];
    
    _curWavFilePath = [self generateAudioFilePathWithDate: nowDate
                                                   andExt: @"wav"];
    _curAmrFilePath = [self generateAudioFilePathWithDate: nowDate
                                                   andExt: @"amr"];
    
    _curWavFileUrl = [NSURL fileURLWithPath: _curWavFilePath];
    
    NSDictionary* recordSettings = @{
             AVSampleRateKey: @8000.0f,                         // 采样率
             AVFormatIDKey: @(kAudioFormatLinearPCM),           // 音频格式
             AVLinearPCMBitDepthKey: @16,                       // 采样位数
             AVNumberOfChannelsKey: @1,                         // 音频通道
             AVEncoderAudioQualityKey: @(AVAudioQualityHigh)    // 录音质量
             };
    
    _avAudioRecorder = [[AVAudioRecorder alloc] initWithURL: _curWavFileUrl
                                                   settings: recordSettings
                                                      error: nil];
    
    if (!_avAudioRecorder) {
        UIAlertController* alertController = [UIAlertController
                                              alertControllerWithTitle: @"Error"
                                              message: @"Error init AVAudioRecorder"
                                              preferredStyle: UIAlertControllerStyleAlert];
        
        UIAlertAction* okAction = [UIAlertAction actionWithTitle: @"OK"
                                                           style: UIAlertActionStyleDefault
                                                         handler: nil];
        
        [alertController addAction: okAction];
        
        [[AudioManager currentViewController] presentViewController: alertController
                           animated: YES
                         completion: nil];
        
        return ;
    }
    
    _avAudioRecorder.meteringEnabled = YES;
    [_avAudioRecorder prepareToRecord];

}

- (void)startRecording {
    [self configRecording];
    [_avAudioRecorder record];
}







/**
 *  播放音频
 */
-(void)playRecording{
    if ([_avAudioRecorder isRecording])
        return ;
    
    if ([[NSFileManager defaultManager] fileExistsAtPath: _curWavFilePath]) {
        _avAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:
                          [NSURL fileURLWithPath: _curWavFilePath]
                                                                error: nil];
        
        [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback
                                               error: nil];
        
        [_avAudioPlayer play];
    }

}

- (void)stopRecording {
    if ([_avAudioRecorder isRecording]) {
        [_avAudioRecorder stop];
    }
    
    NSLog(@"文件大小为 %liKb",
         [self getFileSizeWithFilePath: _curWavFilePath]);
    
    // 可以在这里转换为amr文件
}

- (void)continueRecording {
    [_avAudioRecorder record];
}

- (void)pauseRecording {
    if ([_avAudioRecorder isRecording]) {
        [_avAudioRecorder pause];
    }
}


- (NSString*)generateAudioFilePathWithDate: (NSDate*)date
                                    andExt: (NSString*)ext {
    NSInteger timeStamp = [[NSNumber numberWithDouble:
                            [date timeIntervalSince1970]] integerValue];
    
    return [NSString stringWithFormat: @"%@/%li.%@", AUDIO_FOLDER_PATH,
            timeStamp, ext];
}

- (NSInteger)getFileSizeWithFilePath: (NSString*)filePath {
    if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]) {
        long long fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath: filePath
                                                                error: nil].fileSize;
        
        return fileSize / 1024.0f;
        
    }
    
    return 0.0f;
}


  + (UIViewController*)currentViewController{

      UIViewController* vc = [UIApplication sharedApplication].keyWindow.rootViewController;

      while (1) {
          if ([vc isKindOfClass:[UITabBarController class]]) {
              vc = ((UITabBarController*)vc).selectedViewController;
          }
          if ([vc isKindOfClass:[UINavigationController class]]) {
              vc = ((UINavigationController*)vc).visibleViewController;
          }
          if (vc.presentedViewController) {
              vc = vc.presentedViewController;
          }else{
              break;
          }
      }
      return vc;
}
@end
上一篇 下一篇

猜你喜欢

热点阅读