Dernière activité 1728564236

Windows 中使用 PowerShell 进行录屏的脚本

ryano's Avatar ryano a révisé ce gist 1728564236. Aller à la révision

1 file changed, 1 insertion, 1 deletion

README.md

@@ -4,7 +4,7 @@ Windows 中使用 PowerShell 进行录屏的脚本,只在用户活动的时(
4 4
5 5 ## 准备
6 6
7 - - 安装 `ffmpeg` 用来将截屏的png转换为视频.
7 + - 安装 `ffmpeg` 用来将截屏的png转换为视频. 如果不需要视频只要图片可以不装
8 8
9 9 ## 用法
10 10 1. 用powsershell执行 `screenshot.ps1` 开始截屏生成png文件.

ryano's Avatar ryano a révisé ce gist 1728564190. Aller à la révision

4 files changed, 149 insertions

README.md(fichier créé)

@@ -0,0 +1,15 @@
1 + # Windows录屏脚本
2 +
3 + Windows 中使用 PowerShell 进行录屏的脚本,只在用户活动的时(鼠标点击或移动或敲打键盘)才进行录制
4 +
5 + ## 准备
6 +
7 + - 安装 `ffmpeg` 用来将截屏的png转换为视频.
8 +
9 + ## 用法
10 + 1. 用powsershell执行 `screenshot.ps1` 开始截屏生成png文件.
11 + 2. 停止powershell,执行 `make.cmd` 开始导出视频.
12 + 3. `generate-input-list.py` 可选的python脚本用来重新生成`duration.txt`当你删除了部分png文件时.
13 +
14 + ## 说明
15 + - `duration.txt` 是给`ffmpeg`合成视频时用的时间轴文件,里面指明了每个png图片的播放时长。如果删除了部分png图片,需要使用`generate-input-list.py`来重新生成它

generate-input-list.py(fichier créé)

@@ -0,0 +1,26 @@
1 + import os
2 + from datetime import datetime
3 +
4 + time_format = '%Y%m%d_%H%M%S%f'
5 +
6 + # 获取当前目录下所有的png文件名,无扩展名
7 + png_files = [f.split('.')[0] for f in os.listdir('./shots') if f.endswith('.png')]
8 +
9 + # 解析文件名并排序
10 + sorted_files = sorted(png_files, key=lambda x: datetime.strptime(x, time_format))
11 +
12 + # 计算时间间隔并生成输入文件
13 + with open('./shots/duration.txt', 'w') as f:
14 + for i in range(len(sorted_files)):
15 + current_file = sorted_files[i]
16 + current_time = datetime.strptime(current_file, time_format)
17 +
18 + if i != 0:
19 + prev_file = sorted_files[i-1]
20 + prev_time = datetime.strptime(prev_file, time_format)
21 + duration = (current_time - prev_time).total_seconds()
22 + f.write(f"duration {duration}\n")
23 +
24 + f.write(f"file '{current_file}.png'\n")
25 +
26 + print("输入文件列表已生成为 duration.txt")

make.cmd(fichier créé)

@@ -0,0 +1 @@
1 + ffmpeg -f concat -i ./shots/duration.txt -pix_fmt yuv420p -c:v libx264 -r 5 output.mp4

screenshot.ps1(fichier créé)

@@ -0,0 +1,107 @@
1 + # 定义保存截图的文件夹路径为当前脚本所在目录下的shots文件夹
2 + $folderPath = Join-Path -Path $PSScriptRoot -ChildPath "shots"
3 + if (-not (Test-Path -Path $folderPath)) {
4 + New-Item -ItemType Directory -Path $folderPath
5 + }
6 +
7 + # 导入用户32.dll,用于检测鼠标键盘活动
8 + Add-Type @"
9 + using System;
10 + using System.Runtime.InteropServices;
11 + public class UserActivity {
12 + [DllImport("user32.dll")]
13 + public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
14 +
15 + [StructLayout(LayoutKind.Sequential)]
16 + public struct LASTINPUTINFO {
17 + public uint cbSize;
18 + public uint dwTime;
19 + }
20 + }
21 + "@
22 +
23 + # 检测用户是否活跃
24 + function IsUserActive {
25 + $lastInput = New-Object UserActivity+LASTINPUTINFO
26 + $lastInput.cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf($lastInput)
27 +
28 + if ([UserActivity]::GetLastInputInfo([ref]$lastInput)) {
29 + $idleTime = [Math]::Floor([TimeSpan]::FromMilliseconds([Environment]::TickCount - $lastInput.dwTime).TotalSeconds)
30 + # 如果空闲时间小于5秒,认为用户是活跃的
31 + return ($idleTime -lt 1)
32 + }
33 + return $false
34 + }
35 +
36 + $durationTxt = Join-Path -Path $folderPath -ChildPath "duration.txt"
37 + $fileMatches = if (Test-Path -Path $durationTxt) { (Get-Content -Path $durationTxt -Tail 3 | Select-String -Pattern "^file '(.*\.png)'$").Matches } else { @() }
38 + $script:lastScreenshotFile = if ($fileMatches.Count -gt 0) { $fileMatches[0].Groups[1].Value } else { "" }
39 + # Write-Host "lastScreenshotFile: $lastScreenshotFile"
40 + $script:isFirstRun = $true
41 + $script:lastScreenshotTime = if ($script:lastScreenshotFile -ne "") { [DateTime]::ParseExact($script:lastScreenshotFile.Substring(0, 18), "yyyyMMdd_HHmmssfff", $null) } else { [DateTime]::MinValue }
42 +
43 + # 截屏函数
44 + function TakeScreenshot {
45 + $now = Get-Date
46 + $timestamp = $now.ToString("yyyyMMdd_HHmmssfff")
47 + $filePath = Join-Path -Path $folderPath -ChildPath "$timestamp.png"
48 +
49 + Add-Type -AssemblyName System.Windows.Forms
50 + Add-Type -AssemblyName System.Drawing
51 + $bitmap = New-Object System.Drawing.Bitmap([System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width, [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height)
52 + $graphics = [System.Drawing.Graphics]::FromImage($bitmap)
53 + # Capture the screen
54 + $graphics.CopyFromScreen(0, 0, 0, 0, $bitmap.Size)
55 +
56 + # Draw the cursor
57 + $cursorPosition = [System.Windows.Forms.Cursor]::Position
58 + $cursorRectangle = New-Object System.Drawing.Rectangle($cursorPosition, [System.Drawing.Size]::new(32, 32)) # Adjust size if needed
59 + # [System.Windows.Forms.Cursor]::Current.Draw($graphics, $cursorRectangle)
60 + [System.Windows.Forms.Cursors]::Arrow.Draw($graphics, $cursorRectangle)
61 +
62 + $bitmap.Save($filePath, [System.Drawing.Imaging.ImageFormat]::Png)
63 +
64 + # Add filename to duration.txt
65 + if ($script:lastScreenshotFile -ne "") {
66 + $duration = ([TimeSpan]::FromTicks(($now - $script:lastScreenshotTime).Ticks)).TotalSeconds
67 + $durationStr = "duration {0:F3}" -f $duration
68 + if ($script:isFirstRun) {
69 + $lastDuration = Get-Content -Path $durationTxt -Tail 1 | Select-String -Pattern "^duration [\d\.]+$"
70 + if ($lastDuration) {
71 + # remove last line
72 + $lines = Get-Content -Path $durationTxt
73 + $lines = $lines[0..($lines.Length - 2)]
74 + $lines += $durationStr
75 + $lines | Set-Content -Path $durationTxt
76 + } else {
77 + Add-Content -Path $durationTxt -Value $durationStr
78 + }
79 + $script:isFirstRun = $false
80 + } else {
81 + Add-Content -Path $durationTxt -Value $durationStr
82 + }
83 + }
84 + Add-Content -Path $durationTxt -Value "file '$timestamp.png'"
85 +
86 + Write-Host "Screenshot saved: $timestamp.png"
87 + [console]::beep(1000, 500) # 播放提示音
88 +
89 + $script:lastScreenshotTime = $now
90 + $script:lastScreenshotFile = "$timestamp.png"
91 + }
92 +
93 + # Delay 3 seconds to start
94 + Start-Sleep -Seconds 3
95 +
96 + # 主循环
97 + while ($true) {
98 + try {
99 + if (IsUserActive) {
100 + TakeScreenshot
101 + }
102 + Start-Sleep -Seconds 1
103 + } catch {
104 + Write-Host "An error occurred: $_"
105 + Start-Sleep -Seconds 5 # 出错时等待5秒再继续
106 + }
107 + }
Plus récent Plus ancien