下载“Windows应用-音视频捕获”项目
本应用可以同时捕获4个视频源和4个音频源,可以监视视频源图像,监听音频源;可以将视频源图像写入MP4文件,将音频源写入MP3或WAV文件;还可以录制系统播放的声音。本应用使用MFC对话框程序创建。下面是应用的界面图像。
在这里插入图片描述

使用方法

启动应用就可以获取捕获设备,也可以按“重新捕获”按钮,再次捕获。上图是,电脑外接1个摄像头和1个话筒获得的界面图像。红色区域中,左侧是视频捕获设备名称,其右是监视按钮,点击可以显示该捕获设备当前视频图像,“SelAu”按钮点击后,会弹出菜单,菜单项是音频捕获设备名称和系统声音,选择菜单项就可以为视频录制指定声音源。点击“录制”按钮,会将该捕获设备的图像和选择的声音,写入MP4文件。
蓝色区域中,左侧是音频捕获设备名称,其右是监听按钮,点击后,电脑可以播放该捕获设备的声音;监听按钮右边的按钮可以选择录制产生的文件的格式(wav或mp3)。点击“录制”按钮,会将该声音源写入音频文件。

应用开发信息

应用使用了4个插件,捕获.dll,写MP4.dll,写wav.dll,写mp3.dll。有关这4个插件的信息可以看前面的文章。捕获.dll使用媒体基础的方法获取捕获设备。虽然DirectShow也可以实现音视频捕获,但由于媒体基础对象可以在win32和MFC程序中创建并使用,所以使用起来更加灵活。
加载捕获DLL,获取两个导出函数的地址。

typedef int(__cdecl *MYPROC_CAP_Init)(CAP_INIT init, CAP_VIDEO_INFO*& VideoInfo, CAP_AUDIO_INFO*& AudioInfo);
typedef int(__cdecl *MYPROC_VOID)();HMODULE hCap = NULL;//捕获dll模块句柄MYPROC_CAP_Init CAP_Init = NULL;MYPROC_VOID CAP_ReleaseDevice = NULL;hCap = LoadLibrary(L"捕获.dll");//加载捕获模块if (hCap){CAP_Init=(MYPROC_CAP_Init)GetProcAddress(hCap, "Init");//获取捕获模块“初始化”函数地址CAP_ReleaseDevice=(MYPROC_VOID)GetProcAddress(hCap, "ReleaseDevice");//获取捕获模块“释放所有捕获设备”函数地址}

定义捕获初始化结构和视频样本,音频样本输出函数。

typedef int(__cdecl *MYPROC_CAP_Sample)(LONGLONG star, LONGLONG end, BYTE* pB, LONG len);int VideoSample0(LONGLONG star, LONGLONG end, BYTE* pB, LONG len)//视频流0样本输出函数
{return 1;
}
....struct CAP_INIT
{MYPROC_CAP_Sample VideoSample0 = NULL;//视频样本输出函数MYPROC_CAP_Sample VideoSample1 = NULL;MYPROC_CAP_Sample VideoSample2 = NULL;MYPROC_CAP_Sample VideoSample3 = NULL;MYPROC_CAP_Sample AudioSample0 = NULL;//音频样本输出函数MYPROC_CAP_Sample AudioSample1 = NULL;MYPROC_CAP_Sample AudioSample2 = NULL;MYPROC_CAP_Sample AudioSample3 = NULL;
};

