☰
基于Windows任务计划和FFmpeg的自动化录屏托管方案
2026/10/16 9:42:56 网站建设 项目流程

当业务方提出“把每月的线上培训录屏自动归档,并生成一个可供内部访问的链接”时,最容易想到的方案是找一个人手动操作:到点开录屏软件、结束保存、上传共享盘、粘贴链接。这个流程初期没有问题,但当录制频率变成每周固定几次,或者录制时间在下班后、凌晨时,人力成本立刻暴露出来。更麻烦的是,手动操作一定会出现漏录、错录、文件名混乱、覆盖旧文件这些问题,最终导致事后找不回关键素材。

本文要整理的,是一套基于 Windows 任务计划程序 + FFmpeg 命令行录屏 + 静态目录托管的自动化“托管录屏”方案。这套方案可以做到:到点自动开始录屏,录制结束自动保存为带时间戳的文件,并同步到 Web 静态目录中,让内部人员通过 HTTP 链接直接观看。全程无人值守,适合月度固定培训、每周例会录制、服务器远程演示记录等场景。

整体内容包含:方案架构、环境准备、FFmpeg 录屏命令拆解、PowerShell 封装脚本、目录托管策略、计划任务配置、常见报错排查,以及生产环境使用时的最佳实践。文章里的代码都按可复制标准给出,读者按顺序操作即可复现整套流程。

1. 方案背景与适用场景

1.1 什么是“托管录屏”

托管录屏,可以拆成两个动作理解:

  • 录制:通过命令行或脚本启动录屏软件,将屏幕内容编码为视频文件。
  • 托管:将生成的视频文件统一移动到某个 Web 服务器或共享目录中,让用户可以用浏览器直接访问。

传统录屏软件通常提供“手动录制”和“定时录制”两种模式,但定时录制往往依赖软件本身常驻后台,一旦软件被误退出、弹窗抢占焦点、网络中断,定时任务就会静默失败。更常见的是,录屏软件免费版有录制时长限制,根本撑不住两小时的培训课程。

基于 FFmpeg 的托管录屏方案,将录制动作从 GUI 软件中剥离出来,变成一个命令行任务。这样就能交给 Windows 任务计划程序、Linux cron、Jenkins 这类标准调度工具来管理。录制命令结束后,脚本继续完成文件重命名、转码、移动、归档等一系列动作。

1.2 为什么需要自动托管录屏

最常见的业务驱动场景有下面几类:

  • 月度例行培训:每个月固定时间开展内部技术分享,需要完整记录讲师屏幕操作。
  • 远程演示存档:项目组做客户演示时,需要留存操作过程,用于后续复盘或录制操作手册。
  • 无人值守录制:员工下班后服务器执行批量任务,需要把执行过程录下来,第二天检查。
  • 多机器集中录制:多台演示机都要录屏,手动操作很难保证所有机器同时启动。

这些场景共同的特点是:开始时间固定、持续时间长、结束时间不确定、事后需要快速访问。手动操作很难满足以上全部要求,而“任务计划 + 命令行录屏 + Web 目录”的组合能稳定覆盖。

1.3 方案选型说明

市面上录制方案不少,这里做一轮简单对比:

方案优点缺点
商业录屏软件界面友好,功能全面费用高,定时能力弱,难以批量管理
OBS Studio免费开源,支持推流录制配置复杂,自动化依赖第三方插件
FFmpeg 命令录制纯命令行,轻量,易集成无 GUI,需要学习参数
Windows 自带 Xbox 录屏无需安装限制多,不适合长时间录制

本文选择 FFmpeg,因为它在服务器和开发机上都容易部署,录制命令可以自由组合,配合 PowerShell 脚本和 Windows 任务计划程序,几乎不需要额外的付费组件。这也是目前自动化录屏方案中性价比最高的做法。

2. 整体架构与工作流程

2.1 架构组成

整套方案由四层构成:

  • 调度层:Windows 任务计划程序按计划触发录制任务。
  • 脚本层:PowerShell 脚本负责调用 FFmpeg、生成文件名、判断录制时长。
  • 录制层:FFmpeg 捕获屏幕画面并编码为 H.264 视频。
  • 托管层:Nginx 或 IIS 将指定目录暴露为静态站点,提供视频访问链接。

