编辑
2025-11-22
C#
00

目录

准备工作
安装必要的 NuGet 包
下载 FFmpeg
基本视频合并方案
简单视频合并
4. 高级合并场景
处理不同编码的视频
视频比特率(SetVideoBitrate)
音频比特率(SetAudioBitrate)
注意事项
结论

视频合并是多媒体处理中常见的需求,无论是拼接分段视频、创建视频集锦,还是处理长视频分片,使用 FFmpeg 都是一个高效的解决方案。本文将详细介绍如何使用 C# 和 Xabe.FFmpeg 库实现视频合并。

准备工作

安装必要的 NuGet 包

首先,在 Visual Studio 中安装 Xabe.FFmpeg NuGet 包:

Bash
Install-Package Xabe.FFmpeg

下载 FFmpeg

确保系统中已安装 FFmpeg:

Windows: 可以使用 Chocolatey

Bash
# 使用 Chocolatey choco install ffmpeg

下载FFmpeg:

HTML
https://ffmpeg.org/download.html

基本视频合并方案

简单视频合并

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xabe.FFmpeg; namespace App07 { public class VideoMerger { public async Task MergeVideosAsync(List<string> inputFiles, string outputFile, IProgress<double> progress = null) { FFmpeg.SetExecutablesPath("D:\\Software\\ffmpeg-master-latest-win64-gpl-shared\\bin"); // 首先计算所有视频的总时长 double totalDuration = 0; foreach (var file in inputFiles) { var mediaInfo = await FFmpeg.GetMediaInfo(file); totalDuration += mediaInfo.Duration.TotalSeconds; } string listFilePath = "concat.txt"; using (StreamWriter writer = new StreamWriter(listFilePath)) { foreach (var file in inputFiles) { writer.WriteLine($"file '{file}'"); } } var conversion = FFmpeg.Conversions.New() .AddParameter($"-f concat -safe 0 -i {listFilePath}") .SetOutput(outputFile) .SetOverwriteOutput(true); // 添加进度回调 conversion.OnProgress += (sender, args) => { var progressValue = (args.Duration.TotalSeconds / totalDuration) * 100; progress?.Report(Math.Min(progressValue, 100)); // 确保进度不超过100% }; await conversion.Start(); if (File.Exists(listFilePath)) { File.Delete(listFilePath); } } } }

image.png

4. 高级合并场景

处理不同编码的视频

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xabe.FFmpeg; namespace App07 { public class VideoMergerAdvanced { public enum VideoQuality { Low, Medium, High, VeryHigh } public async Task MergeVideosAsync(List<string> inputFiles, string outputFile, VideoQuality quality = VideoQuality.Medium, IProgress<double> progress = null) { FFmpeg.SetExecutablesPath("D:\\Software\\ffmpeg-master-latest-win64-gpl-shared\\bin"); // 获取第一个视频的信息来确定输出视频的参数 var firstVideoInfo = await FFmpeg.GetMediaInfo(inputFiles[0]); var videoStream = firstVideoInfo.VideoStreams.First(); var resolution = GetResolution(videoStream.Width, videoStream.Height); // 根据质量设置比特率 var (videoBitrate, audioBitrate) = GetBitratesByQuality(quality, resolution); // 计算总时长用于进度显示 double totalDuration = 0; foreach (var file in inputFiles) { var mediaInfo = await FFmpeg.GetMediaInfo(file); totalDuration += mediaInfo.Duration.TotalSeconds; } // 创建concat文件 string listFilePath = "concat.txt"; using (StreamWriter writer = new StreamWriter(listFilePath)) { foreach (var file in inputFiles) { writer.WriteLine($"file '{file}'"); } } try { var conversion = FFmpeg.Conversions.New() .AddParameter($"-f concat -safe 0 -i \"{listFilePath}\"") .AddParameter($"-c:v libx264") // 视频编码器 .AddParameter($"-b:v {videoBitrate}k") // 视频比特率 .AddParameter($"-c:a aac") // 音频编码器 .AddParameter($"-b:a {audioBitrate}k") // 音频比特率 .AddParameter("-preset medium") // 编码预设 .AddParameter("-threads 0") // 使用所有可用线程 .SetOutput(outputFile) .SetOverwriteOutput(true); // 添加进度报告 conversion.OnProgress += (sender, args) => { if (totalDuration > 0) { var progressValue = (args.Duration.TotalSeconds / totalDuration) * 100; progress?.Report(Math.Min(progressValue, 100)); } }; await conversion.Start(); } finally { if (File.Exists(listFilePath)) { File.Delete(listFilePath); } } } private (int videoBitrate, int audioBitrate) GetBitratesByQuality(VideoQuality quality, string resolution) { switch (quality) { case VideoQuality.Low: return resolution switch { "480p" => (1000, 96), "720p" => (2000, 128), "1080p" => (4000, 128), "2K" => (8000, 192), "4K" => (16000, 192), _ => (2000, 128) }; case VideoQuality.Medium: return resolution switch { "480p" => (1500, 128), "720p" => (3000, 192), "1080p" => (6000, 192), "2K" => (12000, 256), "4K" => (25000, 256), _ => (3000, 192) }; case VideoQuality.High: return resolution switch { "480p" => (2000, 192), "720p" => (4000, 256), "1080p" => (8000, 256), "2K" => (16000, 320), "4K" => (35000, 320), _ => (4000, 256) }; case VideoQuality.VeryHigh: return resolution switch { "480p" => (2500, 256), "720p" => (5000, 320), "1080p" => (10000, 320), "2K" => (20000, 320), "4K" => (45000, 320), _ => (5000, 320) }; default: return (4000, 192); // 默认中等质量 } } private string GetResolution(int width, int height) { if (width >= 3840 || height >= 2160) return "4K"; if (width >= 2560 || height >= 1440) return "2K"; if (width >= 1920 || height >= 1080) return "1080p"; if (width >= 1280 || height >= 720) return "720p"; return "480p"; } } }

视频比特率(SetVideoBitrate)

视频比特率通常以 kbps(千比特每秒)为单位。常见设置:

// 视频比特率设置示例 .SetVideoBitrate(1000) // 1000 kbps = 1 Mbps

常见分辨率对应的推荐比特率:

  • 480p (854×480): 1000-2000 kbps
  • 720p (1280×720): 2000-4000 kbps
  • 1080p (1920×1080): 4000-8000 kbps
  • 2K (2560×1440): 8000-16000 kbps
  • 4K (3840×2160): 16000-35000 kbps

音频比特率(SetAudioBitrate)

音频比特率也是以 kbps 为单位。常见设置:

// 音频比特率设置示例 .SetAudioBitrate(128) // 128 kbps

常见音频比特率选择:

  • 96 kbps: 基本质量
  • 128 kbps: 标准质量(最常用)
  • 192 kbps: 较高质量
  • 256 kbps: 高质量
  • 320 kbps: 最高质量

image.png

注意事项

  • 确保有足够的磁盘空间
  • 大文件合并可能需要较长时间
  • 不同编码的视频可能需要转码
  • 处理大量或大尺寸视频时,考虑内存和性能优化

结论

使用C#调用FFmpeg进行视频合并是一个强大而灵活的解决方案。通过合理使用FFmpeg的参数和正确的错误处理,可以实现稳定可靠的视频合并功能。在实际应用中,需要根据具体场景选择合适的合并方案,并注意处理各种边界情况。

本文作者:技术老小子

本文链接:

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