调用捕获初始化函数,此时将获取捕获设备,创建视频流和音频流。即,视频音频样本输出函数被反复调用,函数的参数提供时间戳,样本缓冲区指针和样本大小。

	CAP_INIT CapInit;CapInit.VideoSample0 = &VideoSample0;//为视频,音频源指定输出函数CapInit.VideoSample1 = &VideoSample1;CapInit.VideoSample2 = &VideoSample2;CapInit.VideoSample3 = &VideoSample3;CapInit.AudioSample0 = &AudioSample0;CapInit.AudioSample1 = &AudioSample1;CapInit.AudioSample2 = &AudioSample2;CapInit.AudioSample3 = &AudioSample3;struct CAP_VIDEO_INFO
{UINT32 Width = 0;//视频宽,单位像素UINT32 Height = 0;//视频高,单位像素double nFrames = 0;//帧率WCHAR *Name = NULL;//视频捕获设备名称
};struct CAP_AUDIO_INFO
{UINT32 nCh;//声道数WCHAR *Name = NULL;//视频捕获设备名称
};CAP_VIDEO_INFO* pVInfo = NULL;//结构数组用于存储视频流,音频流信息CAP_AUDIO_INFO* pAInfo = NULL;pVInfo = new CAP_VIDEO_INFO[4]; pAInfo = new CAP_AUDIO_INFO[4];//结构数组用于存储视频流,音频流信息	WORD w = CAP_Init(CapInit, pVInfo, pAInfo);//获取捕获设备,创建视频流,音频流ACount = LOBYTE(w); VCount = HIBYTE(w);//获取音频流,视频流数量

在程序退出时,释放所有捕获设备。

	CAP_ReleaseDevice();//释放捕获设备

加载写MP4 DLL,获取所有导出函数地址。

typedef int(__cdecl *MYPROC_MP4_Init)(int index, MW_INIT init);
typedef int(__cdecl *MYPROC_Sample)(BYTE* pB, LONG len);
typedef int(__cdecl *MYPROC_ISample)(int index, BYTE* pB, LONG len);
typedef int(__cdecl *MYPROC_IVSample)(int index, LONGLONG star, LONGLONG end, BYTE* pB, LONG len);
typedef int(__cdecl *MYPROC_IVOID)(int index);
typedef int(__cdecl *H264Set)(int index, VARIANT var);
typedef int(__cdecl *H264Get)(int index, VARIANT& var);HMODULE hMp4 = NULL;MYPROC_VOID MP4_Create = NULL;MYPROC_MP4_Init MP4_Init = NULL;MYPROC_IVSample MP4_VSample = NULL;MYPROC_ISample MP4_ASample = NULL;MYPROC_IVOID MP4_Exit = NULL;MYPROC_IVOID MP4_GetState = NULL;MYPROC_IVOID MP4_Stop = NULL;MYPROC_IVOID MP4_Run = NULL;MYPROC_VOID MP4_DestroyAll = NULL;H264Set H264_SetAdaptiveMode = NULL;//自适应地更改帧速率设置函数H264Set H264_SetRateMode = NULL;//速率控制模式设置函数H264Set H264_SetQuality = NULL;//质量级别设置函数H264Set H264_SetQualityVsSpeed = NULL;//质量/速度权衡设置函数H264Set H264_SetMeanBitRate = NULL;//平均比特率设置函数H264Get H264_GetMeanBitRate = NULL;hMp4 = LoadLibrary(L"写MP4.dll");//加载写MP4模块if (hMp4){MP4_Create = (MYPROC_VOID)GetProcAddress(hMp4, "Create");//创建MP4_Init=(MYPROC_MP4_Init)GetProcAddress(hMp4, "Init");//初始化MP4_VSample=(MYPROC_IVSample)GetProcAddress(hMp4, "WriteVideoSample");//写视频样本MP4_ASample = (MYPROC_ISample)GetProcAddress(hMp4, "WriteAudioSample");//写音频样本MP4_GetState = (MYPROC_IVOID)GetProcAddress(hMp4, "GetState");//获取状态MP4_Run=(MYPROC_IVOID)GetProcAddress(hMp4, "Run");//运行MP4_Stop=(MYPROC_IVOID)GetProcAddress(hMp4, "Stop");//停止MP4_Exit=(MYPROC_IVOID)GetProcAddress(hMp4, "Exit");//退出MP4_DestroyAll = (MYPROC_VOID)GetProcAddress(hMp4, "DestroyAll");H264_SetAdaptiveMode = (H264Set)GetProcAddress(hMp4, "H264_SetAdaptiveMode");//自适应地更改帧速率H264_SetRateMode = (H264Set)GetProcAddress(hMp4, "H264_SetRateControlMode");//速率控制模式H264_SetQuality = (H264Set)GetProcAddress(hMp4, "H264_SetQuality");//质量级别H264_SetQualityVsSpeed = (H264Set)GetProcAddress(hMp4, "H264_SetQualityVsSpeed");//质量/速度权衡H264_SetMeanBitRate = (H264Set)GetProcAddress(hMp4, "H264_SetMeanBitRate");//平均比特率H264_GetMeanBitRate = (H264Get)GetProcAddress(hMp4, "H264_GetMeanBitRate");MP4_Create(); MP4_Create(); MP4_Create(); MP4_Create();//创建4个写MP4对象}

