Windows应用-音视频捕获

news2025/6/7 10:03:29

下载“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.coloradmin.cn/o/2397886.html

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

相关文章

【OCCT+ImGUI系列】012-Geom2d_AxisPlacement

Geom2d_AxisPlacement 教学笔记 一、类概述 Geom2d_AxisPlacement 表示二维几何空间中的一个坐标轴(轴系),由两部分组成: gp_Pnt2d:原点(Location)gp_Dir2d:单位方向向量&#xff…

【C++高并发内存池篇】性能卷王养成记:C++ 定长内存池,让内存分配快到飞起!

📝本篇摘要 在本篇将介绍C定长内存池的概念及实现问题,引入内存池技术,通过实现一个简单的定长内存池部分,体会奥妙所在,进而为之后实现整体的内存池做铺垫! 🏠欢迎拜访🏠&#xff…

mac下通过anaconda安装Python

本次分享mac下通过anaconda安装Python、Jupyter Notebook、R。 anaconda安装 点击👉https://www.anaconda.com/download, 点击Mac系统安装包, 选择Mac芯片:苹果芯片 or intel芯片, 选择苹果芯片图形界面安装&#x…

微软PowerBI考试 PL300-Power BI 入门

Power BI 入门 上篇更新了微软PowerBI考试 PL-300学习指南,今天分享PowerBI入门学习内容。 简介 Microsoft Power BI 是一个完整的报表解决方案,通过开发工具和联机平台提供数据准备、数据可视化、分发和管理。 Power BI 可以从使用单个数据源的简单…

逻辑回归知识点

一、逻辑回归概念 逻辑回归(Logistic Regression)是一种广泛应用于分类问题的统计方法,尤其适用于二分类问题。 注意: 尽管名称中有"回归"二字,但它实际上是一种分类算法。 解决二分类的问题。 API:sklearn.linear_model.Logis…

Ubuntu22.04 安装 CUDA12.8

1.下载CUDA 由于我装完 Ubuntu22.04 后就自动带了最新的显卡驱动,就没有再去配置驱动。 先查看驱动能支持的CUDA最高版本,这里显示可支持到12.8。 nvidia-smi在CUDA的 说明文档 可查看CUDA对应的驱动版本要求。 在 CUDA Toolkit Archive 查找需要的 …

Android的uid~package~pid的关系

UID : Linux 系统级用户标识,Android 中每个应用安装时分配唯一 UID(如 1000)。 Package: Android 应用包名(例如android),一个 UID 可关联多个 Package(共享 UID 场景如android:sharedUserI…

20250530-C#知识:万物之父Object

C#知识:万物之父Object Object类(即object)是所有类的基类,这里面的方法还是需要好好了解一下。 1、Object类 是顶级父类,其他类默认都是Object类的子类(自定义类也会默认继承Object类)可以用O…

多元素纳米颗粒:开启能源催化新纪元

在能源转型的浪潮中,纳米催化剂正成为推动能源技术突破的关键力量。多元素纳米颗粒(Polyelemental Nanoparticles)凭借其独特的元素协同效应,展现出在能源催化领域的巨大潜力。然而,合成这些复杂体系的纳米颗粒面临着诸…

分布式锁优化:使用Lua脚本保证释放锁的原子性问题

分布式锁优化(二):使用Lua脚本保证释放锁的原子性问题 💻黑马视频链接:Lua脚本解决多条命令原子性问题 在上一章节视频实现了一个可用的Redis分布式锁,采用SET NX EX命令实现互斥和过期自动释放机制&…

电脑wifi显示已禁用怎么点都无法启用

一、重启路由器与电脑 有时候,简单的重启可以解决很多小故障。试着先断开电源让路由器休息一会儿再接通;对于电脑,则可选择重启系统看看情况是否有改善。 二、检查驱动程序 无线网卡驱动程序的问题也是导致WiFi无法启用的常见原因之一。我…

【FPGA开发】Ubuntu16.04环境下配置Vivado2018.3—附软件包

文章目录 环境介绍关键步骤记录安装虚拟机及镜像安装vivadolicense导入 环境介绍 vivado:2018.3 虚拟机:vmware 16 pro 镜像:Ubuntu16.04 64位 所有相关软件压缩包: 链接:https://pan.quark.cn/s/fd2730b46b20 提取码…

vue-seamless-scroll 结束从头开始,加延时后滚动

今天遇到一个大屏需求: 1️⃣初始进入页面停留5秒,然后开始滚动 2️⃣最后一条数据出现在最后一行时候暂停5秒,然后返回1️⃣ 依次循环,发现vue-seamless-scroll的方法 ScrollEnd是监测最后一条数据消失在第一行才回调&#xff…

0-EATSA-GNN:基于图节点分类师生机制的边缘感知和两阶段注意力增强图神经网络(code)

code:https://github.com/afofanah/EATSA-GNN. 文章目录 Abstract1. Introduction1.1.动态图场景1.2.EATSA-GNN框架的背景化2. Background2.1.GNN边缘感知挑战2.2.GNN的可解释性问题2.3.EATSA-GNN可解释性3. Related worksAbstract 图神经网络(GNNs)从根本上改变了我们处理和…

配置前端控制器

一、DispatcherServlet 详解 在使用 Spring MVC 框架构建 Web 应用时,DispatcherServlet是整个请求处理流程的核心。本文将深入解析DispatcherServlet的作用、工作原理及其在 Spring MVC 架构中的关键地位。 1.DispatcherServlet 是什么? DispatcherS…

lua注意事项

感觉是lua的一大坑啊,它还不如函数内部就局部变量呢 注意函数等内部,全部给加上local得了

Git的三种合并方式

在 Gitee(码云)中合并分支主要有三种方式:​普通合并(Merge Commit)、压缩合并(Squash Merge)​和变基合并(Rebase Merge)​。每种方式适用于不同的场景,各有…

从零到一:我的技术博客导航(持续更新)

作者:冰茶 最后更新:2025年6月3日 本文收录了我的C#编程学习心得与技术探索,将持续更新 前言 作为一名.NET开发者,C#语言的学习与探索一直是我技术成长的核心路径。本文集整理了我在C#学习过程中的思考与实践,希望能够…

SpringBoot整合Flowable【08】- 前后端如何交互

引子 在第02篇中,我通过 Flowable-UI 绘制了一个简单的绩效流程,并在后续章节中基于这个流程演示了 Flowable 的各种API调用。然而,在实际业务场景中,如果要求前端将用户绘制的流程文件发送给后端再进行解析处理,这种…

【五模型时间序列预测对比】Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN

【五模型时间序列预测对比】Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN 目录 【五模型时间序列预测对比】Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Transformer-LSTM、Transformer、CNN-LSTM、LSTM、…