record_screen

RecorderMode, 三种:Video, Steps, Replay.

VideoSourcesViewModel   在ViewCore里面,主要为Captura服务的。视频源ViewModel

VideoWritersViewModel  在ViewCore里面,主要为Captura服务的。视频Writer view model.

SelectedVideoWriter 选中的视频Writer。

IVideoWriterItem里面有个函数返回IVideoFileWriter. 从单独的frame里面创建一个视频,并写入到一个文件里面。

把frame写入到视频里面, 帧实际上是IBitmapFrame

IBitmapFrame是个接口,主要包含时间戳,CopyTo(byte[] Buffer), CopyTo(IntPtr Buffer)

MF media foundation, 微软出的,Vista之后的系统都有。

MfWriter继承自IVideoFileWriter

实际的录制对象在Screna工程里面,

Recorder.cs

函数DoRecord, 里面调用了FrameWriter

_fpsManager?.OnFrame();

如果_fpsManager为null,就停止,否则调用OnFrame函数。

WithPreviewWriter实现接口IVideoFileWriter, 有个函数WriteFrame, 调用MfWriter的WriteFrame函数。

MfWriterProvider : IVideoWriterProvider

SharpAviWriterProvider: IVideoWriterProvider

FFmpegWriterProvider : IVideoWriterProvider

IVideoWriterProvider : IEnumerable<IVideoWriterItem> 

接口里面有个重要函数:ParseCli(string Cli) 返回IVideoWriterItem.

选择是录制全屏,窗口,屏幕,还是区域是在Screna项目里面,VideoSourceProviders目录当中:

1. FullScreenSourceProvider

2. RegionSourceProvider

3. ScreenSourceProvider

4. VideoSourceProvider

5. WindowSourceProvider

如果不想用ffmpeg,可以用Windows自身的media foundation, 需要工程Captura.Windows

在Core项目中OnLoad函数中调用BindVideoSourceProvider(Binder), 在改函数中调用

Binder.BindAsInterfaceAndClass<IVideoSourceProvider, RegionSourceProvider>();

首先在App.xaml.cs中Application_Startup调用静态ServiceProvider.LoadModule(new CoreModule());

再次盗用Kernel.Load(new Binder(Module));

在Base项目中Binder.cs类中调用Load()--》_module.OnLoad(this);

Base项目中ServiceProvider.cs中List<IModule> 添加Module.

选择窗口还是区域等,是在ServiceLocator.cs中,有个ScreenShotViewModel(在ViewCore项目当中)

在ScreenShotModel中,有个函数ScreenshotRegion, 调用IVideoSourcePicker.PickRegion();

在VideoSourcePicker类中,调用RegionPickerWindow.PickRegion, 显示picker.ShowDialog();

 

在RegionSelectorProvider类中定义了readonly Lazy<RegionSelector> _regionSelector;

RegionItem包含IRegionProvider和IPlatformService, IRegionProvider里面有个Rectangle和IVideoItem

RegionSelectorProvider实现IRegionProvider

RegionSelectorProvider有个属性SelectedRegion, 引用的是RegionSelectorViewModel里面的SelectedRegion

IPlatformService用来枚举系统里面所有的屏幕,窗口,光标位置,IImageProvider

RegionProvider实现了IImageProvider接口。

WindowsPlatformServices.cs类中有个函数GetRegionProvider

在RecordingViewModel类中的StartRecording函数中,

录制的时候需要三个东西:

IVideoSourcedProvider 定义窗口还是区域大小等。

VideoWriter,写帧到文件里面

Microphone, 需要录制麦克风?

IAudioPlayer接口只有一个函数Play

AudioPlayer类实现了IAudioPlayer接口。该类中有声音设置和MediaPlayer播放器,用于录制声音。

暂停的时候,调用_audioPlayer.Play(SoundKind.Pause)和RecordingModel.OnPauseExecute();

在Core模块里面设计到RecordingModel, 里面有函数OnPauseExecute,涉及到定时器TimerModel(也在Core项目中)。

调用User32.RegisterHotKey注册热键。如果返回false,已经被别的程序注册了。

AudioSettings,音频设置,比如quality默认为80,这个设置包含在Settings里面

在Application_Startup中var settings = ServiceProvider.Get<Settings>();获取所有的设置。

三个DI模块:

1. CoreModule, Core project

2. ViewCoreModule, ViewCore project

3. MainModule, 主项目

Overlay覆盖层:

1. KeyOverlay   按键覆盖

2. MouseClickOverlay 鼠标覆盖

3. MouseKeyOverlay 

4. ScrollOverlay

5. ImageOverlay

6. MousePointerOverlay

7. TextOverlay

Screna项目中有很多Overlay

MessageProvider里面包含一个ILocalizationProvider,主要显示出错信息,显示异常信息, 显示是或者否等,容易替换。

ServiceName枚举类型

None, ScreenShot, Pause, DesktopScreenShot, ActiveScreenShot, ToggleMouseClicks, ToggleKeystrokes, ScreenShotRegion, ...

Service就是显示ServiceName用的。构造函数有个ServiceName, 

Modifiers, 枚举类型

1. None

2. Alt

3. Ctrl

4. Shift

IHotkeyListener, 接口,里面有个HotkeyReceived事件

HotkeyModel, 快捷键模型, 从Hotkeys.json文件中读出来。形成一个一个的HotkeyModel

然后由HotkeyModel生成Hotkey

Hotkey的IsActive,set的时候该注册的注册,该卸载的卸载

在MainWindow的构造函数里面调用_helper.HotkeySetup.Setup();进行快捷键的注册,从json中读入等动作。