下面以录制1个视频源举例。
开始录制视频源0:

struct MW_INIT
{WCHAR* Path;//输出文件路径UINT VideoWidth;//视频图像宽度,单位像素UINT VideoHeight;//视频图像高度,单位像素double nFramePerSec;//视频每秒帧数BOOL Fixed;//TRUE,样本持续时间是固定值;FALSE,非固定值UINT BIT_RATE;//视频传输率。为0使用默认传输率UINT AudioSamplesPerSec;//音频采样率
};
int mvState0=0//录制状态。在“C音视频捕获Dlg”类中定义MW_INIT MwInit;MwInit.Path = L"D:\\1.mp4";MwInit.VideoWidth = 1280;MwInit.VideoHeight = 720;MwInit.nFramePerSec = 30;MwInit.BIT_RATE = 0;MwInit.Fixed = FALSE;MwInit.AudioSamplesPerSec = 48000;MP4_Init(0, MwInit);MP4_Run(0);mvState0 = 1;//录制状态

暂停录制视频源0:

	if (mvState0 == 1){mvState0 = 2;MP4_Stop(0);}

停止录制视频源0:

	mvState0 = 0;MP4_Stop(0);MP4_Exit(0);

在视频流0样本输出函数中,写视频样本:

//以下变量在“C音视频捕获Dlg”类中定义int mvState0, mvState1, mvState2, mvState3;//视频录制状态。0停止,1运行,2暂停LONGLONG mTime0, mTime1, mTime2, mTime3;BOOL First0, First1, First2, First3;LONGLONG mStar0, mStar1, mStar2, mStar3;LONGLONG mPause0, mPause1, mPause2, mPause3;int VideoSample0(LONGLONG star, LONGLONG end, BYTE* pB, LONG len)//视频流0样本输出函数
{C音视频捕获Dlg* pDlg = (C音视频捕获Dlg*)theApp.m_pMainWnd;if (pDlg->mvState0 == 0)//如果停止{pDlg->First0 = TRUE;pDlg->mTime0 = 0; pDlg->mPause0 = 0;}if (pDlg->mvState0 == 1)//如果运行{if (pDlg->First0){pDlg->First0 = FALSE;pDlg->mStar0 = star;}pDlg->MP4_VSample(0, pDlg->mPause0 + star - pDlg->mStar0, pDlg->mPause0 + end - pDlg->mStar0, pB, len);pDlg->mTime0 = pDlg->mPause0 + end - pDlg->mStar0;}if (pDlg->mvState0 == 2)//如果暂停{pDlg->First0 = TRUE;pDlg->mPause0 = pDlg->mTime0;}return 1;
}

在音频流0样本输出函数中,写音频样本:

int AudioSample0(LONGLONG star, LONGLONG end, BYTE* pB, LONG len)//音频流0样本输出函数
{C音视频捕获Dlg* pDlg = (C音视频捕获Dlg*)theApp.m_pMainWnd;if (pDlg->mvState0 == 1 &&pDlg->mAudioSel0 == 0)//如果图像0需要获取此音频{if (pDlg->MP4_GetState(0))//如果写MP4已运行{pDlg->MP4_ASample(0, pB, len);}}return 1;
}