为了便于理解,这里用一个 ASCII 简图展示数据流向:

任务计划程序 │ 每天 09:00 触发 ▼ PowerShell 脚本 │ 调用 ffmpeg 命令 ▼ FFmpeg 录屏进程 │ 输出 mp4 文件 ▼ 录制文件目录 │ 脚本移动到 Web 根目录 ▼ Nginx / IIS 静态目录 │ 用户访问 ▼ 内部浏览器直接播放

2.2 核心流程

一次完整的托管录屏流程如下:

  1. 任务计划程序在指定时间启动 PowerShell 脚本。
  2. 脚本检查 FFmpeg 进程是否已存在,避免重复录制。
  3. 脚本根据规则生成视频文件名,例如training_20250830_0900.mp4。
  4. 脚本启动 FFmpeg,录制主屏幕。
  5. 到达预设时长或检测到手动停止条件后,脚本结束 FFmpeg 进程。
  6. 脚本将生成的视频移动到 Web 根目录。
  7. 脚本生成一个简单的播放页面或输出视频直链。
  8. 运维人员检查日志文件,确认录制成功。

2.3 为什么不用现成的录屏 API

有些开发者会问:Windows 不是有 Win32 API 可以枚举窗口、抓取屏幕吗?我用 C# 写一个录屏程序不是更灵活吗?

从技术难度和稳定性角度看,直接调用 GDI 或 DXGI 抓屏再编码,需要处理分辨率变化、显示器缩放、编码器选择、音视频同步等多个复杂问题。而 FFmpeg 的gdigrab设备已经把这些底层问题封装好了,一条命令就能完成屏幕采集和 H.264 编码。对于“定时录屏 + 自动归档”这个需求来说,FFmpeg 是投入产出比最高的方案。

3. 环境准备与版本说明

3.1 环境清单

本文示例以 Windows Server 2019 / Windows 10 22H2 为运行环境,具体配置如下:

  • 操作系统:Windows 10 或 Windows Server 2019 及以上版本
  • 录制工具:FFmpeg 6.0 及以上版本
  • 脚本环境:Windows PowerShell 5.1
  • 调度工具:Windows 任务计划程序
  • Web 托管:Nginx 1.24 或 IIS 10
  • 浏览器访问端:Chrome、Edge、Firefox 任意一种

如果你的服务器是 Windows Server Core 或 Linux,需要根据实际条件调整录制设备。Windows 桌面版使用gdigrab录屏,Linux 桌面版使用x11grab,macOS 使用avfoundation。本文以 Windows 平台为主进行演示。

3.2 FFmpeg 安装与验证

FFmpeg 是一个开源的多媒体处理工具,提供命令行接口,可以从官方网站下载 Windows 构建版本。安装步骤较为简单,一种是直接解压到本地目录,另一种是下载已编译的 EXE 单文件版本。

这里说明一个比较规范的做法:

首先下载 FFmpeg 压缩包,解压到C:\Tools\ffmpeg目录。解压后的目录结构大致如下:

C:\Tools\ffmpeg ├── bin │ ├── ffmpeg.exe │ ├── ffplay.exe │ └── ffprobe.exe ├── doc └── LICENSE

为了让命令行可以直接使用ffmpeg命令,需要将C:\Tools\ffmpeg\bin加入系统环境变量 Path。

操作路径为:“此电脑” → “属性” → “高级系统设置” → “环境变量” → 在 “系统变量” 中找到Path→ “编辑” → “新建” → 输入C:\Tools\ffmpeg\bin→ 保存。

配置完成后,打开新的 PowerShell 窗口,输入以下命令验证:

ffmpeg -version

正常输出应包含 ffmpeg 版本号、编译配置、可用的库信息。例如:

ffmpeg version 6.0-full_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developers

如果出现“无法识别 ffmpeg 命令”的提示,通常是 Path 环境变量未生效或路径配置错误。此时可以重启命令行窗口,或直接在 PowerShell 中重新加载环境变量:

$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")

3.3 创建基础目录结构

