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() {// 初始化 FFmpegavdevice_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() {// 初始化 FFmpegavdevice_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.mzph.cn/news/900080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据集】多视图文本数据集

多视图文本数据集指的是包含多个不同类型或来源的信息的文本数据集。不同视图可以来源于不同的数据模式&#xff08;如原始文本、元数据、网络结构等&#xff09;&#xff0c;或者不同的文本表示方法&#xff08;如 TF-IDF、词嵌入、主题分布等&#xff09;。这些数据集常用于多…

C++ 继承方式使用场景(极简版)

1. 公有继承&#xff08;public&#xff09; 什么时候用&#xff1f; “是一个”&#xff08;is-a&#xff09;关系&#xff1a;派生类 是 基类的一种。 例&#xff1a;class Dog : public Animal&#xff08;狗是动物&#xff09; 最常见&#xff0c;90%的继承都用它。 2. 保…

Ubuntu 系统 Docker 中搭建 CUDA cuDNN 开发环境

CUDA 是 NVIDIA 推出的并行计算平台和编程模型&#xff0c;利用 GPU 多核心架构加速计算任务&#xff0c;广泛应用于深度学习、科学计算等领域。cuDNN 是基于 CUDA 的深度神经网络加速库&#xff0c;为深度学习框架提供高效卷积、池化等操作的优化实现&#xff0c;提升模型训练…

高密度任务下的挑战与破局:数字样机助力火箭发射提效提质

2025年4月1日12时&#xff0c;在酒泉卫星发射中心&#xff0c;长征二号丁运载火箭顺利升空&#xff0c;成功将一颗卫星互联网技术试验卫星送入预定轨道&#xff0c;发射任务圆满完成。这是长征二号丁火箭的第97次发射&#xff0c;也是长征系列火箭的第567次发射。 执行本次任务…

关于SQL子查询的使用策略

在 SQL 优化中&#xff0c;一般遵循**“非必要不使用子查询”**的原则&#xff0c;因为子查询可能会带来额外的计算开销&#xff0c;影响查询效率。但是&#xff0c;并不是所有子查询都需要避免&#xff0c;有时子查询是最优解&#xff0c;具体要根据实际场景选择合适的优化方式…

JavaEE初阶复习(JVM篇)

JVM Java虚拟机 jdk java开发工具包 jre java运行时环境 jvm java虚拟机(解释执行 java 字节码) java作为一个半解释,半编译的语言,可以做到跨平台. java 通过javac把.java文件>.class文件(字节码文件) 字节码文件, 包含的就是java字节码, jvm把字节码进行翻译转化为…

2.pycharm保姆级安装教程

一、pycharm安装 1.官网上下载好好软&#xff0c;双击打开 2.下一步 3.修改路径地址 (默认也可以) 4.打勾 5.安装 不用重启电脑 二、添加解释器 1.双击软件&#xff0c;打开 2.projects – new project 3.指定项目名字&#xff0c;项目保存地址&#xff0c;解释器 4.右击 – …

zk基础—4.zk实现分布式功能二

大纲 1.zk实现数据发布订阅 2.zk实现负载均衡 3.zk实现分布式命名服务 4.zk实现分布式协调(Master-Worker协同) 5.zk实现分布式通信 6.zk实现Master选举 7.zk实现分布式锁 8.zk实现分布式队列和分布式屏障 4.zk实现分布式协调(Master-Worker协同) (1)Master-Worker架构…

Java 实现 字母异位词分组

在这篇博客中&#xff0c;我们将详细解析如何使用 Java 代码来解决 字母异位词分组这个经典的算法问题。我们会逐步分析代码逻辑&#xff0c;并探讨其时间复杂度及优化思路。 题目描述 给定一个字符串数组 strs&#xff0c;请将字母异位词组合在一起。字母异位词是指由相同字…

【Ragflow】10. 助理配置参数详细解析/模型响应加速方法

概述 Ragflow的助理配置中&#xff0c;有很多参数&#xff0c;尽管官方文档给出了一定程度的解释&#xff0c;但不够详细。 本文将对各项参数进行更详细的解释说明&#xff0c;并进一步挖掘某些参数中隐含的潜在陷阱。 助理设置 空回复 含义&#xff1a;输入的问题若未能在…

Mac Apple silicon如何指定运行amd64架构的ubuntu Docker?

如何指定运行amd64架构的ubuntu Docker 下面这个docker命令如何指定运行amd64架构的ubuntu Docker&#xff1f; docker run -it -v $(pwd):/workspace ubuntu:20.04 bash这个命令已经非常接近正确运行一个基于 amd64 架构的 Ubuntu 容器了&#xff0c;但如果你想明确指定运行…

ColPali:基于视觉语言模型的高效文档检索

摘要 文档是视觉丰富的结构&#xff0c;不仅通过文本传递信息&#xff0c;还包括图表、页面布局、表格&#xff0c;甚至字体。然而&#xff0c;由于现代检索系统主要依赖从文档页面中提取的文本信息来索引文档&#xff08;通常是冗长且脆弱的流程&#xff09;&#xff0c;它们…

使用C++实现HTTP服务

天天开心&#xff01;&#xff01;&#xff01; 阅读本篇文章之前&#xff0c;请先阅读HTTP基础知识 传送门----> HTTP基础知识 文章目录 一、CWeb服务器&#xff08;核心代码WebServer.cpp&#xff09;二、静态文件结构三、编译和运行四、访问测试 一、CWeb服务器&#xff…

Reactive编程入门:Project Reactor 深度指南

文章目录 4.2.1 创建 Flux 和 MonoFlux 基础创建方式高级创建模式Mono 创建方式 4.2.2 订阅与数据处理基础订阅模式数据处理操作符 4.2.3 核心操作符深度解析flatMap 操作符zip 操作符buffer 操作符 高级组合模式复杂流处理示例背压处理策略 测试响应式流性能优化技巧 React 编…

【万字总结】前端全方位性能优化指南(完结篇)——自适应优化系统、遗传算法调参、Service Worker智能降级方案

前言 自适应进化宣言 当监控网络精准定位病灶&#xff0c;真正的挑战浮出水面&#xff1a;系统能否像生物般自主进化&#xff1f; 五维感知——通过设备传感器实时捕获环境指纹&#xff08;如地铁隧道弱光环境自动切换省电渲染&#xff09; 基因调参——150个性能参数在遗传算…

PQ以及有关索引的笔记Faiss: The Missing Manual

参考Faiss 索引结构总结&#xff1a; 为了加深记忆&#xff0c;介绍一下Inverted File Index&#xff08;IVF&#xff09;的名字由来&#xff1a; IVF索引的名字源自“倒排文件”&#xff08;Inverted File&#xff09;的概念。在传统的信息检索中&#xff0c;倒排文件是一种索…

win10彻底让图标不显示在工具栏

关闭需要不显示的软件 打开 例此时我关闭了IDEA的显示 如果说只是隐藏&#xff0c;鼠标拖动一个道理 例QQ 如果说全部显示不隐藏

关税核爆72小时!跨境矩阵防御战紧急打响

一、T86崩塌&#xff1a;全球贸易链的至暗时刻 &#xff08;配图&#xff1a;美国海关系统深夜弹出红色警报&#xff09; 5月2日凌晨2:17&#xff0c;杭州某光伏企业的供应链系统突然发出刺耳警报——其价值1800万美元的逆变器模块被划入34%关税清单。这场代号"黑天鹅突…

蓝桥杯Java B组省赛真题题型近6年统计分类

困难题 题号题型分值代码量难度通过率内容2024-F解答1581困难0.12最短路问题 Dijkstra 期望2024-G解答20116困难0.19模拟 暴力 搜索 DFS 剪纸 枚举2023-H解答2070困难0动态规划2022-H解答20109困难0.032022-J解答25141困难0搜索2021-H解答2041困难0.18二分 思维 规律2021-I解答…

【网络流 图论建模 最大权闭合子图】 [六省联考 2017] 寿司餐厅

题目描述&#xff1a; P3749 [六省联考 2017] 寿司餐厅 题目描述 Kiana 最近喜欢到一家非常美味的寿司餐厅用餐。 每天晚上&#xff0c;这家餐厅都会按顺序提供 n n n 种寿司&#xff0c;第 i i i 种寿司有一个代号 a i a_i ai​ 和美味度 d i , i d_{i, i} di,i​&…