文章结束后实现:
- 用户点击 录音按钮 录制声音
- 松开 录音按钮 的时候,音频文件转换为 mp3 格式上传到服务器
- 点击 播发按钮 播放之前录制的声音文件
需要的类
1: 导入 AVFoundation 框架,使用:
- AVAudioRecorder, 声音录制
- AVAudioPlayer, 声音播放
2: 需要 lame 进行声音转化
plist 配置
允许使用麦克风
屏幕快照 2017-07-19 下午5.10.08.png代码
示例代码:
import UIKit
import AVFoundation
class ViewController: UIViewController {
private var session: AVAudioSession!
private var recorder: AVAudioRecorder!
private var player: AVAudioPlayer!
private var pcmPath: String!
private var mp3FilePath: String!
private var recorderSetting: [String: AnyObject]!
private var mp3FileURL: URL!
private let avSampleRateKey = 44100
override func viewDidLoad() {
super.viewDidLoad()
session = AVAudioSession.sharedInstance()
try! session.setActive(true)
let docDic = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
pcmPath = docDic + "/play.pcm"
mp3FilePath = docDic + "/play.mp3"
mp3FileURL = URL(fileURLWithPath: mp3FilePath)
recorderSetting =
[
AVFormatIDKey: NSNumber(value: kAudioFormatLinearPCM),
AVNumberOfChannelsKey: 2 as AnyObject, //录音的声道数,立体声为双声道
AVEncoderAudioQualityKey : AVAudioQuality.max.rawValue as AnyObject,
AVEncoderBitRateKey : 640000 as AnyObject,
AVSampleRateKey : avSampleRateKey as AnyObject //录音器每秒采集的录音样本数
]
}
@IBAction func touchDown() {
do {
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
recorder = try AVAudioRecorder(url: URL(string: pcmPath)!, settings: recorderSetting)
recorder.isMeteringEnabled = true
recorder.record()
} catch let error {
print("create recorder error: \(error)")
}
}
@IBAction func touchUp() {
recorder.stop()
DispatchQueue.global().async {
let success = AudioTransform.transformToMp3(fromPath: self.pcmPath,
toMp3Path: self.mp3FilePath,
withAVSampleRateKey: Int32(self.avSampleRateKey))
DispatchQueue.main.async {
print("transform success")
if success {
do {
let data = try Data(contentsOf: self.mp3FileURL!)
print("data: \(data)")
DemoModel.uploadRecord(data: data) { (success, info) in
}
} catch let error {
print("upload audio error: \(error)")
}
}
}
}
}
@IBAction func play() {
do {
try session.setCategory(AVAudioSessionCategoryPlayback)
player = try AVAudioPlayer(contentsOf: recorder.url)
player.play()
} catch let error {
print("paly audio error: \(error)")
}
}
}
注意需要为 录制按钮 实现:
- touchDown 事件(按住按钮触发)
- touchUpInside 事件(松开按钮触发)
转化为 mp3 代码:
#import "lame.h"
@implementation AudioTransform
+ (BOOL)transformToMp3FromPath:(NSString *)originalPath
toMp3Path:(NSString *)mp3Path
withAVSampleRateKey:(int)rateKey {
@try {
int read, write;
FILE *pcm = fopen([originalPath cStringUsingEncoding:1], "rb"); //source
fseek(pcm, 4*1024, SEEK_CUR); //skip file header
FILE *mp3 = fopen([mp3Path cStringUsingEncoding:1], "wb"); //output
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, rateKey);
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]);
return false;
}
@finally {
return true;
}
}
@end
注意:需要使用 lame 这个小插件实现转化,lame下载地址。你也可以直接使用Demo内的 fat-lame 里面是已经编译好的文件 (转化文件是用 Objective-C 写的,在 Swift 项目中需要一个bridge 文件)
屏幕快照 2017-07-19 下午5.33.17.png录制完声音后,如果播放的时候发现 声音变小
在播放声音的方法内设置:
try! session.setCategory(AVAudioSessionCategoryPlayback)
录制声音的方法内设置:
try! session.setCategory(AVAudioSessionCategoryPlayAndRecord)
参考链接:
音频的文件格式和数据格式
网友评论