在创建ServiceProvider.Get<MainViewModel>的时候创建HotKeyManager, 而在创建HotKeyManager的时候,因为构造函数里面有

所有的按键事件处理函数在HotKeyManager中,ProcessHotkey(int Id)

再依次调用HotkeyPressed += M => {

foreach (var actor in HotkeyActors)

{

actor.Act(M);

}

HotkeyActor按钮处理对象,由该对象处理按键。

RecordingViewModel构造函数传进来一个RecordingModel

在MainViewModel的Dispose函数里面,把当前的选项保存起来,调用Remember函数实现的。

录制框如何出来的?

1. RestoreVideoSource, 从Settings.Video.Source里面反序列化得到配置参数。

2. 由配置参数得到录制区域大小, RegionSourceProvider.Deserialize函数

3. 设置RegionSelectorProvider的SelectorVisible为true,调用_regionSelector.Value.Show()显示选择框。

4. RegionSelectorProvider实现IRegionProvider接口。

5. 从单例里面获取录制区域的大小,设置RegionSelectorProvider的SelectorVisible属性,控制窗口的显示与否。

6. 先要设置窗口大小,再把visible属性设置为true就可以了。

7. 本来是再MainWindow的构造函数里面实现的,改为按钮控制。

8. 要想显示,需要获取RegionSelectorProvider的对象,在MainModule的OnLoad函数里面绑定了。

9. 录制框出来之后,注册热键

启动的时候在RegionSourceProvider里面设置SelectorVisible = true;的,然后显示框。

Settings.GetOutputPath()最后生成的mp4的目录

VideoSourcesViewModel是单例的,里面包含

public IEnumerable<IVideoSourceProvider> VideoSources { get; }

IVideoSourceProvider

RegionSourceProvider继承自VideoSourceProviderBase

VideoSourceProviderBase实现IVideoSourceProvider接口

而RegionSourceProvider里面包含_regionProvider.是IRegionProvider接口类型

而RegionSelectorProvider实现IRegionProvider接口。

切换录课方框是通过VideoSourcesViewModel里面的VideoSources获取唯一的选项,然后获取

RegionSourceProvider, 进一步获取RegionSourceProvider, 再调用RegionSourceProvider的OnUnselect()函数即可。

通过单例RecordingViewModel来获取RecordingModel,进一步获取视频文件名称。

RecordingModel是单例

overlay相关的:

TextOverlays, ImageOverlays,都实现IOverlay接口, 在Scre项目中。

RecordingModel里面有GetOverlays或者overlay的方法。该类中还有一个方法就是GetImageProviderWithOverlays

--》这个方法同时又被SetupVideoRecorder方法调用,

--》在StartRecording方法中调用

在开始录制时,需要建立VideoRecorder,此时会调用GetImageProviderWithOverlays, 接着调用GetOverlays

登陆时,获取成员信息,如果满足,不铺设overlay,如果不满足,则铺设overlay

需要制定一个接口,根据外部条件决定是否添加overlay

RegionProvider实现IImageProvider接口,提供图片,

在设置里添加overlay,会调用OverlayListViewModel类的OnAddExecute函数,但是这个应该只在设置里起到作用?

图片是CustomImageOverlay, 看看是如何添加到

图片都是OverlayedImageProvider提供的, 它的构造函数里面有个IOverlay[] Overlays, 这个是由GetOverlays函数提供

这个函数里面由一系列的yield return

登录时,根据条件在Settings.ImageOverlays添加图片即可。

只要构造一个ImageOverlays,然后把他添加到Settings.ImageOverlays里面即可。

ImageOverlays里面包含CustomImageOverlaySettings : ImageOverlaySettings

里面重要的两个参数一个时Source,一个时Resize, ResizeWidth, ResizeHeight, 透明度

CustomImageOverlaysViewModel : OverlayListViewModel, 而且是单例很好,

应该是调整好大小,准备录制时定制水印大小,因为要调整位置。

CustomImageOverlay有函数Draw和GetPosition

最后往每一帧视频里面写的时候,需要

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
解释下这段代码record_list = [] screen_width = 1024 screen_height = 768 interest_time_start_offset = 1200 interest_time_duration = 3000 while row_index <= fix_record.max_row: row_start = fix_record[row_index][0].value if row_start is None: break if row_start.startswith("trail"): record_list.clear() record_list.append(fix_record[row_index][0].value) record_list.append(images_info[image_index + 1][0].value) img_width = float(images_info[image_index + 1][1].value) img_height = float(images_info[image_index + 1][2].value) object1_xmin = float(images_info[image_index + 1][3].value) / img_width * screen_width object1_ymin = float(images_info[image_index + 1][4].value) / img_height * screen_height object1_xmax = float(images_info[image_index + 1][5].value) / img_width * screen_width object1_ymax = float(images_info[image_index + 1][6].value) / img_height * screen_height if images_info[image_index + 1][7].value is None: object2_xmin = -1.0 object2_ymin = -1.0 object2_xmax = -1.0 object2_ymax = -1.0 else: object2_xmin = float(images_info[image_index + 1][7].value) / img_width * screen_width object2_ymin = float(images_info[image_index + 1][8].value) / img_height * screen_height object2_xmax = float(images_info[image_index + 1][9].value) / img_width * screen_width object2_ymax = float(images_info[image_index + 1][10].value) / img_height * screen_height image_index += 1 row_index += 1 start_time = -1 end_time = -1 interest_duration_start = -1 interest_duration_end = -1 object1_attention_time = -1 object2_attention_time = -1 object1_times = 0 object2_times = 0
最新发布
06-07

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

novodexx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值