在存放脚本前,先在服务器上规划好目录。个人建议按照下面的结构组织,方便日志、脚本、视频和 Web 根目录分离:

D:\RecordTask ├── scripts │ └── record-screen.ps1 ├── logs │ └── record-20250830.log ├── temp │ └── (临时录制文件) └── wwwroot └── videos └── training_20250830_0900.mp4

目录职责如下:

  • D:\RecordTask\scripts:存放 PowerShell 脚本和配置文件。
  • D:\RecordTask\logs:存放每次录制任务的日志。
  • D:\RecordTask\temp:FFmpeg 输出临时文件,录制结束后再移动。
  • D:\RecordTask\wwwroot:Web 站点根目录,Nginx 直接指向这里。
  • D:\RecordTask\wwwroot\videos:视频文件最终存放目录。

在 PowerShell 中执行以下命令批量创建:

New-Item -ItemType Directory -Force -Path "D:\RecordTask\scripts" | Out-Null New-Item -ItemType Directory -Force -Path "D:\RecordTask\logs" | Out-Null New-Item -ItemType Directory -Force -Path "D:\RecordTask\temp" | Out-Null New-Item -ItemType Directory -Force -Path "D:\RecordTask\wwwroot\videos" | Out-Null

-Force参数的作用是目录存在时不报错,不存在时自动创建。Out-Null用来隐藏命令成功输出的提示信息。

4. FFmpeg 录屏命令核心拆解

4.1 最简单的录屏命令

在正式编写托管脚本前,先直接执行一条 FFmpeg 录屏命令,验证本机录制能力。假设当前屏幕分辨率为 1920x1080,录制 10 秒测试视频,命令如下:

ffmpeg -f gdigrab -framerate 30 -video_size 1920x1080 -offset_x 0 -offset_y 0 -i desktop -c:v libx264 -preset veryfast -pix_fmt yuv420p -t 10 D:\RecordTask\temp\test.mp4

参数含义如下:

  • -f gdigrab:指定输入设备为 GDI 屏幕抓取,这是 Windows 平台 FFmpeg 的桌面录制设备。
  • -framerate 30:录制帧率,即每秒采集 30 帧画面。
  • -video_size 1920x1080:录制区域尺寸,应和实际屏幕分辨率保持一致。
  • -offset_x 0 -offset_y 0:录制区域左上角坐标,0 表示从屏幕左上角开始。
  • -i desktop:输入源为整个桌面。
  • -c:v libx264:视频编码器使用 H.264,兼容性和压缩率都比较好。
  • -preset veryfast:编码速度优先,降低 CPU 占用,适合长时间录制。
  • -pix_fmt yuv420p:像素格式设为 yuv420p,保证视频可以在浏览器和播放器中正常解码。
  • -t 10:录制时长为 10 秒。
  • 最后一个路径参数:输出文件路径。

这条命令的核心逻辑是:从桌面采集原始画面,通过 libx264 编码器压缩成 H.264 视频流,最后封装到 MP4 容器中。

执行后,如果一切正常,终端会滚动输出编码进度信息。结束后检查D:\RecordTask\temp\test.mp4是否生成。

4.2 只录制指定窗口或区域

实际场景中,往往只需要录制某个应用程序窗口,而不是整个桌面。FFmpeg 的gdigrab设备支持-i title方式按窗口标题录制。

例如录制标题为“计算器”的窗口:

ffmpeg -f gdigrab -framerate 30 -i title="计算器" -c:v libx264 -preset veryfast -pix_fmt yuv420p D:\RecordTask\temp\calc.mp4

这里把-i desktop换成了-i title="计算器",FFmpeg 会自动捕获该窗口的位置和尺寸,无需手动指定-video_size。

不过按窗口标题录制有一个明显的短板:如果窗口标题发生改变,录制就会立即报错退出。例如浏览器窗口标题会跟随当前标签页变化,Office 文档标题也会变。因此,如果是长时间无人值守录制,更推荐固定录制整个屏幕,或者通过录制区域参数固定一块坐标范围。

指定区域录制的命令如下:

ffmpeg -f gdigrab -framerate 30 -video_size 1280x720 -offset_x 320 -offset_y 180 -i desktop -c:v libx264 -preset veryfast -pix_fmt yuv420p D:\RecordTask\temp\area.mp4

