Windows應用-音視頻捕獲

下載“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…