当前位置: 首页 > news >正文

FFmpeg录制屏幕和音频

一、FFmpeg命令行实现录制屏幕和音频

1、Windows 示例

#include <cstdlib>
#include <string>
#include <iostream>

int main() {
    // FFmpeg 命令行(录制屏幕 + 麦克风音频)
    std::string command = 
        "ffmpeg -f gdigrab -framerate 30 -i desktop "          // 屏幕捕获(GDI)
        "-f dshow -i audio=\"麦克风 (Realtek Audio)\" "       // 音频设备(需替换为你的设备名)
        "-c:v libx264 -preset ultrafast -crf 18 "             // 视频编码(H.264)
        "-c:a aac -b:a 192k "                                 // 音频编码(AAC)
        "-pix_fmt yuv420p "                                   // 兼容性格式
        "output.mp4";                                         // 输出文件

    std::cout << "开始录制(按 Ctrl+C 停止)..." << std::endl;
    int ret = system(command.c_str());

    if (ret == 0) {
        std::cout << "录制完成!保存为 output.mp4" << std::endl;
    } else {
        std::cerr << "录制失败!错误码: " << ret << std::endl;
    }

    return 0;
}

仅仅录制视频:

ffmpeg -f gdigrab -framerate 30 -i desktop -vcodec libx264 -pix_fmt yuv420p output.mp4

2、Linux 示例

std::string command =
    "ffmpeg -f x11grab -framerate 30 -video_size 1920x1080 -i :0.0 "  // X11 屏幕捕获
    "-f alsa -i default "                                              // ALSA 音频输入
    "-c:v libx264 -preset ultrafast -crf 18 "
    "-c:a aac -b:a 192k "
    "output.mp4";

 3、macOS 示例

std::string command =
    "ffmpeg -f avfoundation -framerate 30 -i \"1:0\" "        // 屏幕+音频捕获
    "-c:v libx264 -preset ultrafast -crf 18 "
    "-c:a aac -b:a 192k "
    "output.mp4";

关键参数说明

参数说明
-f gdigrabWindows 屏幕捕获驱动
-f x11grabLinux 屏幕捕获驱动
-f avfoundationmacOS 屏幕/音频捕获驱动
-i desktop捕获整个屏幕(Windows)
-i :0.0Linux 主显示器(X11)
-f dshow -i audio="..."Windows 音频设备名(通过 ffmpeg -list_devices true -f dshow -i dummy 查询)
-f alsa -i defaultLinux 默认音频输入
-c:v libx264H.264 视频编码
-preset ultrafast编码速度优化(牺牲压缩率)
-crf 18视频质量(18~28,值越小质量越高)
-c:a aacAAC 音频编码
-b:a 192k音频比特率(192kbps)

4、高级功能

1)录制特定窗口(Windows)

// 替换 -i desktop 为窗口标题(模糊匹配)
std::string command = "ffmpeg -f gdigrab -framerate 30 -i title=\"Chrome\" output.mp4";

2)硬件加速(NVIDIA/Intel)

// NVIDIA NVENC
std::string command = "ffmpeg -f gdigrab -framerate 30 -i desktop -c:v h264_nvenc -preset p7 -tune hq output.mp4";

// Intel QuickSync
std::string command = "ffmpeg -f gdigrab -framerate 30 -i desktop -c:v h264_qsv -preset faster output.mp4";

 3)仅录制音频

// Windows
std::string command = "ffmpeg -f dshow -i audio=\"麦克风 (Realtek Audio)\" -c:a aac audio.m4a";

// Linux
std::string command = "ffmpeg -f alsa -i default -c:a aac audio.m4a";

4)设备名称:Windows 需通过 ffmpeg -list_devices true -f dshow -i dummy 查询正确的音频设备名。
5)权限问题:Linux/macOS 可能需要 sudo 或音频组权限。
6)性能优化:高分辨率录制建议使用硬件加速(如 h264_nvenc)。

二、FFmpeg库实现录制屏幕和音频

1、 初始化 FFmpeg

#include <iostream>
#include <string>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
}

int main() {
    // 初始化 FFmpeg
    avdevice_register_all(); // 注册设备输入(屏幕、麦克风等)
    avformat_network_init();

    // ... 后续代码
    return 0;
}