该命令表示从屏幕坐标(320, 180)开始,向右下截取1280x720的区域进行录制。这种方式适合录制某个固定的软件面板。

4.3 声音录制与音视频同步

屏幕画面录制只是第一步,培训录屏还需要收录麦克风声音或系统声音。这是最容易遗漏的环节。

先看一个同时录制桌面和麦克风声音的命令:

ffmpeg -f gdigrab -framerate 30 -i desktop -f dshow -i audio="Microphone Array" -c:v libx264 -preset veryfast -pix_fmt yuv420p -c:a aac -b:a 128k D:\RecordTask\temp\record.mp4

参数新增部分解释如下:

  • -f dshow:Windows 平台通过 DirectShow 采集音频设备。
  • -i audio="Microphone Array":指定音频输入设备名称,需要根据实际设备名修改。
  • -c:a aac:音频编码器使用 AAC,这是流媒体播放的通用格式。
  • -b:a 128k:音频码率设置为 128kbps,适合人声录制。

如果只录制系统内部播放的声音,需要安装虚拟音频设备,例如 VB-Audio Virtual Cable。启用后,把系统默认播放设备切换为虚拟声卡,再从 FFmpeg 端捕获该设备。

设备名称不确定时,可以先列出 Windows 所有音频输入设备:

ffmpeg -list_devices true -f dshow -i dummy

执行后会输出可用的音频设备列表,从中挑选正确的设备名称填入命令。

4.4 输出文件规范与时间戳

无人值守录屏生成的文件必须具有可读性。建议文件名遵循统一规则:场景标识_日期_开始时间.mp4。

PowerShell 中可通过以下方式生成时间戳:

$timestamp = Get-Date -Format "yyyyMMdd_HHmmss" $videoName = "training_$timestamp.mp4" $tempPath = "D:\RecordTask\temp\$videoName"

Get-Date -Format "yyyyMMdd_HHmmss"将当前时间格式化为20250830_090000这样的字符串。这样生成的文件名类似于training_20250830_090000.mp4,一看就知道是哪一天、哪一场培训录制的。

除了文件名,录制日志也建议带上时间戳。日志内容至少包含任务开始时间、任务结束时间、FFmpeg 退出码、输出文件路径和文件大小。

5. 编写 PowerShell 托管脚本

5.1 脚本设计目标

将手工执行 FFmpeg 命令的过程封装成 PowerShell 脚本,需要实现以下几件事:

  • 接收任务参数:录制时长、场景标识、输出目录。
  • 检查 FFmpeg 是否可用。
  • 避免任务重复运行。
  • 记录日志。
  • 执行录制命令,并在结束时判断文件是否生成。
  • 将文件移动到 Web 目录。
  • 输出本次录制的访问链接。

脚本会自动处理这些步骤,无需人工干预。

5.2 完整脚本参考

以下是一个面向实际部署的 PowerShell 脚本。将内容保存为D:\RecordTask\scripts\record-screen.ps1,使用 UTF-8 with BOM 编码保存,避免中文字符乱码。