如果需要全部代码,可以下载“Windows应用-音视频捕获”项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/86249.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/86249.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/86249.shtml

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

相关文章

MATLAB生成大规模无线通信网络拓扑(任意节点数量)

功能: 生成任意节点数量的网络拓扑,符合现实世界节点空间分布和连接规律 效果: 30节点: 100节点: 500节点: 程序: %创建时间:2025年6月8日 %zhouzhichao %自然生长出n节点的网络% …

TDengine 开发指南—— UDF函数

UDF 简介 在某些应用场景中,应用逻辑需要的查询功能无法直接使用内置函数来实现,TDengine 允许编写用户自定义函数(UDF),以便解决特殊应用场景中的使用需求。UDF 在集群中注册成功后,可以像系统内置函数一…

C#提取CAN ASC文件时间戳:实现与性能优化

C#提取CAN ASC文件时间戳:实现与性能优化 在汽车电子和工业控制领域,CAN总线是最常用的通信协议之一。而ASC(ASCII)文件作为CAN总线数据的标准日志格式,广泛应用于数据记录和分析场景。本文将深入探讨如何高效地从CAN…

计算机网络基础总结:TCP/IP 模型、TCP vs UDP、DNS 查询过程

在学习计算机网络的过程中,理解 TCP/IP 模型与 OSI 模型的对应关系、掌握 TCP 与 UDP 的区别,以及熟悉 DNS 的查询过程,是打好网络基础的关键。本文将围绕这三部分进行简明扼要的讲解。 一、TCP/IP 模型与 OSI 七层模型的对应关系 1. OSI 七…

基于PHP的扎染文创产品商城

有需要请加文章底部Q哦 可远程调试 基于PHP的扎染文创产品商城 一 介绍 扎染文创产品商城系统基于原生PHP开发,数据库mysql,前端bootstrap,jquery.js等。系统角色分为用户和管理员。 技术栈:phpmysqlbootstrapphpstudyvscode 二…

数据库学习(三)——MySQL锁

