屏幕录制现在已经变得非常常见了。不管是做教程视频、游戏直播,还是记录会议内容,一款好用的录屏工具都能让我们轻松抓取画面,并分享重要的瞬间。接下来,本文会一步步教你如何用 C# 和 FFmpeg 打造一个简单却实用的屏幕录制程序。
FFmpeg 是一个强大的开源音频与视频处理工具,支持几乎所有的音视频格式。结合 C# 的界面设计,我们可以快速构建出一个用户友好的录屏应用程序。本文将逐步引导您如何实现这一功能。
在开始之前,请确保您已经安装了以下软件:
AppRecordScreen。在多媒体处理中,将一系列图片转换为视频是一个常见的需求。本文将详细介绍如何使用 SharpAvi库在 C# 中实现这一功能。
C#Install-Package SharpAvi Install-Package System.Drawing.Common
C#using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using SharpAvi;
using SharpAvi.Output;
using Image = System.Drawing.Image;
namespace AppSharpAvi
{
public class VideoCreator
{
/// <summary>
/// 将图片序列转换为 AVI 视频
/// </summary>
/// <param name="imagePaths">图片路径数组</param>
/// <param name="outputPath">输出的 AVI 文件路径</param>
/// <param name="frameRate">视频帧率</param>
public static void CreateAviFromImages(
string[] imagePaths,
string outputPath,
int frameRate = 30
)
{
// 参数有效性检查
if (imagePaths == null || imagePaths.Length == 0)
throw new ArgumentException("图片路径数组不能为空");
// 读取第一张图片获取尺寸
using (var firstImage = Image.FromFile(imagePaths[0]))
{
int width = firstImage.Width;
int height = firstImage.Height;
// 创建 AVI 写入器
using (var writer = new AviWriter(outputPath)
{
FramesPerSecond = frameRate,
EmitIndex1 = true
})
{
// 添加视频流
var videoStream = writer.AddVideoStream(
width,
height,
BitsPerPixel.Bpp24
);
// 逐帧处理
ProcessFrames(imagePaths, videoStream, width, height);
}
}
}
/// <summary>
/// 处理每一帧图像
/// </summary>
private static void ProcessFrames(
string[] imagePaths,
IAviVideoStream videoStream,
int width,
int height)
{
foreach (var imagePath in imagePaths)
{
using (var bitmap = new Bitmap(imagePath))
{
// 调整图像大小
using (var resizedBitmap = new Bitmap(bitmap, width, height))
{
// 锁定图像数据
var bitmapData = resizedBitmap.LockBits(
new Rectangle(0, 0, width, height),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format24bppRgb
);
try
{
// 准备帧数据
int frameDataLength = bitmapData.Stride * height;
byte[] frameData = new byte[frameDataLength];
// 垂直翻转图像数据
for (int y = 0; y < height; y++)
{
Marshal.Copy(
new IntPtr(bitmapData.Scan0.ToInt64() + bitmapData.Stride * (height - 1 - y)),
frameData,
y * bitmapData.Stride,
bitmapData.Stride
);
}
// 写入帧
videoStream.WriteFrame(
true, // 关键帧
frameData,
0,
frameDataLength
);
}
finally
{
resizedBitmap.UnlockBits(bitmapData);
}
}
}
}
}
}
}
C#namespace AppSharpAvi
{
internal class Program
{
static void Main(string[] args)
{
VideoCreator.CreateAviFromImages(new string[] { "1.jpg", "2.jpg", "3.jpg","4.jpg" }, "output.avi", 30);
}
}
}

在现代异步编程里,CancellationTokenSource`是一个既强大又灵活的工具,能帮助我们管理并取消耗时较长的任务。接下来,我们会详细聊聊它的使用场景、一些推荐的做法,以及实际的例子。
CancellationTokenSource 是 .NET 中用于协作式取消操作的核心类。它允许您:
C#namespace AppCancellation
{
internal class Program
{
private static async Task<string> DownloadWebContentAsync(string url, CancellationToken cancellationToken)
{
using (var client = new HttpClient())
{
try
{
// 设置超时时间
client.Timeout = TimeSpan.FromSeconds(10);
// 发起异步GET请求,并传入取消令牌
var response = await client.GetAsync(url, cancellationToken);
// 确保请求成功
response.EnsureSuccessStatusCode();
// 读取响应内容
return await response.Content.ReadAsStringAsync(cancellationToken);
}
catch (OperationCanceledException)
{
// 捕获操作取消异常
Console.WriteLine("下载已被取消");
return string.Empty;
}
}
}
static async Task Main(string[] args)
{
// 创建取消令牌源
using (var cts = new CancellationTokenSource())
{
// 可以在另一个线程中取消操作
_ = Task.Run(() =>
{
// 例如3秒后取消
Thread.Sleep(3000);
cts.Cancel();
});
try
{
string result = await DownloadWebContentAsync("http://blog.idiosoft.com", cts.Token);
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine($"发生错误: {ex.Message}");
}
}
}
}
}

闭包(Closure)是一种强大的编程概念,它允许函数捕获并记住其定义时的环境上下文。在C#中,闭包使得函数可以访问并操作其词法作用域之外的变量。这个东西在JS中用的太多了。
闭包本质上是一个函数,它能够"记住"并访问其创建时的环境变量,即使这些变量已经超出了原始作用域。
C#public class ClosureDemo
{
public static Func<int> CreateCounter()
{
// count 是被捕获的局部变量
int count = 0;
// 返回一个匿名函数(闭包)
return () =>
{
count++; // 闭包可以修改外部变量
return count;
};
}
public static void Main()
{
// 创建两个独立的计数器
var counter1 = CreateCounter();
var counter2 = CreateCounter();
Console.WriteLine(counter1()); // 输出: 1
Console.WriteLine(counter1()); // 输出: 2
Console.WriteLine(counter2()); // 输出: 1 (独立的计数器)
}
}

在Windows应用程序中,播放系统声音是一个常见的需求。本文将详细介绍在C#中调用系统声音的多种方法,并提供具体的代码示例。
System.Media.SystemSounds 类提供了最简单的系统声音播放方式,包括常见的系统提示音。
C#using System.Media;
// 播放不同类型的系统声音
SystemSounds.Asterisk.Play(); // 信息提示音
SystemSounds.Beep.Play(); // 基本蜂鸣声
SystemSounds.Exclamation.Play();// 警告声
SystemSounds.Hand.Play(); // 错误提示音
SystemSounds.Question.Play(); // 询问声
C#using System.Media;
namespace AppSystemSound
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnPlayAsterisk_Click(object sender, EventArgs e)
{
SystemSounds.Asterisk.Play();
}
private void btnPlayBeep_Click(object sender, EventArgs e)
{
SystemSounds.Beep.Play();
}
private void btnPlayExclamation_Click(object sender, EventArgs e)
{
SystemSounds.Exclamation.Play();
}
}
}
