当前位置: 首页 > news >正文

视频、音频录制

1,项目介绍。

实现全屏录屏选择区域录屏摄像头录像麦克风录音主板音频录音截屏画板的自由组合。并通过FFmpeg完成音频与视频的合并。

功能界面
在这里插入图片描述
画板画笔

在这里插入图片描述

参考的项目

https://github.com/yangjinming1062/RecordWin

本项目是在此项目的基础上修复了部分bug,并增加了屏幕区域录屏,与主板音频录音功能。

2,知识点总结

2.1,热键注册。

WPF中进行热键注册需要添加钩子,用以监视热键输入。

public IntPtr winHandle;
private HwndSource hWndSource;
private void Window_Loaded(object sender, RoutedEventArgs e)
{//获取窗口句柄winHandle = new WindowInteropHelper(this).Handle;//在Win32窗口呈现wpf内容hWndSource = HwndSource.FromHwnd(winHandle);GoToScreenTopMiddle();SetHotKey(true);}private void SetHotKey(bool Add){if (Add){hWndSource.AddHook(MainWindowProc);HotKeyBF = HotKey.GlobalAddAtom($"{SettingHelp.Settings.播放暂停.Item1}-{Enum.GetName(typeof(System.Windows.Forms.Keys), SettingHelp.Settings.播放暂停.Item2)}");HotKeyTZ = HotKey.GlobalAddAtom($"{SettingHelp.Settings.停止关闭.Item1}-{Enum.GetName(typeof(System.Windows.Forms.Keys), SettingHelp.Settings.停止关闭.Item2)}");HotKeyHB = HotKey.GlobalAddAtom($"{SettingHelp.Settings.开关画笔.Item1}-{Enum.GetName(typeof(System.Windows.Forms.Keys), SettingHelp.Settings.开关画笔.Item2)}");HotKey.RegisterHotKey(winHandle, HotKeyBF, SettingHelp.Settings.播放暂停.Item1, SettingHelp.Settings.播放暂停.Item2);HotKey.RegisterHotKey(winHandle, HotKeyTZ, SettingHelp.Settings.停止关闭.Item1, SettingHelp.Settings.停止关闭.Item2);HotKey.RegisterHotKey(winHandle, HotKeyHB, SettingHelp.Settings.开关画笔.Item1, SettingHelp.Settings.开关画笔.Item2);}else//暂时没起作用,todo{hWndSource.RemoveHook(MainWindowProc);HotKey.GlobalDeleteAtom((short)HotKeyBF);HotKey.GlobalDeleteAtom((short)HotKeyTZ);HotKey.GlobalDeleteAtom((short)HotKeyHB);HotKey.UnregisterHotKey(winHandle, HotKeyBF);HotKey.UnregisterHotKey(winHandle, HotKeyTZ);HotKey.UnregisterHotKey(winHandle, HotKeyHB);}}private IntPtr MainWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled){switch (msg){case HotKey.WM_HOTKEY:{int sid = wParam.ToInt32();if (Visibility == Visibility.Visible){if (!SettingPop.IsOpen){if (sid == HotKeyBF){if (btBegin.Visibility == Visibility.Visible)btBegin_Click(null, null);elsebtParse_Click(null, null);}else if (sid == HotKeyTZ){if (btStop.Visibility == Visibility.Visible)btStop_Click(null, null);elseBtClose_Click(null, null);}}if (sid == HotKeyHB){btPen.IsChecked = !btPen.IsChecked;OpenDraweWin();}}handled = true;break;}}return IntPtr.Zero;}

外部函数

 public class HotKey{/// <summary> /// 如果函数执行成功,返回值不为0。 /// 如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。.NET方法:Marshal.GetLastWin32Error() /// </summary> /// <param name="hWnd">要定义热键的窗口的句柄</param> /// <param name="id">定义热键ID(不能与其它ID重复) </param> /// <param name="fsModifiers">标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效</param> /// <param name="vk">定义热键的内容,WinForm中可以使用Keys枚举转换, /// WPF中Key枚举是不正确的,应该使用System.Windows.Forms.Keys枚举,或者自定义正确的枚举或int常量</param> [DllImport("user32.dll", SetLastError = true)]public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, int vk);/// <summary> /// 取消注册热键 /// </summary> /// <param name="hWnd">要取消热键的窗口的句柄</param> /// <param name="id">要取消热键的ID</param> [DllImport("user32.dll", SetLastError = true)]public static extern bool UnregisterHotKey(IntPtr hWnd, int id);/// <summary> /// 向全局原子表添加一个字符串,并返回这个字符串的唯一标识符,成功则返回值为新创建的原子ID,失败返回0 /// </summary> [DllImport("kernel32", SetLastError = true)]public static extern short GlobalAddAtom(string lpString);[DllImport("kernel32", SetLastError = true)]public static extern short GlobalDeleteAtom(short nAtom);/// <summary> /// 定义了辅助键的名称(将数字转变为字符以便于记忆,也可去除此枚举而直接使用数值) /// </summary> [Flags()]public enum KeyModifiers{None = 0,Alt = 1,Ctrl = 2,Shift = 4,WindowsKey = 8}/// <summary> /// 热键的对应的消息ID /// </summary> public const int WM_HOTKEY = 0x312;}
2. 2,两种透明。

根据实际需要可以定义两种透明,一种是真透明Transparent,一种是假透明#01000000

 <Color x:Key="FakeTransparentColor" >#01000000</Color><Color x:Key="TrueTransparentColor" >Transparent</Color>
 Background = Application.Current.Resources[enable ? "FakeTransparent" : "TrueTransparent"] as Brush;

在窗口定义为接受透明时:AllowsTransparency="True",采用真透明背景的窗体A,覆盖在应用B上时,应用B的控件可透过窗体A被操作。采用假透明背景的窗体A,覆盖在应用B上时,应用B的控件不能透过窗体A被操作。

2. 3,音视频合并。

音视频的合并一般以命令的形式调用软件FFmpeg完成。

下载FFmpeg软件

常用语法:

  1. ‌直接合并(视频流复制+音频转码)

    若需保持视频无损且兼容MP4容器,建议将WAV转码为AAC:

ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -strict experimental output.mp4

​ 参数说明:

  • -c:v copy:复制视频流不重新编码

  • -c:a aac:将WAV音频转码为MP4支持的AAC格式

  • -strict experimental:早期版本需此参数支持AAC‌

  1. 强制替换原视频音频轨道

若原视频已含音频需替换,可指定映射关系:

ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4

参数说明

  • -map 0:v:0:选择第一个输入文件(video.mp4)的视频流
  • -map 1:a:0:选择第二个输入文件(audio.wav)的音频流‌
  1. 无损合并(需视频无音频)

若视频本身无音频轨道,可直接复制流:

ffmpeg -i video.mp4 -i audio.wav -c copy output.mkv

注意:需改用MKV容器以支持PCM音频流‌。

  1. 示例:

    将视频1.mp4与音频1.wav合并为output.mkv
    在这里插入图片描述

2. 4,自定义动画。
public class CornerRadiusAnimation : AnimationTimeline{static CornerRadiusAnimation(){FromProperty = DependencyProperty.Register("From", typeof(CornerRadius), typeof(CornerRadius));ToProperty = DependencyProperty.Register("To", typeof(CornerRadius), typeof(CornerRadius));}private bool _fromSetted;private bool _toSetted;public static readonly DependencyProperty FromProperty;public CornerRadius From{get => (CornerRadius)GetValue(FromProperty);set{SetValue(FromProperty, value);_fromSetted = true;}}public static readonly DependencyProperty ToProperty;public CornerRadius To{get => (CornerRadius)GetValue(ToProperty);set{SetValue(ToProperty, value);_toSetted = true;}}public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock){var fromVal = _fromSetted ? (CornerRadius)GetValue(FromProperty) : (CornerRadius)defaultOriginValue;var toVal = _toSetted ? (CornerRadius)GetValue(ToProperty) : (CornerRadius)defaultDestinationValue;if (animationClock.CurrentProgress != null)return new CornerRadius(animationClock.CurrentProgress.Value * (toVal.TopLeft - fromVal.TopLeft) + fromVal.TopLeft,animationClock.CurrentProgress.Value * (toVal.TopRight - fromVal.TopRight) + fromVal.TopRight,animationClock.CurrentProgress.Value * (toVal.BottomRight - fromVal.BottomRight) + fromVal.BottomRight,animationClock.CurrentProgress.Value * (toVal.BottomLeft - fromVal.BottomLeft) + fromVal.BottomLeft);return new CornerRadius();}protected override Freezable CreateInstanceCore() => new CornerRadiusAnimation();public override Type TargetPropertyType => typeof(CornerRadius);}
2.5,注意事项

不同目标框架的.NetFramework,编译后的.dll不一定相同,例如使用.NetFramerwork4.6.1将生成大量系统自带的.dll

如下:面对同一个解决方案

.NetFramerwork4.7编译清单。
在这里插入图片描述

.NetFramerwork4.6.1编译清单

在这里插入图片描述

3,项目链接

https://download.csdn.net/download/lingxiao16888/91461603

http://www.lryc.cn/news/597546.html

相关文章:

  • 使用Docker搭建SearXNG搜索引擎
  • 从0开始学习R语言--Day55--弹性网络
  • DIOR-ViT:用于病理图像癌症分类的差分序数学习视觉Transformer|文献速递-医学影像算法文献分享
  • 9、STM32的启动过程
  • VSCODE 禁用git 功能
  • Deep learning--模型压缩的五种方法
  • DenseNet详解,附模型代码(pytorch)
  • 扫描电镜与透射电镜联用表征形貌与元素组成-测试GO
  • 【OD机试】数列构造
  • 智能Agent场景实战指南 Day 19:Agent工具使用与API调用
  • 网安-JWT
  • 1、黑马点评复盘(短信登录-Session或Redis实现)
  • BUUCTF(web)部分题解
  • Redis 的事务机制是怎样的?
  • 模仿学习(Imitation Learning, IL)和监督学习(Supervised Learning, SL)区别
  • Python--Tkinter--标准 GUI 工具包
  • STL学习(?函数对象,谓词,内建函数对象)
  • Hexo - 免费搭建个人博客05 - 更新个人博客
  • DAY 22 复习日
  • 【提示词技巧】高级提示方法与框架
  • 第七章 Pytorch构建模型详解【构建CIFAR10模型结构】
  • 【WRF】根据自动安装脚本安装 WRF / WRF-CHEM等
  • Google Chrome V8< 14.0.221 类型混淆漏洞
  • linux中如何清除history命令
  • IAR Embedded Workbench for ARM 8.1 安装教程
  • 有没有能读懂PDF里手写批注的工具?
  • C# 值类型与引用类型的储存方式_堆栈_
  • 基于Kafka实现简单的延时队列
  • 【JVM】从 JVM 整体说明 JVM 运行的完整流程
  • C#与WPF使用mvvm简单案例点击按钮触发弹窗