ffmpeg实现屏幕录制、摄像头录制、录音和RTMP推流

本文档介绍了使用ffmpeg框架进行屏幕录制、音频录制、摄像头采集和RTMP推流的项目,适合新手学习。项目采用QT+VS2017进行开发,并提供了关键代码段,包括音频输入设备和摄像头设备的获取,ffmpeg的初始化及音视频流的设置。项目源码链接可从提供的百度网盘获取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.项目介绍

本项目适用于新手对ffmpeg框架学习的项目,此项目包括功能,屏幕录制、音频录制、摄像头采集录制、音视频通过RTMP推流。

二、开发环境

QT+vs2017+ffmpeg

三、主要代码介绍

      1.使用QT获取音频输入设备代码

QStringList CUtilDevice::get_input_audio_devices()
{
    //获取输入音频设备名称
    QList<QAudioDeviceInfo> audioDeviceListI = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    QStringList ret;

    for(int i = 0; i < audioDeviceListI.size(); i++)
    {
        QString device_name = audioDeviceListI.at(i).deviceName();
        bool is_repeat = false;
        for(int j = 0; j < ret.size(); j++)
        {
            if(ret.at(j) == device_name)
            {
                is_repeat = true;
            }
        }

        if(!is_repeat)
        {
            ret.append(device_name);
        }
    }

    return ret;
}

      2.使用QT获取摄像头设备代码

QStringList ret;
    QList<QCameraInfo> device_list = QCameraInfo::availableCameras();

    for(int i = 0; i < device_list.size(); i++)
    {
        QString device_name = device_list.at(i).description();
        bool is_repeat = false;
        for(int j = 0; j < ret.size(); j++)
        {
            if(ret.at(j) == device_name)
            {
                is_repeat = true;
            }
        }

        if(!is_repeat)
        {
            ret.append(device_name);
        }
    }

    return ret;

       3.ffmpeg初始化

avcodec_register_all();
av_register_all();
avdevice_register_all();

        4.ffmpeg音视频输入流设置

if(m_video_device.isEmpty()& m_audio_device.isEmpty())
    {
        qDebug("you have not set any capture device \n");
        return false;
    }

    int i;

    //打开Directshow设备前需要调用FFmpeg的avdevice_register_all函数,否则下面返回失败
    m_pInputFormat_d = av_find_input_format("dshow"); //这个主要用于摄像头和音频设备的输入
    m_pInputFormat = av_find_input_format("gdigrab");//这个主要用于屏幕获取的
    if(nullptr == m_pInputFormat)
    {
        qDebug()<<"find video input fail.";
    }

    // Set device params
    AVDictionary *device_param = 0;
    //if not setting rtbufsize, error messages will be shown in cmd, but you can still watch or record the stream correctly in most time
    //setting rtbufsize will erase those error messages, however, larger rtbufsize will bring latency
    //av_dict_set(&device_param, "rtbufsize", "10M", 0);

    if(!m_video_device.isEmpty())
    {
        int res = 0;
        if(m_is_use_camera)//如果是摄像头录制
        {
            QString device_name = "video=" + m_video_device;
            //Set own video device's name
            if ((res = avformat_open_input(&m_pVidFmtCtx, device_name.toStdString().c_str(), m_pInputFormat_d, &device_param)) != 0)
            {
                qDebug("Couldn't open input video stream.(无法打开输入流)\n");
                return false;
            }
        }
        else//如果是屏幕录制
        {
            av_dict_set(&device_param,"framerate","5",0);
            QString device_name = "desktop";
            qDebug()<<"device_name: "<<device_name;
            if ((res = avformat_open_input(&m_pVidFmtCtx, device_name.toStdString().c_str(), m_pInputFormat, &device_param)) != 0)
            {
                qDebug("Couldn't open input video stream.(无法打开输入流)\n");
                return false;
            }
        }

        //input video initialize
        AVDictionary *param = NULL;
        if (avformat_find_stream_info(m_pVidFmtCtx, &param) < 0)
        {
            qDebug("Couldn't find video stream information.(无法获取流信息)\n");
            return false;
        }
        m_videoindex = -1;
        for (i = 0; i < m_pVidFmtCtx->nb_streams; i++)
        {
            if (m_pVidFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
            {
                m_videoindex = i;
                break;
            }
        }

        if (m_videoindex == -1)
        {
            qDebug("Couldn't find a video stream.(没有找到视频流)\n");
            return false;
        }
        //编码器
        //if (avcodec_open2(encodec_ctx, encodec, &param) < 0)
        if (avcodec_open2(m_pVidFmtCtx->streams[m_videoindex]->codec, avcodec_find_decoder(m_pVidFmtCtx->streams[m_videoindex]->codec->codec_id),NULL) < 0)
        {

            qDebug("Could not open video codec.(无法打开解码器)\n");
            return false;
        }

    }

    //
    if(!m_audio_device.isEmpty())
    {
        AVDictionary *device_param_a = 0;
        QString device_name = "audio=" + m_audio_device;

        //Set own audio device's name
        if (avformat_open_input(&m_pAudFmtCtx, device_name.toStdString().c_str(), m_pInputFormat_d, &device_param_a) != 0){

            qDebug("Couldn't open input audio stream.(无法打开输入流)\n");
            return false;
        }

        //input audio initialize
        if (avformat_find_stream_info(m_pAudFmtCtx, NULL) < 0)
        {
            qDebug("Couldn't find audio stream information.(无法获取流信息)\n");
            return false;
        }
        m_audioindex = -1;
        for (i = 0; i < m_pAudFmtCtx->nb_streams; i++)
        {
            if (m_pAudFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
            {
                m_audioindex = i;
                break;
            }
        }
        if (m_audioindex == -1)
        {
            qDebug("Couldn't find a audio stream.(没有找到音频流)\n");
            return false;
        }
        if (avcodec_open2(m_pAudFmtCtx->streams[m_audioindex]->codec, avcodec_find_decoder(m_pAudFmtCtx->streams[m_audioindex]->codec->codec_id), NULL) < 0)
        {
            qDebug("Could not open audio codec.(无法打开解码器)\n");
            return false;
        }
    }

    return true;

         5.ffmpeg音视频输出流设置代码

 m_output_path = out_path;

    //output initialize
    avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_path);
    //rtmp 直播使用
    //avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_pa
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值