美文网首页
iOS 录制音频文件,播放,转化成mp3上传

iOS 录制音频文件,播放,转化成mp3上传

作者: 阿朱先生 | 来源:发表于2017-07-19 16:47 被阅读0次
    文章结束后实现:
    • 用户点击 录音按钮 录制声音
    • 松开 录音按钮 的时候,音频文件转换为 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)
    
    

    Demo 地址

    参考链接:
    音频的文件格式和数据格式

    相关文章

      网友评论

          本文标题:iOS 录制音频文件,播放,转化成mp3上传

          本文链接:https://www.haomeiwen.com/subject/renlkxtx.html