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
{
///
/// 同步删除视频指定帧和对应音频片段
///
/// 输入文件路径
/// 输出文件路径
/// 要删除的帧编号(从1开始)
/// 操作是否成功
public static async Task 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);
}
}
}