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 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 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)。
相关文章:
FFmpeg录制屏幕和音频
一、FFmpeg命令行实现录制屏幕和音频 1、Windows 示例 #include <cstdlib> #include <string> #include <iostream>int main() {// FFmpeg 命令行(录制屏幕 麦克风音频)std::string command "ffmpeg -f gdigrab -framerate 3…...
爬虫:请求头,requests库基本使用
请求方式:get(向服务器要资源)和post(提交资源) user-agent:模拟正常用户的一种方式 cookie:登陆保持 referer:表示当前这一次请求是由哪个请求过来的 抓取数据包得到的内容才是判断依据elements中的源码是渲染之后的不能作为…...
[物联网iot]对比WIFI、MQTT、TCP、UDP通信协议
第一步:先理解最基础的关系(类比快递) 假设你要给朋友寄快递: Wi-Fi:相当于“公路和卡车”,负责把包裹从你家运到快递站。 TCP/UDP:相当于“快递公司的运输规则”。 TCP:顺丰快递&…...
CSDN自动设置vip文章的解除办法
文章目录 CSDN真的会将“全部可见”文章偷偷自动设置为“VIP可读”最省事的途径:联系客服,预计1-2个工作日可以取消新版“内容管理”内手工操作 CSDN真的会将“全部可见”文章偷偷自动设置为“VIP可读” 今天无意中发现之前一些公开的文章变为仅VIP可读…...
P4305 [JLOI2011] 不重复数字
使用stl中的动态数组和unordered_map #include<iostream> #include<iostream> #include<vector> #include<unordered_map> using namespace std; int t; int main(){cin>>t;while(t--){//每次处理一组数据.int n;cin>>n;vector<int&…...
Joomla教程—Joomla 模块管理与Joomla 模块类型介绍
Joomla 模块管理 原文:Joomla 模块管理_w3cschool 模块管理,从文字意面上理解,可想而知,就是管理网站中所有的模块,模块的增、删、改、查都会在模块管理进行。这一节将简单介绍joomla后台的模块管理 1、模块管理的界…...
安装gvm后普通用户模式下无法使用cd切换目录
安装gvm后普通用户模式下无法使用cd切换目录 今天装完gvm后发现无法使用cd来切换目录了。。。 1.使用type cd命令发现cd命令被定义为了函数 usrusr-pc:~$ type cd cd 是函数 cd () { if __gvm_is_function __gvm_oldcd; then__gvm_oldcd $*;fi;local dot_go_version dot_go_…...
Pyspark学习二:快速入门基本数据结构
写在前面:实际工作中其实不需要自己安装和配置,更重要的是会用。所以就不研究怎么安装配置了。 前面介绍过:简单来说,Spark是一款分布式的计算框架,用于调度成百上千的服务器集群,计算TB、PB乃至EB级别的海…...
Vue中虚拟DOM创建到挂载的过程
Vue中虚拟DOM创建到挂载的过程 流程概括下来基本上就是:模板 → AST → render函数 → 虚拟节点 → 挂载 AST:抽象语法树,它用于记录原始代码中所有的关键信息,根据AST可以将代码从一种语言转化为另一种语言。 虚拟DOM创建到挂载…...
选择网上购物系统要看几方面?
随着电子商务的迅猛发展,选择一个合适的网上购物系统已成为许多企业成功的关键。无论是初创企业还是已经成熟的公司,选择合适的购物系统都能显著提升用户体验、提高销售额和优化运营效率。本文将从几个重要方面探讨选择网上购物系统时需要考虑的关键因素…...
C++进阶知识复习 31~38
目的 写这一系列文章的目的主要是为了秋招时候应对计算机基础问题能够流畅的回答出来 (如果不整理下 磕磕绊绊的回答会被认为是不熟悉) 本文章题目的主要来源来自于 面试鸭 部分面试鸭上没有而牛客网上有的博主会进行查缺补漏 题目编号按照面试鸭官网…...
定制开发开源AI智能名片S2B2C商城小程序:技术赋能商业价值实现路径研究
摘要 在数字经济与社交新零售蓬勃发展的背景下,本研究聚焦"定制开发开源AI智能名片S2B2C商城小程序"这一创新技术解决方案,通过解析其技术架构、功能模块及业务应用场景,探讨其如何支持企业目标达成、补充技术栈短板、实现数据整合…...
美关税加征下,Odoo免费开源ERP如何助企业破局?
近期,美国特朗普政府推行的关税政策对全球供应链和进出口企业造成巨大冲击,尤其是依赖中美贸易的企业面临成本激增、利润压缩和合规风险。在此背景下,如何通过数字化转型优化管理效率、降低运营成本成为企业生存的关键。本文以免费开源ERP系统…...
高级:高并发架构面试题深度解析
一、引言 在现代互联网应用开发中,高并发架构设计是确保系统在高负载下仍能稳定、高效运行的关键。面试官通过相关问题,考察候选人对高并发系统设计的理解、架构模式的掌握以及在实际项目中解决问题的能力。本文将深入剖析高并发系统的设计原则、常见的…...
Unity中 JobSystem使用整理
Unity 的JobSystem允许创建多线程代码,以便应用程序可以使用所有可用的 CPU 内核来执行代码,这提供了更高的性能,因为您的应用程序可以更高效地使用运行它的所有 CPU 内核的容量,而不是在一个 CPU 内核上运行所有代码。 可以单独使…...
洛谷 P1032 [NOIP 2002 提高组] 字串变换
【题目链接】 洛谷 P1032 [NOIP 2002 提高组] 字串变换 【题目考点】 1. 广搜 2. 双向广搜 【解题思路】 解空间树中每个结点包含的状态为一个字符串s,该结点的子结点中的字符串为字符串s通过变换规则可以变化而成的字符串。求从起始字符串变换为最终字符串的…...
Python Websockets库深度解析:构建高效的实时Web应用
引言 在现代Web开发中,实时通信已经成为许多应用的核心需求。无论是聊天应用、在线游戏、金融交易平台还是协作工具,都需要服务器和客户端之间建立持久、双向的通信通道。传统的HTTP协议由于其请求-响应模式,无法有效满足这些实时交互需求。…...
42.C++11-右值引用与移动语义/完美转发
⭐上篇文章:41.C哈希6(哈希切割/分片/位图/布隆过滤器与海量数据处理场景)-CSDN博客 ⭐本篇代码:c学习/22.C11新特性的使用 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) ⭐标⭐是比较重要的部分 目录 一. 右值引用…...
LeetCode题二:判断回文
查阅资料我得到的结果远没有大佬们的做法更省时间,而且还很麻烦 我的代码(完整): class Solution:def isPalindrome(self, x: int) -> bool:# 若 x 为负数,由于负数不可能是回文数,直接返回 Falseif x < 0:return False# …...
[王阳明代数讲义]琴语言类型系统工程特性
琴语言类型系统工程特性 层展物理学组织实务与艺术与琴生生.物机.械科.技工.业研究.所软凝聚态物理开发工具包社会科学气质砥砺学人生意气场社群成员魅力场与心气微积分社会关系力学 意气实体过程图论信息编码,如来码导引 注意力机制道装Transformer架构的发展标度律…...
问题:tomcat下部署eureka双重路径
开发时在tomcat下启动eureka服务 客户端注册时需要地址需要注意 http://localhost:8761/eureka/eureka 后面一个eureka与tomcat context-path有关系按实际配置替换 如果不想要两个path可将tomcat context-path写为 / 建议使用 / 避免出现其他问题 如图...
JUC系列JMM学习之随笔
JUC: JUC 是 Java 并发编程的核心工具包,全称为 Java Util Concurrent,是 java.util.concurrent 包及其子包的简称。它提供了一套强大且高效的并发编程工具,用于简化多线程开发并提高性能。 CPU核心数和线程数的关系:1核处理1线程(同一时间单次) CPU内核结构: 工作内…...
React(九)React Hooks
初识Hook 我们到底为什么需要hook那? 函数组件类组件存在问题 函数组件存在的问题: import React, { PureComponent } from reactfunction HelloWorld2(props) {let message"Hello world"// 函数式组件存在的缺陷:// 1.修改message之后&a…...
PyTorch嵌入层(nn.Embedding)
在 PyTorch 中,nn.Embedding 层(即 model.user_embedding)除了 .weight 这个核心属性外,还有其他属性和方法。以下是完整的解析: 1. 主要属性 (1) weight(核心参数) 作用:存储所有…...
AIGC7——AIGC驱动的视听内容定制化革命:从Sora到商业化落地
引言:个性化视听时代的到来 2024年,OpenAI发布视频生成模型Sora,可生成60秒高清视频;中国团队推出的Vidu模型实现16秒镜头连贯生成。这些突破标志着AIGC正式进入高质量视听内容定制化阶段。据Gartner预测,到2027年&am…...
接上文,SpringBoot的线程池配置以及JVM监控
接上篇文章, 拿SpringBoot举个例 1.1 默认线程池的隐患 Spring Boot的Async默认使用SimpleAsyncTaskExecutor(无复用线程),频繁创建/销毁线程易引发性能问题。 1.2 自定义线程池配置 Configuration EnableAsync public class A…...
《AI大模型应知应会100篇》加餐篇:LlamaIndex 与 LangChain 的无缝集成
加餐篇:LlamaIndex 与 LangChain 的无缝集成 问题背景:在实际应用中,开发者常常需要结合多个框架的优势。例如,使用 LangChain 管理复杂的业务逻辑链,同时利用 LlamaIndex 的高效索引和检索能力构建知识库。本文在基于…...
部署大模型实战:如何巧妙权衡效果、成本与延迟?
目录 部署大模型实战:如何巧妙权衡效果、成本与延迟? 一、为什么要进行权衡? 二、权衡的三个关键维度 三、如何进行有效权衡?(实操策略) (一)明确需求场景与优先级 (…...
元素三大等待
硬性等待(强制等待) 线程休眠,强制等待 Thread.sleep(long millis);这是最简单的等待方式,使用time.sleep()方法来实现。在代码中强制等待一定的时间,不论元素是否已经加载完成,都会等待指定的时间后才继…...
【DY】信息化集成化信号采集与处理系统;生物信号采集处理系统一体机
MD3000-C信息化一体机生物信号采集处理系统 实验平台技术指标 01、整机外形尺寸:1680mm(L)*750mm(w)*2260mm(H); 02、实验台操作面积:750(w)*1340(L)(长*宽); 03、实验台面离地高度…...
