update
This commit is contained in:
parent
d00b3a414b
commit
788ae8ab5f
258
Video.xaml.cs
258
Video.xaml.cs
@ -1,7 +1,12 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
using WPFDevelopers.Helpers;
|
||||||
using static System.Net.WebRequestMethods;
|
using static System.Net.WebRequestMethods;
|
||||||
|
using File = System.IO.File;
|
||||||
|
|
||||||
namespace VideoConcat
|
namespace VideoConcat
|
||||||
{
|
{
|
||||||
@ -11,17 +16,28 @@ namespace VideoConcat
|
|||||||
public partial class Video : Window
|
public partial class Video : Window
|
||||||
{
|
{
|
||||||
public string text = "", outPut = "";
|
public string text = "", outPut = "";
|
||||||
public FileSystemInfo[]? Floders { get; set; }
|
|
||||||
public string[] Heads = [];
|
|
||||||
public string[] Tails = [];
|
|
||||||
public List<string[]> Middles = [];
|
|
||||||
|
|
||||||
public DirectoryInfo? Path { get; set; }
|
public Dictionary<int, string[]> videoFolders = [];
|
||||||
|
|
||||||
|
public DirectoryInfo Path;
|
||||||
|
|
||||||
|
public Dictionary<int, A> AllPublicCombinVideos = [];
|
||||||
|
|
||||||
|
int GenerateVideoCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Video()
|
public Video()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
string currentPath = Directory.GetCurrentDirectory();
|
||||||
|
|
||||||
|
DirectoryInfo ExecParentPath = Directory.GetParent(currentPath) ?? new DirectoryInfo("");
|
||||||
|
if (ExecParentPath != null)
|
||||||
|
{
|
||||||
|
Path = ExecParentPath;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,10 +45,10 @@ namespace VideoConcat
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
count = int.Parse(videoCount.Text);
|
GenerateVideoCount = int.Parse(videoCount.Text);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@ -41,7 +57,7 @@ namespace VideoConcat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteTxt($"生成视频的个数:{videoCount.Text} 个");
|
WriteTxt($"生成视频的个数:{GenerateVideoCount} 个");
|
||||||
|
|
||||||
Check_Folder();
|
Check_Folder();
|
||||||
|
|
||||||
@ -49,107 +65,64 @@ namespace VideoConcat
|
|||||||
MakeOutPutDir();
|
MakeOutPutDir();
|
||||||
|
|
||||||
startButton.IsEnabled = false;
|
startButton.IsEnabled = false;
|
||||||
|
GenerateAllvideos(videoFolders);
|
||||||
|
var dateStart = DateTime.Now; //记录用时的起始时间
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await Task.Run(async () =>
|
await Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var dateStart = DateTime.Now; //记录用时的起始时间
|
|
||||||
|
|
||||||
|
|
||||||
|
List<List<string>> lists = GenerateAllvideos(videoFolders);
|
||||||
for (int i = 0; i <= count; i++)
|
|
||||||
|
|
||||||
|
|
||||||
{
|
await MockIOPerformanceAsync(lists);
|
||||||
|
|
||||||
await MockIOPerformanceAsync(Middles[i]);
|
|
||||||
//System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
|
||||||
//{
|
|
||||||
// processVideoBar.Dispatcher.Invoke(() =>
|
|
||||||
// {
|
|
||||||
// processVideoBar.Value = i;
|
|
||||||
|
|
||||||
// });
|
|
||||||
// outputTxt.Dispatcher.Invoke(new Action(() =>
|
|
||||||
// {
|
|
||||||
// WriteTxt("正在生成第" + i + "个视频");
|
|
||||||
// }));
|
|
||||||
//});
|
|
||||||
//System.Threading.Thread.Sleep(50);
|
|
||||||
}
|
|
||||||
|
|
||||||
startButton.Dispatcher.Invoke(() =>
|
startButton.Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
startButton.IsEnabled = true;
|
startButton.IsEnabled = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
var dateEnd = DateTime.Now;
|
});
|
||||||
var timeSpan = dateEnd - dateStart;//记录开票用时
|
var dateEnd = DateTime.Now;
|
||||||
|
var timeSpan = dateEnd - dateStart;//记录开票用时
|
||||||
|
|
||||||
});//ProcessVideo.RunTask(processVideoBar, startButton)
|
WriteTxt($"用时:{timeSpan.TotalSeconds}秒");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Check_Folder()
|
private void Check_Folder()
|
||||||
{
|
{
|
||||||
|
|
||||||
string currentPath = Directory.GetCurrentDirectory();
|
|
||||||
Path = Directory.GetParent(currentPath);
|
|
||||||
if (Path == null)
|
if (Path == null)
|
||||||
{
|
{
|
||||||
WriteTxt("获取相关视频文件目录失败!");
|
WriteTxt("获取相关视频文件目录失败!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WriteTxt("当前目录为:" + Path.FullName);
|
WriteTxt("当前目录为:" + Path.FullName);
|
||||||
|
videoFolders.Clear();
|
||||||
|
AllPublicCombinVideos.Clear();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Boolean hasHead = false;
|
int k = 1;
|
||||||
Boolean hasTail = false;
|
for (int i = 1; i < 100; i++)
|
||||||
|
|
||||||
DirectoryInfo dirD = Path as DirectoryInfo;
|
|
||||||
//获取文件夹下所有文件夹
|
|
||||||
Floders = dirD.GetDirectories();
|
|
||||||
|
|
||||||
//对单个FileSystemInfo进行判断,如果是文件夹则进行递归操作
|
|
||||||
|
|
||||||
foreach (FileSystemInfo folder in Floders)
|
|
||||||
{
|
{
|
||||||
WriteTxt($"{folder.Name}");
|
|
||||||
|
|
||||||
if (folder.Name == "head")
|
var folder = string.Format("{0:D2}", i);
|
||||||
|
string currentFolderPath = $"{Path}\\{folder}";
|
||||||
|
if (Directory.Exists(currentFolderPath))
|
||||||
{
|
{
|
||||||
hasHead = true;
|
WriteTxt(folder);
|
||||||
Heads = GetAllVideos($"{Path}\\{folder.Name}");
|
string[] videos = GetAllVideos(currentFolderPath);
|
||||||
continue;
|
if (videos.Length > 0)
|
||||||
|
{
|
||||||
|
videoFolders.Add(k, videos);
|
||||||
|
AllPublicCombinVideos.Add(k, new A());
|
||||||
|
k++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (folder.Name == "tail")
|
|
||||||
{
|
|
||||||
hasTail = true;
|
|
||||||
Tails = GetAllVideos($"{Path}\\{folder.Name}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] files = GetAllVideos($"{Path}\\{folder.Name}");
|
|
||||||
Middles.Add(files);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!hasHead)
|
return;
|
||||||
{
|
|
||||||
WriteTxt("存在名称为head的文件夹,将作为视频开头!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasTail)
|
|
||||||
{
|
|
||||||
WriteTxt("存在名称为tail的文件夹,将作为视频结尾!");
|
|
||||||
}
|
|
||||||
|
|
||||||
Middles.Insert(0, Heads);
|
|
||||||
Middles.Add(Tails);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -160,9 +133,14 @@ namespace VideoConcat
|
|||||||
|
|
||||||
private void WriteTxt(string str)
|
private void WriteTxt(string str)
|
||||||
{
|
{
|
||||||
text += str + "\r\n";
|
|
||||||
outputTxt.Text = text;
|
outputTxt.Dispatcher.Invoke(() =>
|
||||||
scrowText.ScrollToEnd();
|
{
|
||||||
|
text += str + "\r\n";
|
||||||
|
outputTxt.Text = text;
|
||||||
|
scrowText.ScrollToEnd();
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] GetAllVideos(string path)
|
public static string[] GetAllVideos(string path)
|
||||||
@ -170,49 +148,28 @@ namespace VideoConcat
|
|||||||
return Directory.GetFiles(path, "*.mp4", SearchOption.AllDirectories);
|
return Directory.GetFiles(path, "*.mp4", SearchOption.AllDirectories);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 执行
|
|
||||||
/// C# Process进程调用 https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.process?view=net-5.0
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="commandStr">执行命令</param>
|
|
||||||
public static void CommandManager(string commandStr)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (Process process = new Process())
|
|
||||||
{
|
|
||||||
process.StartInfo.FileName = @"D:\FFmpeg\ffmpeg.exe";//要执行的程序名称(属性,获取或设置要启动的应用程序或文档。FileName 属性不需要表示可执行文件。 它可以是其扩展名已经与系统上安装的应用程序关联的任何文件类型。)
|
|
||||||
process.StartInfo.Arguments = " " + commandStr;//启动该进程时传递的命令行参数
|
|
||||||
process.StartInfo.UseShellExecute = false;
|
|
||||||
process.StartInfo.RedirectStandardInput = false;//可能接受来自调用程序的输入信息
|
|
||||||
process.StartInfo.RedirectStandardOutput = false;//由调用程序获取输出信息
|
|
||||||
process.StartInfo.RedirectStandardError = false;//重定向标准错误输出
|
|
||||||
process.StartInfo.CreateNoWindow = false;//不显示程序窗口
|
|
||||||
process.Start();//启动程序
|
|
||||||
process.WaitForExit();//等待程序执行完退出进程(避免进程占用文件或者是合成文件还未生成)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CombineMp4WithoutTxt(string[] files, string StrOutMp4Path)
|
public void CombineMp4WithoutTxt(List<string> files, string StrOutMp4Path)
|
||||||
{
|
{
|
||||||
Process p = new();//建立外部调用线程
|
Process p = new();//建立外部调用线程
|
||||||
p.StartInfo.FileName = Directory.GetCurrentDirectory() + "\\ffmpeg.exe";//要调用外部程序的绝对路径
|
p.StartInfo.FileName = Directory.GetCurrentDirectory() + "\\ffmpeg.exe";//要调用外部程序的绝对路径
|
||||||
|
|
||||||
string combineFile = "";
|
|
||||||
|
|
||||||
|
//int i = 0;
|
||||||
|
//string vao = "";
|
||||||
|
List<string> ooootext = [];
|
||||||
|
|
||||||
|
files.ForEach(file => {
|
||||||
|
ooootext.Add($"file '{file}'");
|
||||||
|
});
|
||||||
|
string tmpConcatFile = $"{outPut}\\{Guid.NewGuid().ToString()}";
|
||||||
|
// 也可以指定编码方式
|
||||||
|
File.WriteAllLines(tmpConcatFile, ooootext, Encoding.ASCII);
|
||||||
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
combineFile += $"| {file}";
|
|
||||||
|
|
||||||
}
|
string StrArg = $"-f concat -safe 0 -i {tmpConcatFile} -c copy -bsf:a aac_adtstoasc -movflags +faststart {StrOutMp4Path}";
|
||||||
|
//string StrArg = $"-i {combineFile} -filter_complex \"{vao} concat=n={i}:v=1:a=1 [v][a]\" -map \"[v]\" -map \"[a]\" {StrOutMp4Path}";
|
||||||
string StrArg = $"-i concat:\"{combineFile}\" -vcodec copy -acodec copy " + StrOutMp4Path + " -y";
|
|
||||||
|
|
||||||
|
|
||||||
p.StartInfo.Arguments = StrArg;
|
p.StartInfo.Arguments = StrArg;
|
||||||
@ -238,7 +195,7 @@ namespace VideoConcat
|
|||||||
|
|
||||||
public void MakeOutPutDir()
|
public void MakeOutPutDir()
|
||||||
{
|
{
|
||||||
outPut = $"{Path}\\output";
|
outPut = $"{Path.FullName}\\output";
|
||||||
|
|
||||||
if (!Directory.Exists(outPut))
|
if (!Directory.Exists(outPut))
|
||||||
{
|
{
|
||||||
@ -246,27 +203,84 @@ namespace VideoConcat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<IEnumerable<string>> MockIOPerformanceAsync(string[] ls)
|
public async Task<IEnumerable<string>> MockIOPerformanceAsync(List<List<string>> ls)
|
||||||
{
|
{
|
||||||
List<string> lss = new List<string>();
|
List<string> lss = [];
|
||||||
List<Task> tasks = new List<Task>();
|
List<Task> tasks = [];
|
||||||
|
|
||||||
foreach (var item in ls)
|
foreach (var item in ls)
|
||||||
{
|
{
|
||||||
|
|
||||||
Task task = new Task(() =>
|
Task task = new(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(Thread.GetCurrentProcessorId());
|
DateTime now = DateTime.Now;
|
||||||
lss.Add(item);
|
Random random = new Random();
|
||||||
|
string randomString = random.Next(100000, 999999).ToString();
|
||||||
|
string result = now.ToString("yyyyMMddHHmmss") + randomString;
|
||||||
|
CombineMp4WithoutTxt(item, $"{outPut}\\{result}.mp4");
|
||||||
});
|
});
|
||||||
|
|
||||||
tasks.Add(task);
|
tasks.Add(task);
|
||||||
task.Start();
|
task.Start();
|
||||||
|
|
||||||
|
if (tasks.Count >= GenerateVideoCount)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var item in tasks)
|
foreach (var item in tasks)
|
||||||
{
|
{
|
||||||
await item;
|
await item;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lss;
|
return lss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<List<string>> GenerateAllvideos(Dictionary<int, string[]> dict)
|
||||||
|
{
|
||||||
|
|
||||||
|
List<List<string>> ls = [];
|
||||||
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
ls.Add(new List<string>(item.Value));
|
||||||
|
}
|
||||||
|
List<List<string>> permutations = CalculatePermutations(ls);
|
||||||
|
|
||||||
|
|
||||||
|
return permutations;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<List<string>> CalculatePermutations(List<List<string>> inputList)
|
||||||
|
{
|
||||||
|
List<List<string>> result = new List<List<string>>();
|
||||||
|
|
||||||
|
// 递归计算全排列的辅助函数
|
||||||
|
void Permute(List<string> currentPermutation, int index)
|
||||||
|
{
|
||||||
|
if (index == inputList.Count)
|
||||||
|
{
|
||||||
|
result.Add(new List<string>(currentPermutation));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string item in inputList[index])
|
||||||
|
{
|
||||||
|
currentPermutation.Add(item);
|
||||||
|
Permute(currentPermutation, index + 1);
|
||||||
|
currentPermutation.RemoveAt(currentPermutation.Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Permute(new List<string>(), 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class A
|
||||||
|
{
|
||||||
|
public int Index { get; set; }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user