编辑
2025-11-22
C#
00

目录

简介
环境准备
项目实现
创建FFmpeg包装类
使用示例
常见视频转换场景
转换为MP4格式
转换为WebM格式
压缩视频
总结

简介

FFmpeg是一个功能强大的开源多媒体框架,可以用于视频和音频的编码、解码、转码等操作。本文将介绍如何使用C#封装FFmpeg,实现一个简单但功能完整的视频格式转换工具。

环境准备

项目实现

创建FFmpeg包装类

首先,我们创建一个FFmpegWrapper类来封装FFmpeg的核心功能:

C#
using System.Diagnostics; public class FFmpegWrapper { private readonly string _ffmpegPath; // FFmpeg进程执行的事件委托 public delegate void OnProgressHandler(double percentage); public event OnProgressHandler OnProgress; // 构造函数 public FFmpegWrapper(string ffmpegPath) { _ffmpegPath = ffmpegPath; if (!File.Exists(_ffmpegPath)) { throw new FileNotFoundException("FFmpeg executable not found!", _ffmpegPath); } } /// <summary> /// 获取视频信息 /// </summary> public async Task<VideoInfo> GetVideoInfoAsync(string inputPath) { if (!File.Exists(inputPath)) { throw new FileNotFoundException("Input video file not found!", inputPath); } var startInfo = new ProcessStartInfo { FileName = _ffmpegPath, Arguments = $"-i \"{inputPath}\"", RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process = new Process { StartInfo = startInfo }; process.Start(); string output = await process.StandardError.ReadToEndAsync(); await process.WaitForExitAsync(); // 解析视频信息 return ParseVideoInfo(output); } /// <summary> /// 转换视频格式 /// </summary> public async Task ConvertVideoAsync(string inputPath, string outputPath, VideoConversionOptions options) { if (!File.Exists(inputPath)) { throw new FileNotFoundException("Input video file not found!", inputPath); } // 构建FFmpeg命令 string arguments = BuildFFmpegArguments(inputPath, outputPath, options); var startInfo = new ProcessStartInfo { FileName = _ffmpegPath, Arguments = arguments, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process = new Process { StartInfo = startInfo }; // 添加输出数据接收处理 process.ErrorDataReceived += (sender, e) => { if (e.Data != null) { UpdateProgress(e.Data); } }; process.Start(); process.BeginErrorReadLine(); await process.WaitForExitAsync(); if (process.ExitCode != 0) { throw new Exception($"FFmpeg process exited with code {process.ExitCode}"); } } /// <summary> /// 构建FFmpeg命令参数 /// </summary> private string BuildFFmpegArguments(string inputPath, string outputPath, VideoConversionOptions options) { var args = new List<string> { "-i", $"\"{inputPath}\"", "-y" // 覆盖输出文件 }; // 添加视频编码器 if (!string.IsNullOrEmpty(options.VideoCodec)) { args.Add("-c:v"); args.Add(options.VideoCodec); } // 添加音频编码器 if (!string.IsNullOrEmpty(options.AudioCodec)) { args.Add("-c:a"); args.Add(options.AudioCodec); } // 设置视频比特率 if (options.VideoBitrate > 0) { args.Add("-b:v"); args.Add($"{options.VideoBitrate}k"); } // 设置音频比特率 if (options.AudioBitrate > 0) { args.Add("-b:a"); args.Add($"{options.AudioBitrate}k"); } // 设置分辨率 if (!string.IsNullOrEmpty(options.Resolution)) { args.Add("-s"); args.Add(options.Resolution); } // 添加输出文件路径 args.Add($"\"{outputPath}\""); return string.Join(" ", args); } /// <summary> /// 更新转换进度 /// </summary> private void UpdateProgress(string data) { // 解析FFmpeg输出,计算进度 if (data.Contains("time=")) { try { var timeIndex = data.IndexOf("time="); var timeStr = data.Substring(timeIndex + 5, 11); var time = TimeSpan.Parse(timeStr); // 假设我们已经知道总时长,这里简化处理 double percentage = (time.TotalSeconds / 100.0) * 100; OnProgress?.Invoke(Math.Min(percentage, 100)); } catch { // 解析失败时忽略 } } } /// <summary> /// 解析视频信息 /// </summary> private VideoInfo ParseVideoInfo(string ffmpegOutput) { var videoInfo = new VideoInfo(); // 解析时长 var durationMatch = System.Text.RegularExpressions.Regex.Match(ffmpegOutput, @"Duration: (\d{2}):(\d{2}):(\d{2})\.(\d{2})"); if (durationMatch.Success) { videoInfo.Duration = TimeSpan.Parse($"{durationMatch.Groups[1]}:{durationMatch.Groups[2]}:{durationMatch.Groups[3]}.{durationMatch.Groups[4]}"); } // 解析分辨率 var resolutionMatch = System.Text.RegularExpressions.Regex.Match(ffmpegOutput, @"(\d{2,4})x(\d{2,4})"); if (resolutionMatch.Success) { videoInfo.Width = int.Parse(resolutionMatch.Groups[1].Value); videoInfo.Height = int.Parse(resolutionMatch.Groups[2].Value); } return videoInfo; } } /// <summary> /// 视频转换选项类 /// </summary> public class VideoConversionOptions { public string VideoCodec { get; set; } public string AudioCodec { get; set; } public int VideoBitrate { get; set; } public int AudioBitrate { get; set; } public string Resolution { get; set; } } /// <summary> /// 视频信息类 /// </summary> public class VideoInfo { public TimeSpan Duration { get; set; } public int Width { get; set; } public int Height { get; set; } }

使用示例

下面是如何使用FFmpegWrapper类的示例代码:

C#
static async Task Main(string[] args) { try { // 初始化FFmpeg包装器 var ffmpeg = new FFmpegWrapper(@"D:\Software\ffmpeg-master-latest-win64-gpl-shared\bin\ffmpeg.exe"); // 设置进度回调 ffmpeg.OnProgress += (percentage) => { Console.WriteLine($"转换进度: {percentage:F2}%"); }; // 获取视频信息 string inputPath = @"D:\Video\1.mp4"; var videoInfo = await ffmpeg.GetVideoInfoAsync(inputPath); Console.WriteLine($"视频时长: {videoInfo.Duration}"); Console.WriteLine($"分辨率: {videoInfo.Width}x{videoInfo.Height}"); // 设置转换选项 var options = new VideoConversionOptions { VideoCodec = "libx264", // H.264编码 AudioCodec = "aac", // AAC音频编码 VideoBitrate = 2000, // 2000kbps视频比特率 AudioBitrate = 128, // 128kbps音频比特率 Resolution = "1280x720" // 720p分辨率 }; // 执行转换 string outputPath = @"D:\output.mkv"; await ffmpeg.ConvertVideoAsync(inputPath, outputPath, options); Console.WriteLine("视频转换完成!"); } catch (Exception ex) { Console.WriteLine($"错误: {ex.Message}"); } }

image.png

常见视频转换场景

转换为MP4格式

C#
var options = new VideoConversionOptions { VideoCodec = "libx264", AudioCodec = "aac", VideoBitrate = 2000, AudioBitrate = 128 }; await ffmpeg.ConvertVideoAsync("input.avi", "output.mp4", options);

转换为WebM格式

C#
var options = new VideoConversionOptions { VideoCodec = "libvpx-vp9", AudioCodec = "libvorbis", VideoBitrate = 1500, AudioBitrate = 128 }; await ffmpeg.ConvertVideoAsync("input.mp4", "output.webm", options);

压缩视频

C#
var options = new VideoConversionOptions { VideoCodec = "libx264", AudioCodec = "aac", VideoBitrate = 1000, // 降低比特率 Resolution = "1280x720" // 降低分辨率 }; await ffmpeg.ConvertVideoAsync("input.mp4", "compressed.mp4", options);

总结

本文介绍了如何使用C#封装FFmpeg实现视频格式转换功能。通过封装,我们可以:

  • 更方便地调用FFmpeg功能
  • 监控转换进度
  • 获取视频信息
  • 灵活设置转换参数

这个实现可以作为基础,根据实际需求进行扩展,比如添加更多的转换选项、支持更多的格式等。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!