param( [int]$DurationMinutes = 60, [string]$SceneName = "training", [string]$OutputRoot = "D:\RecordTask\wwwroot\videos", [string]$TempRoot = "D:\RecordTask\temp" ) $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" $logDir = "D:\RecordTask\logs" $logFile = Join-Path $logDir "record-$timestamp.log" function Write-Log { param([string]$Message) $time = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $line = "$time $Message" Write-Host $line Add-Content -Path $logFile -Value $line -Encoding UTF8 } try { Write-Log "========== Record Task Start ==========" Write-Log "Duration: $DurationMinutes minutes" Write-Log "Scene: $SceneName" # 1. 检查 FFmpeg 是否可用 $ffmpeg = Get-Command ffmpeg -ErrorAction SilentlyContinue if (-not $ffmpeg) { throw "FFmpeg not found in PATH." } # 2. 防止重复录制 $existing = Get-Process ffmpeg -ErrorAction SilentlyContinue if ($existing) { throw "Another ffmpeg process is already running. Task aborted." } # 3. 生成视频文件名 $videoName = "${SceneName}_${timestamp}.mp4" $tempFilePath = Join-Path $TempRoot $videoName $targetFilePath = Join-Path $OutputRoot $videoName Write-Log "Temp file: $tempFilePath" # 4. 构造 FFmpeg 参数 $durationSeconds = $DurationMinutes * 60 $ffmpegArgs = @( "-f", "gdigrab", "-framerate", "30", "-video_size", "1920x1080", "-offset_x", "0", "-offset_y", "0", "-i", "desktop", "-c:v", "libx264", "-preset", "veryfast", "-pix_fmt", "yuv420p", "-t", "$durationSeconds", "$tempFilePath" ) # 5. 执行录制 Write-Log "Start ffmpeg recording..." & ffmpeg -y $ffmpegArgs 2>> $logFile $exitCode = $LASTEXITCODE Write-Log "FFmpeg exit code: $exitCode" # 6. 判断文件是否生成 if (-not (Test-Path $tempFilePath)) { throw "Recording failed: output file not exists." } $fileSizeMB = [Math]::Round((Get-Item $tempFilePath).Length / 1MB, 2) Write-Log "Recording file size: ${fileSizeMB} MB" # 7. 移动文件到 Web 目录 Move-Item -Path $tempFilePath -Destination $targetFilePath -Force Write-Log "Moved to: $targetFilePath" # 8. 输出访问链接 $url = "http://your-server-ip/videos/$videoName" Write-Log "Access URL: $url" Write-Log "========== Record Task End ==========" } catch { Write-Log "[ERROR] $($_.Exception.Message)" Write-Log "========== Record Task Failed ==========" exit 1 }

脚本关键点逐段说明:

  • param(...):定义脚本参数。DurationMinutes为录制分钟数,SceneName为场景标签,OutputRoot为 Web 视频目录,TempRoot为临时目录。
  • Write-Log函数:统一写日志,同时输出到控制台和日志文件。
  • Get-Process ffmpeg:检测是否已有 FFmpeg 进程,避免两个录制任务同时运行,防止磁盘写入混乱。
  • & ffmpeg -y $ffmpegArgs 2>> $logFile:&调用外部命令,-y表示输出文件存在时自动覆盖,2>>将错误输出重定向到日志文件。
  • Move-Item:将录制文件从临时目录移动到 Web 根目录,保证 Web 目录只出现录制完成的文件。

5.3 小规模手动执行测试

先用 1 分钟时长测试脚本,命令如下:

powershell -ExecutionPolicy Bypass -File "D:\RecordTask\scripts\record-screen.ps1" -DurationMinutes 1 -SceneName test

执行后观察日志和文件:

Get-Content "D:\RecordTask\logs\record-*.log" -Tail 20 Get-ChildItem "D:\RecordTask\wwwroot\videos"

如果一切正常,videos目录下会生成test_时间戳.mp4文件。

这里补充一个执行策略说明:Windows 默认的 PowerShell 执行策略是Restricted,直接运行.ps1脚本可能被拦截。测试时可以临时用-ExecutionPolicy Bypass绕过限制,但生产环境建议通过“本地组策略”或“当前用户执行策略”将执行策略设为RemoteSigned,只允许本机脚本运行,禁止未签名的远程脚本执行。

5.4 参数化运行

脚本支持参数化,因此可以灵活创建不同录制任务。例如:

  • 每月培训:
powershell -ExecutionPolicy Bypass -File "D:\RecordTask\scripts\record-screen.ps1" -DurationMinutes 120 -SceneName monthly_training
  • 每周例会:
powershell -ExecutionPolicy Bypass -File "D:\RecordTask\scripts\record-screen.ps1" -DurationMinutes 45 -SceneName weekly_meeting

同一个脚本,通过任务计划程序创建多个触发器,就可以服务不同场景,无需复制多份代码。

6. 配置 Windows 任务计划程序

6.1 打开任务计划程序

可以直接在命令行打开任务计划程序:

taskschd.msc

或者在“服务器管理器”中找到“工具” → “任务计划程序”。

6.2 创建基本任务

