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
-f x11grab
-f avfoundation
-i desktop
-i :0.0
-f dshow -i audio=\"...\"
ffmpeg -list_devices true -f dshow -i dummy
查询)-f alsa -i default
-c:v libx264
-preset ultrafast
-crf 18
-c:a aac
-b:a 192k
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
命令行。 -
高性能/嵌入式 → 使用 FFmpeg 库(如
libavformat
)。