录屏程序之添加实时音频流

Viewer

发布日期: 2018-12-18 09:28:00 浏览量: 1819
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

背景

之前自己在视频教程的时候,就从网上找了个破解版的录屏软件来录制视频。虽然是破解版的,但是破解不完全,因为录制的视频播放到十几分钟之后,就开始显示未注册版本的字样在屏幕中,所以很是碍眼啊。

后来,自己细想之后,觉得自己完全可以写一个专属的录屏软件,功能不用太复杂,就支持画面录制和声音录制,存储为视频文件就好。是的,后来我开发出来了。所以,才有了这篇分享文章给大家,来总结下开发心得,同时也向大家剖析下这个程序的实现过程和原理。

这篇文档分成上、下两个部分,上部分主要讲解实现实时录制屏幕画面,保存为视频文件。下部分主要讲解实现实时录制声音,并将声音添加到视频文件中。现在,本文是下部分,讲解实时录音,添加音频流过程。

实现原理

有了上半部分创建视频流并为视频流添加画面帧的基础,向添加音频流就不难理解了。上半部分的关键就是在于将一张张屏幕截图添加在视频流里,形成视频。那么,音频也是同样的原理,我们将一段段音频数据添加到音频流中。其中,实时获取音频流是关键。还好,本站上之前有人写的 “编程实现录音及保存为WAV音频文件” 这篇文章,详细介绍了获取音频数据的过程和原理,大家可以参考,在此就不进行介绍了。现在,就讲讲获取到音频数据之后,怎么添加到音频流中。实现的原理是:

  • 首先,初始化 AVIFile 库,因为下面要使用到该库的函数

  • 然后,判断是否创建音频流,若没有,则开始创建音频流

    • 首先,设置音频流信息 AVISTREAMINFO,设置流类型为音频流、声道数、音频样本频率、缓存大小、样本数等。再按照设置的音频流格式调用 AVIFileCreateStream 函数创建音频流,并获取音频流接口

    • 成功获取音频流接口之后,开始按照波形声音格式 WAVEFORMATEX 设置音频流格式

  • 调用 AVIStreamWrite 函数将音频数据写入到音频流中,并更新 HAVI 结构体中记录音频下一帧的成员

  • 最后,关闭 AVIFile 库

编码实现

  1. // *************** 添加音频帧 ****************
  2. // hAvi句柄
  3. // lpWaveData 音频数据
  4. // dwWaveDataSize 音频数据大小
  5. HRESULT AddWaveFrame(PHAVI pAvi, PVOID lpWaveData, DWORD dwWaveDataSize)
  6. {
  7. // AVI文件环境初始化
  8. ::AVIFileInit();
  9. if (NULL == lpWaveData)
  10. {
  11. return S_OK;
  12. }
  13. // 创建音频流
  14. if (NULL == pAvi->aStream)
  15. {
  16. // 设置音频流信息
  17. AVISTREAMINFO aviStreamInfo = { 0 };
  18. ::RtlZeroMemory(&aviStreamInfo, sizeof(AVISTREAMINFO));
  19. // 流类型
  20. aviStreamInfo.fccType = streamtypeAUDIO;
  21. // 编码器
  22. aviStreamInfo.fccHandler = NULL;
  23. // 声道数
  24. aviStreamInfo.dwScale = pAvi->waveFormatEx.nChannels;
  25. // Hz
  26. aviStreamInfo.dwRate = pAvi->waveFormatEx.nSamplesPerSec;
  27. // 缓存大小
  28. aviStreamInfo.dwSuggestedBufferSize = BUFFERLENGTH;
  29. aviStreamInfo.dwSampleSize = 1;
  30. // 创建音频流
  31. HRESULT hr = ::AVIFileCreateStream(pAvi->pAviFile, &pAvi->aStream, &aviStreamInfo);
  32. if (AVIERR_OK != hr)
  33. {
  34. ShowError("AVIFileCreateStream");
  35. return hr;
  36. }
  37. // 设置音频流格式
  38. hr = ::AVIStreamSetFormat(pAvi->aStream, 0, &pAvi->waveFormatEx, sizeof(WAVEFORMATEX));
  39. if (AVIERR_OK != hr)
  40. {
  41. ShowError("AVIStreamSetFormat");
  42. return hr;
  43. }
  44. }
  45. // 添加到音频流
  46. HRESULT hr = ::AVIStreamWrite(pAvi->aStream,
  47. pAvi->dwNextWaveFrame,
  48. 1,
  49. lpWaveData,
  50. dwWaveDataSize,
  51. AVIIF_KEYFRAME,
  52. NULL,
  53. NULL);
  54. if (AVIERR_OK != hr)
  55. {
  56. ShowError("AVIStreamWrite");
  57. return hr;
  58. }
  59. pAvi->dwNextWaveFrame++;
  60. return S_OK;
  61. }

程序测试

我们直接运行程序,开始录屏,等待一段时间,结束录屏。这是,便生成了一个视频文件。我们打开视频文件,成功播放刚才的录制画面和声音。所以,录屏程序录屏和录音功能成功实现。

总结

这个程序总体上来说,不算复杂。如果你仍觉得比较难理解的话,建议你把这个程序的功能先拆分实现。先实现实时录音功能,再实现实时录屏功能,最后将录音和录屏结合在一起,这样理解起来会比较深刻。

参考

参考自《Windows黑客编程技术详解》一书

上传的附件 cloud_download ScreenRecord_AddSound_Test.7z ( 149.92kb, 15次下载 )

发送私信

如果没有为想要的东西努力,就别为自己失去的东西哭泣

16
文章数
16
评论数
最近文章
eject