VideoConcat/Services/Video/VideoProcess.cs
2025-08-12 00:13:45 +08:00

110 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using FFMpegCore;
using FFMpegCore.Enums;
using System;
using System.IO;
using System.Threading.Tasks;
using VideoConcat.Common.Tools;
using static System.Windows.Forms.DataFormats;
namespace VideoConcat.Services.Video
{
public class VideoProcess
{
/// <summary>
/// 同步删除视频指定帧和对应音频片段
/// </summary>
/// <param name="inputPath">输入文件路径</param>
/// <param name="outputPath">输出文件路径</param>
/// <param name="frameNumber">要删除的帧编号从1开始</param>
/// <returns>操作是否成功</returns>
public static async Task<bool> RemoveFrameRandomeAsync(string inputPath, string outputPath)
{
if (!File.Exists(inputPath))
return false;
try
{
// 1. 获取视频信息
var mediaInfo = await FFProbe.AnalyseAsync(inputPath);
var videoStream = mediaInfo.PrimaryVideoStream;
if (videoStream == null)
{
Console.WriteLine("没有找到视频流");
return false;
}
bool isHevc = videoStream.CodecName == "hevc";
// 2. 创建临时目录
string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
if (isHevc)
{
try
{
// 临时文件路径
string videoConvert = Path.Combine(tempDir, "convert.mp4");
await FFMpegArguments.FromFileInput(inputPath)
.OutputToFile(videoConvert, true, opt => // 设置输出格式
opt.WithVideoCodec("libx264")
).ProcessAsynchronously();
mediaInfo = await FFProbe.AnalyseAsync(videoConvert);
inputPath = videoConvert;
}
catch (Exception)
{
File.Delete(outputPath);
}
}
// 视频总时长(秒)
var totalDuration = mediaInfo.Duration.TotalSeconds;
// 计算帧时间参数
double frameRate = videoStream.FrameRate;
double frameDuration = 1.0 / frameRate; // 一帧时长(秒)
int totalFram = (int)(totalDuration * frameRate);
// 2. 随机生成要删除的帧的时间点(避开最后一帧,防止越界)
var random = new Random();
var randomFrame = random.Next(20, totalFram - 10);
double frameTime = (randomFrame - 1) * frameDuration; // 目标帧开始时间
double nextFrameTime = frameTime + frameDuration; // 下一帧开始时间
// 临时文件路径
string videoPart1 = Path.Combine(tempDir, "video_part1.mp4");
string videoPart2 = Path.Combine(tempDir, "video_part2.mp4");
bool hasSubVideo1 = SubVideo(inputPath, videoPart1, 0, frameTime);
bool hasSubVideo2 = SubVideo(inputPath, videoPart2, nextFrameTime, totalDuration);
if (hasSubVideo1 && hasSubVideo2)
{
return JoinVideo(outputPath, [videoPart1, videoPart2]);
}
return false;
}
catch (Exception ex)
{
LogUtils.Error("抽帧失败", ex);
Console.WriteLine($"操作失败: {ex.Message}");
return false;
}
}
public static bool SubVideo(string inputPath, string outputPath, Double startSec, Double endSec)
{
return FFMpeg.SubVideo(inputPath, outputPath, TimeSpan.FromSeconds(startSec), TimeSpan.FromSeconds(endSec));
}
public static bool JoinVideo(string outPutPath, string[] videoParts)
{
return FFMpeg.Join(outPutPath, videoParts);
}
}
}