2、捕获屏幕(Windows 使用 gdigrab

AVFormatContext* screenFormatCtx = nullptr;
AVDictionary* screenOptions = nullptr;

// 设置屏幕捕获参数(Windows GDI)
av_dict_set(&screenOptions, "framerate", "30", 0);      // 帧率
av_dict_set(&screenOptions, "offset_x", "0", 0);        // 起始 X 坐标
av_dict_set(&screenOptions, "offset_y", "0", 0);        // 起始 Y 坐标
av_dict_set(&screenOptions, "video_size", "1920x1080", 0); // 分辨率

// 打开屏幕输入流
if (avformat_open_input(&screenFormatCtx, "desktop", av_find_input_format("gdigrab"), &screenOptions) < 0) {
    std::cerr << "无法打开屏幕输入!" << std::endl;
    return -1;
}

// 查找视频流
if (avformat_find_stream_info(screenFormatCtx, nullptr) < 0) {
    std::cerr << "无法获取屏幕流信息!" << std::endl;
    return -1;
}

3、捕获音频(Windows 使用 dshow

AVFormatContext* audioFormatCtx = nullptr;
AVDictionary* audioOptions = nullptr;

// 设置音频设备(需替换为你的设备名)
av_dict_set(&audioOptions, "sample_rate", "44100", 0);  // 采样率
av_dict_set(&audioOptions, "channels", "2", 0);         // 声道数

// 打开音频输入流
if (avformat_open_input(&audioFormatCtx, "audio=麦克风 (Realtek Audio)", av_find_input_format("dshow"), &audioOptions) < 0) {
    std::cerr << "无法打开音频输入!" << std::endl;
    return -1;
}

// 查找音频流
if (avformat_find_stream_info(audioFormatCtx, nullptr) < 0) {
    std::cerr << "无法获取音频流信息!" << std::endl;
    return -1;
}

 4、创建输出文件(MP4 封装)

AVFormatContext* outputFormatCtx = nullptr;
avformat_alloc_output_context2(&outputFormatCtx, nullptr, nullptr, "output.mp4");

// 添加视频流(H.264)
AVStream* videoStream = avformat_new_stream(outputFormatCtx, nullptr);
AVCodecParameters* videoCodecParams = videoStream->codecpar;
videoCodecParams->codec_id = AV_CODEC_ID_H264;
videoCodecParams->codec_type = AVMEDIA_TYPE_VIDEO;
videoCodecParams->width = 1920;
videoCodecParams->height = 1080;
videoCodecParams->format = AV_PIX_FMT_YUV420P;

// 添加音频流(AAC)
AVStream* audioStream = avformat_new_stream(outputFormatCtx, nullptr);
AVCodecParameters* audioCodecParams = audioStream->codecpar;
audioCodecParams->codec_id = AV_CODEC_ID_AAC;
audioCodecParams->codec_type = AVMEDIA_TYPE_AUDIO;
audioCodecParams->sample_rate = 44100;
audioCodecParams->channels = 2;
audioCodecParams->channel_layout = AV_CH_LAYOUT_STEREO;

// 打开输出文件
if (avio_open(&outputFormatCtx->pb, "output.mp4", AVIO_FLAG_WRITE) < 0) {
    std::cerr << "无法打开输出文件!" << std::endl;
    return -1;
}

// 写入文件头
if (avformat_write_header(outputFormatCtx, nullptr) < 0) {
    std::cerr << "无法写入文件头!" << std::endl;
    return -1;
}

5、循环读取音视频帧并写入文件

AVPacket packet;
while (true) {
    // 读取视频帧
    if (av_read_frame(screenFormatCtx, &packet) >= 0) {
        av_packet_rescale_ts(&packet, screenFormatCtx->streams[packet.stream_index]->time_base, videoStream->time_base);
        packet.stream_index = videoStream->index;
        av_interleaved_write_frame(outputFormatCtx, &packet);
        av_packet_unref(&packet);
    }

    // 读取音频帧
    if (av_read_frame(audioFormatCtx, &packet) >= 0) {
        av_packet_rescale_ts(&packet, audioFormatCtx->streams[packet.stream_index]->time_base, audioStream->time_base);
        packet.stream_index = audioStream->index;
        av_interleaved_write_frame(outputFormatCtx, &packet);
        av_packet_unref(&packet);
    }

    // 按 Ctrl+C 停止录制
    if (GetAsyncKeyState(VK_ESCAPE) {
        break;
    }
}

// 写入文件尾
av_write_trailer(outputFormatCtx);

6、释放资源

avformat_close_input(&screenFormatCtx);
avformat_close_input(&audioFormatCtx);
avio_closep(&outputFormatCtx->pb);
avformat_free_context(outputFormatCtx);

7、示例代码(window)

#include <iostream>
#include <Windows.h>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
}

int main() {
    // 初始化 FFmpeg
    avdevice_register_all();
    avformat_network_init();

    // 1. 打开屏幕输入
    AVFormatContext* screenFormatCtx = nullptr;
    AVDictionary* screenOptions = nullptr;
    av_dict_set(&screenOptions, "framerate", "30", 0);
    av_dict_set(&screenOptions, "video_size", "1920x1080", 0);

    if (avformat_open_input(&screenFormatCtx, "desktop", av_find_input_format("gdigrab"), &screenOptions) < 0) {
        std::cerr << "无法打开屏幕输入!" << std::endl;
        return -1;
    }

    // 2. 打开音频输入
    AVFormatContext* audioFormatCtx = nullptr;
    AVDictionary* audioOptions = nullptr;
    av_dict_set(&audioOptions, "sample_rate", "44100", 0);
    av_dict_set(&audioOptions, "channels", "2", 0);

    if (avformat_open_input(&audioFormatCtx, "audio=麦克风 (Realtek Audio)", av_find_input_format("dshow"), &audioOptions) < 0) {
        std::cerr << "无法打开音频输入!" << std::endl;
        return -1;
    }

    // 3. 创建输出文件
    AVFormatContext* outputFormatCtx = nullptr;
    avformat_alloc_output_context2(&outputFormatCtx, nullptr, nullptr, "output.mp4");

    // 4. 写入音视频流
    AVStream* videoStream = avformat_new_stream(outputFormatCtx, nullptr);
    AVStream* audioStream = avformat_new_stream(outputFormatCtx, nullptr);

    // 5. 循环读取帧并写入文件
    AVPacket packet;
    while (!GetAsyncKeyState(VK_ESCAPE)) {
        // 读取视频帧
        if (av_read_frame(screenFormatCtx, &packet) >= 0) {
            av_packet_rescale_ts(&packet, screenFormatCtx->streams[packet.stream_index]->time_base, videoStream->time_base);
            packet.stream_index = videoStream->index;
            av_interleaved_write_frame(outputFormatCtx, &packet);
            av_packet_unref(&packet);
        }

        // 读取音频帧
        if (av_read_frame(audioFormatCtx, &packet) >= 0) {
            av_packet_rescale_ts(&packet, audioFormatCtx->streams[packet.stream_index]->time_base, audioStream->time_base);
            packet.stream_index = audioStream->index;
            av_interleaved_write_frame(outputFormatCtx, &packet);
            av_packet_unref(&packet);
        }
    }

    // 6. 释放资源
    avformat_close_input(&screenFormatCtx);
    avformat_close_input(&audioFormatCtx);
    avio_closep(&outputFormatCtx->pb);
    avformat_free_context(outputFormatCtx);

    std::cout << "录制完成!保存为 output.mp4" << std::endl;
    return 0;
}

三、总结

方法适用场景优点缺点
FFmpeg 命令行快速开发简单依赖外部进程
libavformat/libavcodec高性能、精细控制直接操作音视频流代码复杂

推荐

  • 快速开发 → 直接调用 ffmpeg 命令行。

  • 高性能/嵌入式 → 使用 FFmpeg 库(如 libavformat)。

http://www.dtcms.com/a/109295.html

相关文章:

  • 单片机学习之定时器
  • 嵌入式海思Hi3861连接华为物联网平台操作方法
  • Zapier MCP:重塑跨应用自动化协作的技术实践
  • 【Linux】Orin NX + Ubuntu22.04配置国内源
  • 如何实现一个优雅的Go协程池
  • ORION:基于VLM引导动作生成的端到端框架——论文精度
  • 源码分析之Leaflet图层控制控件Control.Layers实现原理
  • 量子计算与人工智能的结合:未来科技的双重革命
  • 人工智能混合编程实践:C++ ONNX进行图像超分重建
  • 从零实现Json-Rpc框架】- 项目实现 - 服务端主题实现及整体封装
  • “清凉海岛·创享一夏” 海南启动旅游线路产品创意设计大赛
  • 【C语言】strstr查找字符串函数
  • 基于milvus安装--可视化工具 attu
  • PyQt6实例_A股日数据维护工具_子窗体
  • 深入理解浏览器的事件循环
  • CentOS7 安装Redis
  • HTML应用指南:利用POST请求获取三大运营商5G基站位置信息(二)
  • OpenCV第3课 图像的绘制以及基本操作
  • C++:继承+菱形虚拟继承的一箭双雕
  • Could not find artifact com.microsoft.sqlserver:sqljdbc4:jar:4.0 in central
  • 2025年嵌入式大厂春招高频面试真题及解析
  • 使用Deployment运行无状态应用
  • 前缀和 一维差分和二维差分 差分差分矩阵
  • php的动态扩展模块(php的缓存模块)
  • 创建python虚拟环境
  • 记录一下零零散散的的东西-ImageNet
  • 大模型——如何在本地部署微软的OmniParser V2
  • PyTorch复现线性模型
  • 大模型 PDF解析-MinerU
  • 容器适配器-stack栈