update
This commit is contained in:
parent
e2a75a64bd
commit
da5f023390
@ -27,7 +27,7 @@ namespace VideoConcat.Services.Video
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 1. 获取视频信息
|
// 1. 获取视频信息
|
||||||
var mediaInfo = await FFProbe.AnalyseAsync(inputPath);
|
IMediaAnalysis mediaInfo = await FFProbe.AnalyseAsync(inputPath);
|
||||||
var videoStream = mediaInfo.PrimaryVideoStream;
|
var videoStream = mediaInfo.PrimaryVideoStream;
|
||||||
if (videoStream == null)
|
if (videoStream == null)
|
||||||
{
|
{
|
||||||
@ -60,9 +60,97 @@ namespace VideoConcat.Services.Video
|
|||||||
throw new Exception("转换失败!");
|
throw new Exception("转换失败!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 1. 获取视频信息
|
||||||
|
mediaInfo = await FFProbe.AnalyseAsync(inputPath);
|
||||||
|
videoStream = mediaInfo.PrimaryVideoStream;
|
||||||
|
if (videoStream == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("没有找到视频流");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 视频总时长(秒)
|
||||||
|
double totalDuration = mediaInfo.Duration.TotalSeconds;
|
||||||
|
double frameRate = videoStream.FrameRate;
|
||||||
|
double frameDuration = Math.Round(1.0 / frameRate, 6); // 一帧时长(秒)
|
||||||
|
int totalFram = (int)(totalDuration * frameRate);
|
||||||
|
|
||||||
|
var random = new Random();
|
||||||
|
var randomFrame = random.Next(1, (int)totalDuration);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
string videoPart1 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
|
||||||
|
string videoPart2 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
|
||||||
|
bool hasSubVideo1 = SubVideo(inputPath, videoPart1, 0, randomFrame-0.016);
|
||||||
|
bool hasSubVideo2 = SubVideo(inputPath, videoPart2, randomFrame, totalDuration);
|
||||||
|
if (!hasSubVideo1 || !hasSubVideo2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool isJoinSuccess = JoinVideo(outputPath, [videoPart1, videoPart2]);
|
||||||
|
if (!isJoinSuccess)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogUtils.Error("抽帧失败", ex);
|
||||||
|
Console.WriteLine($"操作失败: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
string[] files = Directory.GetFiles(tempDir);
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
File.Delete(tempDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool SubVideo(string inputPath, string outputPath, Double startSec, Double endSec)
|
||||||
|
{
|
||||||
|
return FFMpegArguments
|
||||||
|
.FromFileInput(inputPath, true, options => options.Seek(TimeSpan.FromSeconds(startSec)).EndSeek(TimeSpan.FromSeconds(endSec)))
|
||||||
|
.OutputToFile(outputPath, true, options => options.CopyChannel()) //.WithCustomArgument("-an") 去掉音频
|
||||||
|
.ProcessSynchronously();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static bool SubAudio(string inputPath, string outputPath, Double startSec, Double endSec)
|
||||||
|
{
|
||||||
|
return FFMpegArguments
|
||||||
|
.FromFileInput(inputPath, true, options => options.Seek(TimeSpan.FromSeconds(startSec)).EndSeek(TimeSpan.FromSeconds(endSec)))
|
||||||
|
.OutputToFile(outputPath, true, options => options.CopyChannel())
|
||||||
|
.ProcessSynchronously();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool JoinVideo(string outPutPath, string[] videoParts)
|
||||||
|
{
|
||||||
|
return FFMpeg.Join(outPutPath, videoParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ProcessVideo(string inputPath,string outputPath, string tempDir)
|
||||||
|
{
|
||||||
|
// 1. 获取视频信息
|
||||||
|
IMediaAnalysis mediaInfo = await FFProbe.AnalyseAsync(inputPath);
|
||||||
|
var videoStream = mediaInfo.PrimaryVideoStream;
|
||||||
|
if (videoStream == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("没有找到视频流");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// 视频总时长(秒)
|
// 视频总时长(秒)
|
||||||
var totalDuration = mediaInfo.Duration.TotalSeconds;
|
var totalDuration = mediaInfo.Duration.TotalSeconds;
|
||||||
|
|
||||||
// 计算帧时间参数
|
// 计算帧时间参数
|
||||||
double frameRate = videoStream.FrameRate;
|
double frameRate = videoStream.FrameRate;
|
||||||
double frameDuration = Math.Round(1.0 / frameRate, 6); // 一帧时长(秒)
|
double frameDuration = Math.Round(1.0 / frameRate, 6); // 一帧时长(秒)
|
||||||
@ -72,8 +160,8 @@ namespace VideoConcat.Services.Video
|
|||||||
var random = new Random();
|
var random = new Random();
|
||||||
var randomFrame = random.Next(20, totalFram - 10);
|
var randomFrame = random.Next(20, totalFram - 10);
|
||||||
|
|
||||||
double frameTime = Math.Round((randomFrame - 1) * frameDuration,6); // 目标帧开始时间
|
double frameTime = Math.Round((randomFrame - 1) * frameDuration, 6); // 目标帧开始时间
|
||||||
double nextFrameTime = Math.Round(randomFrame * frameDuration,6); // 下一帧开始时间
|
double nextFrameTime = Math.Round((randomFrame + 1) * frameDuration, 6); // 下一帧开始时间
|
||||||
// 临时文件路径
|
// 临时文件路径
|
||||||
string videoPart1 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
|
string videoPart1 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
|
||||||
string videoPart2 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
|
string videoPart2 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
|
||||||
@ -132,43 +220,5 @@ namespace VideoConcat.Services.Video
|
|||||||
opt.WithCustomArgument("-c copy -shortest -y"))
|
opt.WithCustomArgument("-c copy -shortest -y"))
|
||||||
.ProcessAsynchronously();
|
.ProcessAsynchronously();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LogUtils.Error("抽帧失败", ex);
|
|
||||||
Console.WriteLine($"操作失败: {ex.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
string[] files = Directory.GetFiles(tempDir);
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
File.Delete(tempDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool SubVideo(string inputPath, string outputPath, Double startSec, Double endSec)
|
|
||||||
{
|
|
||||||
return FFMpegArguments
|
|
||||||
.FromFileInput(inputPath, true, options => options.Seek(TimeSpan.FromSeconds(startSec)).EndSeek(TimeSpan.FromSeconds(endSec)))
|
|
||||||
.OutputToFile(outputPath, true, options => options.CopyChannel().WithCustomArgument("-an"))
|
|
||||||
.ProcessSynchronously();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static bool SubAudio(string inputPath, string outputPath, Double startSec, Double endSec)
|
|
||||||
{
|
|
||||||
return FFMpegArguments
|
|
||||||
.FromFileInput(inputPath, true, options => options.Seek(TimeSpan.FromSeconds(startSec)).EndSeek(TimeSpan.FromSeconds(endSec)))
|
|
||||||
.OutputToFile(outputPath, true, options => options.CopyChannel())
|
|
||||||
.ProcessSynchronously();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool JoinVideo(string outPutPath, string[] videoParts)
|
|
||||||
{
|
|
||||||
return FFMpeg.Join(outPutPath, videoParts);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,8 +76,15 @@ namespace VideoConcat.ViewModels
|
|||||||
var remover = new VideoProcess();
|
var remover = new VideoProcess();
|
||||||
// 删除4秒处的帧(需根据实际帧位置调整)
|
// 删除4秒处的帧(需根据实际帧位置调整)
|
||||||
string _tmpPath = Path.GetDirectoryName(video) ?? "";
|
string _tmpPath = Path.GetDirectoryName(video) ?? "";
|
||||||
string _tmpFileName = $"抽帧视频-{Path.GetFileName(video)}";
|
string _tmpFileName = $"{(new Random()).Next(10000,99999)}{Path.GetFileName(video)}";
|
||||||
await VideoProcess.RemoveFrameRandomeAsync(video, $"{_tmpPath}\\{_tmpFileName}");
|
|
||||||
|
string outPath = Path.Combine(_tmpPath, "out");
|
||||||
|
if (!Path.Exists(outPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(outPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await VideoProcess.RemoveFrameRandomeAsync(video, $"{_tmpPath}\\out\\{_tmpFileName}");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user