在任务计划程序右侧操作栏中,点击“创建任务”而非“创建基本任务”。“创建任务”支持更丰富的触发器和条件设置,更适合生产部署。

创建任务时,建议名称填Auto Record Training Screen,描述填“每日 9 点自动录制培训屏幕,并托管到 Web 目录”。

在“常规”选项卡中,勾选“使用最高权限运行”,避免桌面会话权限不足导致录制失败。这里需要特别注意:录屏任务必须在“交互式登录”的会话中执行,如果任务以“不管用户是否登录都要运行”的模式创建,录屏设备可能无法访问桌面,导致黑屏或报错。因此,安全选项建议选择“只在用户登录时运行”。

6.3 配置触发器

点击“触发器”选项卡,点击“新建”,按以下配置:

  • 开始任务:按计划时间。
  • 设置:一次性或每天。
  • 开始日期:根据实际计划填写,例如 2025-08-30。
  • 开始时间:例如 09:00。
  • 启用:勾选。

若需要每月最后一个工作日运行,任务计划程序的“每月”触发器只能选择固定日期,无法直接表达“最后一个工作日”,此时需要额外的 PowerShell 脚本判断当天是否为工作日,若不是则直接退出。这个逻辑可以放在录制脚本外层,本文不展开。

6.4 配置操作

点击“操作”选项卡,点击“新建”。

  • 操作:启动程序。
  • 程序或脚本:powershell.exe
  • 添加参数:
-ExecutionPolicy Bypass -File "D:\RecordTask\scripts\record-screen.ps1" -DurationMinutes 120 -SceneName training
  • 起始于:D:\RecordTask\scripts

配置完成后保存任务。可以右键点击任务,选择“运行”来验证配置是否正确。

6.5 查看运行历史

任务计划程序自带历史日志。在任务计划程序主界面选中目标任务,“操作”窗格中点击“所有任务历史记录”,或者点击“历史记录”选项卡查看最近运行结果。

如果任务运行失败,最直接的排查方式是查看脚本自己的日志文件:

Get-Content "D:\RecordTask\logs\record-*.log" -Tail 50

脚本日志和系统事件日志结合使用,通常能快速定位问题。

7. 配置 Web 静态托管

7.1 使用 Nginx 托管视频目录

录制生成的视频最终要能被内部人员访问。最简单的方式是使用 Nginx 设置一个静态文件目录。

假设 Nginx 安装在C:\nginx,其配置文件位于C:\nginx\conf\nginx.conf。在http块内新增一个server:

server { listen 8080; server_name localhost; location /videos/ { alias D:/RecordTask/wwwroot/videos/; autoindex on; add_header Content-Type video/mp4; } }

配置说明:

  • listen 8080:监听 8080 端口,避免和常见 Web 服务端口冲突。
  • alias:将 URL 路径/videos/映射到本地物理目录。
  • autoindex on:开启目录索引,访问http://服务器IP:8080/videos/时可以直接看到文件列表。
  • add_header Content-Type video/mp4:为目录下的 MP4 文件明确声明 Content-Type,保证浏览器可以正常播放。

修改配置后,测试配置语法并重新加载:

nginx -t nginx -s reload

7.2 使用 IIS 托管视频目录

如果服务器本来就是 Windows Server 环境,使用 IIS 是更原生的选择。

在 IIS 中添加一个网站:

  • 网站名称:VideoArchive
  • 物理路径:D:\RecordTask\wwwroot
  • 端口:8080

随后在 IIS 的“处理程序映射”中确认.mp4文件映射到 StaticFile 处理器即可。

单独针对视频目录添加 MIME 类型,打开 IIS 管理器 → 找到网站 → MIME 类型 → 添加:

  • 文件扩展名:.mp4
  • MIME 类型:video/mp4

如果没有这个 MIME 类型,用户访问 MP4 链接时会被浏览器当作二进制文件下载,而不是直接播放。

8. 文件清理与磁盘空间管理

录屏文件的体积很大,必须提前规划清理策略。以 30 帧/秒、1920x1080、H.264 编码的视频为例,60 分钟视频通常在 300MB 到 800MB 之间,具体取决于画面变化程度。教学场景中画面变化不剧烈,体积会偏小,但长期不清理,磁盘必然爆掉。