一、MySQL锁 当多个用户或进程并发操作数据库时,为了避免数据冲突、脏读、不可重复读、幻读等问题,数据库通过锁机制来保证数据的一致性和完整性。 MySQL 锁的总体分类: 分类维度类型说明按作用对象表级锁(Table Lock&#xff…

<3>-MySQL表的操作

目录 一,创建表 二,查看表结构 三,修改表 四,删除表 一,创建表 语法: CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 eng…

【OSG学习笔记】Day 15: 路径动画与相机漫游

本章来学习下漫游相机。 路径动画与相机漫游 本届内容比较简单,其实就是实现物体的运动和相机的运动 当然这两个要一起执行。 贝塞尔曲线 贝塞尔曲线(Bzier curve)是一种在计算机图形学、动画制作、工业设计等领域广泛应用的参数曲线&am…

LabVIEW自感现象远程实验平台

LabVIEW开发自感现象远程实验平台,通过整合 NI数据采集设备、菲尼克斯(Phoenix Contact)继电器模块及罗技(Logitech)高清摄像头,实现远程数据采集、仪器控制与实时监控三大核心功能。平台突破传统实验装置局…

数据结构——F/图

一、图的基本概念 图是由顶点集合及顶点间的关系组成的一种数据结构&#xff1a;G (V&#xff0c; E)&#xff0c;其中&#xff1a; 顶点集合V {x|x属于某个数据对象集}是有穷非空集合&#xff1b; E {(x,y)|x,y属于V}或者E {<x, y>|x,y属于V && Path(x, y)…

springcloud openfeign 偶现 Caused by: java.net.UnknownHostException

背景 最近查看日志发现某服务偶现Caused by: java.net.UnknownHostException 同时查看eureka的access.log 出现如下异常 10.xxx.xxx.xxx - - [27/May/2025:23:57:29 0800] “PUT /eureka/apps/{appName}/{host}:xxx-job:8082?statusUP&lastDirtyTimestamp1748351637173 H…

第12篇:数据库中间件日志设计与追踪系统落地实践

12.1 引言&#xff1a;中间件日志系统为何如此关键&#xff1f; 数据库中间件作为连接前端应用与后端数据库的“网关”&#xff0c;承载着路由、负载均衡、SQL 改写、权限控制等复杂逻辑。 在出现 性能问题、故障排查、安全审计 等场景中&#xff0c;若没有完善的日志体系&am…

OpenAI对抗法庭命令:捍卫ChatGPT用户隐私之战

人工智能公司OpenAI近期正积极对抗一项涉及隐私问题的法庭命令。该命令要求OpenAI保留所有ChatGPT用户日志&#xff0c;包括已删除的对话记录以及通过API调用生成的聊天内容。 命令背后的真实动机 值得注意的是&#xff0c;法院发布这一指令并非出于对用户隐私或内容安全的考…

嵌入式学习--江协stm32day5

USART 1. 引脚与接口层 异步引脚&#xff1a; TX&#xff1a;发送数据输出&#xff1b;RX&#xff1a;接收数据输入&#xff1b;SW_RX&#xff1a;单线半双工模式的接收引脚&#xff08;替代 RX&#xff09;。 同步引脚&#xff1a;SCLK&#xff1a;同步模式下的时钟输出&…

使用Fiddler抓包

有时候需要跟踪一些小程序的HTTP请求&#xff0c;但是无法像浏览器一样F12查看请求&#xff0c;因此需要借助其他的工具进行&#xff0c;在这里推荐使用Fiddler 配置 此时检查系统代理已经变成如下配置&#xff1a; 抓包 此时随便打开一个小程序&#xff0c;就可以进行抓包…

python学习打卡day47

DAY 47 注意力热图可视化 昨天代码中注意力热图的部分顺移至今天 知识点回顾&#xff1a; 热力图 作业&#xff1a;对比不同卷积层热图可视化的结果 # 可视化空间注意力热力图&#xff08;显示模型关注的图像区域&#xff09; def visualize_attention_map(model, test_loader,…

MySQL-运维篇

运维篇 日志 错误日志 错误日志是 MySQL 中最重要的日志之一&#xff0c;它记录了当 mysqld 启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息当数据库出现任何故障导致无法正常使用时&#xff0c;建议首先查看此日志。 该日志是默认开启的&am…

Prompt Tuning(提示调优)到底训练优化的什么部位

Prompt Tuning(提示调优)到底训练优化的什么部位 在自然语言处理(NLP)领域,Prompt Tuning(提示调优)是一种轻量级的模型优化技术,其核心目标是通过优化提示(Prompt)来引导预训练语言模型(如GPT、BERT等)更好地完成特定任务,而无需大规模调整模型的主体参数。 一…

基于FPGA的超声波显示水位距离,通过蓝牙传输水位数据到手机,同时支持RAM存储水位数据,读取数据。

基于FPGA的超声波显示水位距离 前言一、整体框架二、代码架构1.超声波测距模块2.蓝牙数据发送模块3.数码管数据切换模块4.数码管驱动模块6.串口驱动7.顶层模块8.RAM ip核 仿真相关截图 前言 随着工业化进程的加速和环境保护意识的提升&#xff0c;对水资源管理和水位监测的需求…

OD 算法题 B卷【水果摊小买卖】

文章目录 水果摊小买卖 水果摊小买卖 小王手里有点闲钱&#xff0c;想做点水果买卖&#xff0c;给出两个数组m, n&#xff0c; m[i]表示第i个水果的成本价&#xff0c;n[i]表示第i个水果能卖出的价格&#xff1b;假如现在有本钱k&#xff0c;试问最后最多能赚多少钱&#xff1…