FFmpeg 代码编程录音

项目前准备,我的FFmpeg整个目录是放在和项目文件夹同级

1、在QT项目中集成FFmpeg。

主要是在.pro项目文件中把FFmpeg的include路径和lib库的路径添加就可以了。代码如下:

win32 {
    FFMPEG_HOME = ../ffmpeg-4.2.1-win32-dev
}

INCLUDEPATH += $${FFMPEG_HOME}/include
LIBS += -L$${FFMPEG_HOME}/lib \
        -lavdevice \
        -lavformat \
        -lavutil

2、在MainWindow中拖入一个按钮,并转为槽

(其实就是相当于其他开发的监听按钮的点击事件)


//录音按钮
/*
 * 命令行录音:ffmpeg -f dshow -i audio="设备名" out.wav
 * 修改录音参数:ffmpeg -f dshow -sample_rate 15000 -sample_size 16 -channels 2 -i audio="设备名" out.wav
*/

/*
代码录音的逻辑
1、注册设备
2、获取输入格式对象
3、打开设备
4、采集数据
5、释放资源
*/
void MainWindow::on_recorButton_clicked()
{
    //点击了 开始录音
    if(!_recordThread){
        //创建并启动线程
        _recordThread = new RecordThread(this);
        _recordThread->start();
        //监听线程异常退出的情况
        connect(_recordThread,&RecordThread::finished,
                [this](){
            _recordThread = nullptr;
            //修改按钮文字
            ui->recorButton->setText("开始录音");
        });
        //修改按钮文字
        ui->recorButton->setText("停止录音");
    }else{
        //主动请求提前完成
        _recordThread->requestInterruption();
        _recordThread = nullptr;
        //修改按钮文字
        ui->recorButton->setText("开始录音");
    }


}

3、因为录音是不断地读取数据,耗时操作,所以开了一个子线程在线程的run函数中去录音

#include "recordthread.h"


#include <QDebug>
#include <QFile>
#include <QDateTime>

extern "C" {
    //设备相关API
    #include <libavdevice/avdevice.h>
    //格式相关API
    #include <libavformat/avformat.h>
    //工具相关API
    #include <libavutil/avutil.h>
}


//宏定义
//输入格式名
#define FMT_NAME "dshow"
//设备名
#define DEVICE_NAME "audio=麦克风阵列 (适用于数字麦克风的英特尔® 智音技术)"
//
#define FILE_PATH "C:/Users/love/Desktop/QTWork/09_recordAudio_sdl_playPCM/"


//构造函数
RecordThread::RecordThread(QObject *parent) : QThread(parent)
{
    //监听线程执行完成后调用函数回收内存
    connect(this, &RecordThread::finished, this, &RecordThread::deleteLater);
}

//析构函数
RecordThread::~RecordThread(){
    //断开所有监听
    disconnect();
    //主动请求提前完成
    requestInterruption();
    quit();
    wait();

    qDebug() << this << "录音线程析构函数------";
}


/*
 * 命令行录音:ffmpeg -f dshow -i audio="设备名" out.wav
 * 修改录音参数:ffmpeg -f dshow -sample_rate 15000 -sample_size 16 -channels 2 -i audio="设备名" out.wav
*/

/*
代码录音的逻辑
1、注册设备
2、获取输入格式对象
3、打开设备
4、采集数据
5、释放资源
*/

//线程启动会自动调用内部的run函数
void RecordThread::run(){
    qDebug() << this << "录音线程开始";

    //1、注册设备 (只需要注册一次 所以在main函数里注册就好了)
    //2、获取输入格式对象
    AVInputFormat *fmt = av_find_input_format(FMT_NAME);
    if(!fmt){
        qDebug() << this << "av_find_input_format error" << fmt;
    }

    //3、打开设备
    //上下文 操作设备
    AVFormatContext *ctx = nullptr;
    //url 设备名
    //const char* deviceName = "";
    //选项
    //AVDictionary *options;

    int ret = avformat_open_input(&ctx,DEVICE_NAME, fmt, nullptr);
    if(ret){//0 表示成功。 非0即真
        char errbuff[1024];
        av_strerror(ret,errbuff,sizeof(errbuff));
        qDebug() << this << "avformat_open_input error" << errbuff;
        return;
    }

    //4、采集数据

    //拼接文件名
    QString fileName = FILE_PATH;
    fileName += QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
    fileName += ".pcm";
    QFile file(fileName);
    //打开文件 WriteOnly这个模式打开文件,如果文件不存在就创建文件并打开,如果文件存在就清空
    bool fopen = file.open(QIODevice::WriteOnly);
    if(!fopen){
        //打开文件失败 需要关闭设备 否则内存泄漏
        avformat_close_input(&ctx);
        qDebug() << this << "file.open error" << fileName;
        return;
    }

    //数据包
    AVPacket pkt;
    //不断地读取数据
    while (!isInterruptionRequested()) {
        ret = av_read_frame(ctx,&pkt);
        if(ret == 0){
            //读取成功 把数据写入文件
            file.write((char *)pkt.data,pkt.size);
        }else{
            //关闭文件
            file.close();
            //关闭设备
            avformat_close_input(&ctx);
            break;
        }
    }


    //5、释放资源
    //关闭文件
    file.close();
    //关闭设备
    avformat_close_input(&ctx);

    qDebug() << this << "录音线程正常退出";

}








  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值