PowerShell 定时清理脚本片段如下:

$videosDir = "D:\RecordTask\wwwroot\videos" $retentionDays = 90 $cutoff = (Get-Date).AddDays(-$retentionDays) Get-ChildItem -Path $videosDir -Filter *.mp4 | Where-Object { $_.LastWriteTime -lt $cutoff } | Remove-Item -Force

这段脚本会删除 90 天前的视频文件。建议将其同样放进任务计划程序,每天凌晨执行一次。如果视频需要长期保留,可以在清理前先转移到冷存储或备份盘。

9. 常见问题与排查思路

9.1 常见的坑点汇总

结合真实部署经验,这里整理最容易出现的几类问题:

问题现象常见原因解决思路
任务计划程序运行录屏,生成黑屏视频任务以“不管用户是否登录都要运行”模式执行,无法访问桌面改为“只在用户登录时运行”,并使用当前登录账号执行
提示Could not find codec parameters屏幕分辨率参数和实际分辨率不匹配运行ffmpeg -f gdigrab -i desktop查看实际输入参数
录屏 1 秒后自动退出窗口标题输入错误,窗口不存在先用ffmpeg -list_devices true -f dshow -i dummy确认设备,或改用desktop输入
音频设备无法打开麦克风被其他程序占用,或设备名称变化关闭占用应用;脚本中预留设备参数配置项
任务运行但未生成视频脚本执行策略拦截 PowerShell 脚本设置RemoteSigned执行策略,或用-ExecutionPolicy Bypass
浏览器无法播放视频,只提示下载服务器缺少 video/mp4 MIME 类型在 Nginx 增加add_header Content-Type video/mp4,或在 IIS 中配置 MIME
录屏文件越来越大,磁盘空间不足没有清理策略,或视频编码未压缩调整清理周期,检查编码参数,必要时降低码率

9.2 具体排查示例

这里展开一个最典型的黑屏问题。

现象:通过任务计划程序触发脚本录制,最终生成的 MP4 文件存在,但画面是纯黑色或纯灰色,只有声音正常。

原因分析:FFmpeg 的gdigrab依赖于当前用户的桌面会话。当任务计划程序配置为“不管用户是否登录都要运行”时,任务运行在一个非交互式会话中,没有可捕获的桌面内容,因此数据源始终为空。

解决步骤:

  1. 打开任务计划程序。
  2. 找到对应任务,进入“常规”选项卡。
  3. 将“安全选项”改为“只在用户登录时运行”。
  4. 取消勾选“不管用户是否登录都要运行”。
  5. 保存配置后,再次手动运行任务验证。

这类问题在远程服务器上尤其容易出现。服务器需要保持登录状态,并确保锁屏状态不会影响录制。如果服务器会定期重启,还需要为任务设置“启动时自动登录”策略,或用第三方工具保持桌面会话活跃。

9.3 录屏卡顿的排查思路

录屏卡顿,即视频帧率明显低于设定帧率,原因通常有三个:

  • CPU 编码能力不足:录屏同时执行转码,CPU 占用过高。
  • 显示器分辨率过高:4K 屏录制的数据量是 1080P 的四倍,编码压力剧增。
  • 磁盘写入速度不足:机械硬盘在持续写入高码率视频时容易成为瓶颈。

优化手段有几种,可以根据实际环境选择:

  • 降低帧率:从 30 fps 降到 15 fps,适合PPT讲解类内容。
  • 降低分辨率:采集时直接指定-video_size 1280x720。
  • 切换编码器:使用硬件编码-c:v h264_nvenc(NVIDIA 显卡)或-c:v h264_amf(AMD 显卡),将编码压力从 CPU 转移到 GPU。
  • 提高编码速度预设:-preset ultrafast能大幅降低 CPU 占用,但文件体积会增大。

硬件编码示例:

ffmpeg -f gdigrab -framerate 30 -video_size 1920x1080 -i desktop -c:v h264_nvenc -preset p4 -pix_fmt yuv420p D:\RecordTask\temp\gpu_record.mp4

