美文网首页
2. 【音频采集实战】

2. 【音频采集实战】

作者: 东也_ | 来源:发表于2022-04-21 12:10 被阅读0次

    每个端音频采集的底层和应用层的库是不一样的,所以使用ffmpeg中间层能够实现跨平台开发;

    • Android端的底层库是AudioRecorder,应用层是MediaRecorder;
    • iOS端的底层库是AudioUnit,应用层是AVFoundation;
    • Windows端的常用的是Directshow OpenAL 还有Windows7之上的AudioCore;

    使用ffmpeg有两种采集方式:

    1. 使用命令方式,命令详情查看ffmpeg相关指令的那篇
    2. 使用代码调用api的方式
    • 在mac下的动态库需要对动态库进行签名

    获取本地签名证书列表:/usr/bin/security find-identity -v -p codesigning
    查看动态库是否签名: codesign -d -vv 动态库文件
    签名命令:codesign -fs "iPhone Distribution: 你的签名证书." 动态库文件
    xcode环境:13.2.1
    签名了如果还是报错,关掉沙盒并且设置 Enable Hardened Runtime 为NO
    在项目中设置user header search path的时候,要使用全路径方式,我使用$(PROJECT_NAME)方式,有的头文件在链接的时候会报错;

    采集音频的步骤:

    1. 打开输入输出设备,涉及的包是avdevice avformat
      1. 注册设备
      2. 设置采集方式,根据平台选择,即设置输入
      3. 打开音频设备
    2. 获取数据包 包:avcodec
      1. 主要使用av_read_frame方法获取数据
      2. 将数据放入packet中
      3. 在读取的时候注意缓冲区无未准备好的情况
    3. 将数据输出到文件
      1. 创建文件--- fopen
      2. 将数据写入文件-- fwrite
      3. 关闭文件 -- fclose
    • 打开设备 ·
    void startRecorder(void) {
        // 上下文
        AVFormatContext *av_context = NULL;
        AVDictionary *options = NULL;
        // 1. 注册设备
        avdevice_register_all();
        
        // 2. 设置采集方式
        //设置采集方式 mac os 下是AVfoundation Windows下是dshow  linux 下是alsa
        AVInputFormat *format = av_find_input_format("avfoundation");
        
        // 3. 打开设备
        //里面的识别格式为[[video device]:[audio device]]  这里写0 是获取第1个音频设备
        char *name = ":0";
    
        // url 是路径 可以是网络路径也可以是本地路径 本地路径mac下的格式是 video : audio 这里表示获取第一个音频设备
        int result = avformat_open_input(&av_context, name, format, &options);
        
        if (result != 0) {
            
            char errors[1024];
            // 根据返回值生成错误信息
            av_make_error_string(errors, 1024, result);
            printf("打开设备失败:%s\n", errors);
            return;
        }
        
        printf("打开设备成功!\n");
        
    
        get_audio_packet(av_context,&packet_callback);
        
        // 关闭输入 上下文
        avformat_close_input(&av_context);
        
    }
    
    • 读取数据和存储到文件
    void get_audio_packet(AVFormatContext *context, void (*packet_callback)(AVPacket)) {
        
        // w == 写  b == 二进制  + == 没有就创建文件
        FILE *f = fopen("/Users/cunw/Desktop/learning/音视频学习/音视频文件/code_recorder.pcm", "wb+");
        
        
        AVPacket *packet = av_packet_alloc();
        int result = -1;
        // 循环读取设备信息
        // result == -35 是Resource temporarily unavailable 因为获取太频繁 设备未准备好,还正在处理数据  
      // 因为输入设备准备好需要时间  睡一秒后再读取  
         sleep(1.0);
        while ((result = av_read_frame(·context, packet)) == 0  || result == -35) {
         
            if (packet->size > 0) {
                packet_callback(*packet);
                fwrite(packet->data, packet->size, 1, f);
                // 每读取一次 就清空数据包 不然数据包会一直增大
                av_packet_unref(packet);
              
            }
        }
        
        if (result != 0) {
            char errors[1024];
            av_make_error_string(errors, 1024, result);
            
            printf("get packet occured error is \"%s\" \n", errors);
        }
        
        // 将缓冲区剩余的数据 强制写入文件
        fflush(f);
        fclose(f);
        
        // 释放packet空间
        av_packet_free(&packet);
        
    }
    // 回调函数
    void packet_callback(AVPacket packet) {
        
        printf("packet size is %d\n",packet.size);
    
    }
    
    • 播放

      ffplay 播放pcm数据: ffplay -ar(采样率) 44100 -ac(通道数) 2 -f(采样大小)f32le 文件名

    上一篇::音频基础知识
    下一篇:音频编码原理

    相关文章

      网友评论

          本文标题:2. 【音频采集实战】

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