郁闷 音频录制 哪里出了问题 文件有 就是不对
音频播放没问题
经过 再三深挖之后发现
音屏录制 没有问题
音频播放也没有问题
问题出现在 公司需求 边播放边录制
用的是第三方播放器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
网友评论