使用硬件编码前,先确认 FFmpeg 版本是否包含h264_nvenc编码器。执行ffmpeg -encoders可以列出支持的所有编码器。

10. 最佳实践与生产环境建议

10.1 脚本层面的规范

  • 日志必须落地。不要只依赖任务计划程序的运行状态,录制任务一旦执行几个小时,任何终端输出都不可靠。
  • 脚本开头做前置校验。检查 FFmpeg 路径、磁盘空间、是否有重复进程,避免做无用功。
  • 录制结束后判断文件完整性。可以用 FFmpeg 本身做一次校验:
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $targetFilePath

如果读取时长失败,说明视频文件损坏,应删除并重新录制。

  • 临时文件和正式文件分开存放。录制中的文件放在temp目录,完成后移动到wwwroot\videos。这样即使录制中断,目录列表里也不会出现半截文件。

10.2 安全与权限边界

  • Web 目录如果直接暴露在外网,任何人都可能下载内部培训视频。建议通过 Nginx 增加访问认证,只允许公司内部 IP 或账号密码访问。
  • 脚本执行账号建议使用专用服务账号,而不是管理员账号,账号权限只授予录制目录和 Web 目录读写权限。
  • 定期检查磁盘空间,建议预留录制时长预估体积的 1.5 倍以上的空闲空间。

10.3 配置管理

  • 脚本中的视频目录、录制时长、场景名称建议全部参数化。
  • 不要在每个任务里写死路径,尽量统一通过一个配置文件维护。
  • 如果有多台机器需要录制,可以考虑将配置集中到共享文件或配置中心,避免每台机器手动修改。

10.4 监控与告警

生产环境最怕“看似运行,实际没有录制成功”。建议每天增加一个巡检脚本,读取当天日志,统计是否生成新的 MP4 文件:

$today = Get-Date -Format "yyyyMMdd" $todayFiles = Get-ChildItem "D:\RecordTask\wwwroot\videos" -Filter "*$today*.mp4" if ($todayFiles.Count -eq 0) { # 发送告警邮件或写入异常日志 }

这个巡检脚本放进任务计划程序,每天下午自动运行一次。如果当天应录制的视频不存在,立即发送通知,而不是等用户发现缺视频的时候再手工查找。

10.5 编码与播放兼容性

  • 统一使用 H.264 + AAC 编码组合,这是浏览器兼容性最好的方案。
  • 视频封装统一使用 MP4。
  • FFmpeg 录制时设置-pix_fmt yuv420p,否则部分播放器会无法正常解码颜色信息。
  • 如果录制内容包含大量文字,例如代码演示,建议码率不要低于 2Mbps,否则文字会模糊看不清。

合理码率与画质权衡的命令示例:

ffmpeg -f gdigrab -framerate 30 -video_size 1920x1080 -i desktop ` -c:v libx264 -preset medium -b:v 4M -maxrate 6M -bufsize 8M ` -pix_fmt yuv420p -c:a aac -b:a 128k D:\RecordTask\temp\quality_record.mp4

其中-b:v 4M表示视频目标码率 4Mbps,-maxrate允许峰值码率,-bufsize控制码率波动范围。这个配置适合屏幕内容多、文字密集的培训录屏。

11. 延伸思考与下一步方向

当前方案依赖 Windows 登录会话,这在部分服务器场景中仍然不够“省心”。如果要进一步无人化,可以考虑引入 Windows 远程桌面会话录制、虚拟桌面方案或独立录屏设备。不过这些方案的成本和复杂度会明显上升,通常只有强合规要求的企业才会使用。

如果录制任务部署在多台机器上,可以通过集中管理平台统一派发录制命令,并汇总视频清单。这种方式在做自动化测试录制时非常有用,适合与 CI/CD 流程结合。

对个人开发者来说,这套方案也可以用来做定时录制自己的操作演示视频,配合视频剪辑工具快速生成教程素材。整体投入几乎为零,收益却很直接。

如果本文对你有帮助,可以先收藏备用,需要搭建的时候按步骤操作。如果在配置过程中遇到文中没有覆盖到的报错,也可以通过日志和 FFmpeg 错误输出定位到具体环节,而不是盲目重装。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询