> 技术文档 > FFmpeg录制屏幕和音频_ffmpeg 录屏

FFmpeg录制屏幕和音频_ffmpeg 录屏


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

1、Windows 示例

#include #include #include 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 gdigrab Windows 屏幕捕获驱动 -f x11grab Linux 屏幕捕获驱动 -f avfoundation macOS 屏幕/音频捕获驱动 -i desktop 捕获整个屏幕(Windows) -i :0.0 Linux 主显示器(X11) -f dshow -i audio=\"...\" Windows 音频设备名(通过 ffmpeg -list_devices true -f dshow -i dummy 查询) -f alsa -i default Linux 默认音频输入 -c:v libx264 H.264 视频编码 -preset ultrafast 编码速度优化(牺牲压缩率) -crf 18 视频质量(18~28,值越小质量越高) -c:a aac AAC 音频编码 -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 NVENCstd::string command = \"ffmpeg -f gdigrab -framerate 30 -i desktop -c:v h264_nvenc -preset p7 -tune hq output.mp4\";// Intel QuickSyncstd::string command = \"ffmpeg -f gdigrab -framerate 30 -i desktop -c:v h264_qsv -preset faster output.mp4\";

 3)仅录制音频

// Windowsstd::string command = \"ffmpeg -f dshow -i audio=\\\"麦克风 (Realtek Audio)\\\" -c:a aac audio.m4a\";// Linuxstd::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 #include extern \"C\" {#include #include #include #include }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 #include extern \"C\" {#include #include #include }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 << \"无法打开音频输入!\" <= 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)。