312 lines
8.9 KiB
C#
312 lines
8.9 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using System.Windows.Shapes;
|
|
using WPFDevelopers.Helpers;
|
|
|
|
|
|
using File = System.IO.File;
|
|
|
|
|
|
namespace VideoConcat
|
|
{
|
|
/// <summary>
|
|
/// Video.xaml 的交互逻辑
|
|
/// </summary>
|
|
public partial class Video : Window
|
|
{
|
|
public string text = "", outPut = "";
|
|
|
|
public Dictionary<int, string[]> videoFolders = [];
|
|
|
|
private static string Path = "", ParentPath = "";
|
|
|
|
public Dictionary<int, A> AllPublicCombinVideos = [];
|
|
|
|
int GenerateVideoCount = 0;
|
|
|
|
public static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
public Video()
|
|
{
|
|
InitializeComponent();
|
|
Init();
|
|
}
|
|
|
|
public static void Init()
|
|
{
|
|
ParentPath = Directory.GetCurrentDirectory();
|
|
log4net.Config.XmlConfigurator.Configure();
|
|
}
|
|
|
|
private async void Button_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
|
|
try
|
|
{
|
|
GenerateVideoCount = int.Parse(videoCount.Text);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
|
|
MessageBox.Show("请输入正确的数字");
|
|
|
|
return;
|
|
}
|
|
|
|
WriteTxt($"生成视频的个数:{GenerateVideoCount} 个");
|
|
|
|
Check_Folder();
|
|
|
|
|
|
MakeOutPutDir();
|
|
|
|
startButton.IsEnabled = false;
|
|
GenerateAllvideos(videoFolders);
|
|
var dateStart = DateTime.Now; //记录用时的起始时间
|
|
await Task.Run(async () =>
|
|
{
|
|
|
|
|
|
List<List<string>> lists = GenerateAllvideos(videoFolders);
|
|
|
|
|
|
await MockIOPerformanceAsync(lists);
|
|
|
|
|
|
startButton.Dispatcher.Invoke(() =>
|
|
{
|
|
startButton.IsEnabled = true;
|
|
});
|
|
|
|
});
|
|
var dateEnd = DateTime.Now;
|
|
var timeSpan = dateEnd - dateStart;//记录开票用时
|
|
|
|
WriteTxt($"用时:{timeSpan.TotalSeconds}秒");
|
|
}
|
|
|
|
private void Check_Folder()
|
|
{
|
|
DirectoryInfo? directory = Directory.GetParent(ParentPath);
|
|
if (directory == null)
|
|
{
|
|
WriteTxt("获取视频路径失败!");
|
|
return;
|
|
}
|
|
|
|
Path = directory.FullName;
|
|
|
|
WriteTxt("当前目录为:" + Path);
|
|
videoFolders.Clear();
|
|
AllPublicCombinVideos.Clear();
|
|
|
|
try
|
|
{
|
|
int k = 1;
|
|
for (int i = 100; i >0; i--)
|
|
{
|
|
|
|
var folder = string.Format("{0:D2}", i);
|
|
string currentFolderPath = $"{Path}\\{folder}";
|
|
if (Directory.Exists(currentFolderPath))
|
|
{
|
|
string[] videos = GetAllVideos(currentFolderPath);
|
|
if (videos.Length > 0)
|
|
{
|
|
videoFolders.Add(k, videos);
|
|
AllPublicCombinVideos.Add(k, new A());
|
|
k++;
|
|
}
|
|
}
|
|
|
|
}
|
|
return;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void WriteTxt(string str)
|
|
{
|
|
|
|
outputTxt.Dispatcher.Invoke(() =>
|
|
{
|
|
log.Info(str);
|
|
text += str + "\r\n";
|
|
outputTxt.Text = text;
|
|
scrowText.ScrollToEnd();
|
|
});
|
|
|
|
}
|
|
|
|
|
|
public static string[] GetAllVideos(string path)
|
|
{
|
|
return Directory.GetFiles(path, "*.mp4", SearchOption.AllDirectories);
|
|
}
|
|
|
|
|
|
public void CombineMp4WithoutTxt(List<string> files, string StrOutMp4Path)
|
|
{
|
|
Process p = new();//建立外部调用线程
|
|
p.StartInfo.FileName = Directory.GetCurrentDirectory() + "\\ffmpeg.exe";//要调用外部程序的绝对路径
|
|
|
|
|
|
//int i = 0;
|
|
//string vao = "";
|
|
List<string> ooootext = [];
|
|
files.Reverse();
|
|
files.ForEach(file =>
|
|
{
|
|
//#file = System.Web.HttpUtility.UrlEncode(file);
|
|
ooootext.Add($"file '{file}'");
|
|
});
|
|
|
|
var random = new Random();
|
|
string tmpConcatFile = $"{outPut}\\{Guid.NewGuid()}{random.Next(100000, 999999)}.aaa";
|
|
// 也可以指定编码方式
|
|
//File.WriteAllLines(tmpConcatFile, ooootext, Encoding.UTF8);
|
|
|
|
File.WriteAllText(tmpConcatFile, string.Join("\n", [.. ooootext]), new System.Text.UTF8Encoding(false));
|
|
|
|
|
|
|
|
|
|
string StrArg = $"-f concat -safe 0 -i {tmpConcatFile} -bsf:a aac_adtstoasc -movflags +faststart -c copy {StrOutMp4Path}";
|
|
//string StrArg = $"-i {combineFile} -filter_complex \"{vao} concat=n={i}:v=1:a=1 [v][a]\" -map \"[v]\" -map \"[a]\" {StrOutMp4Path}";
|
|
|
|
|
|
p.StartInfo.Arguments = StrArg;
|
|
|
|
p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
|
|
p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
|
|
p.StartInfo.CreateNoWindow = true;//不创建进程窗口
|
|
p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
|
|
p.Start();//启动线程
|
|
p.BeginErrorReadLine();//开始异步读取
|
|
p.WaitForExit();//阻塞等待进程结束
|
|
p.Close();//关闭进程
|
|
p.Dispose();//释放资源
|
|
if (File.Exists(tmpConcatFile))
|
|
{
|
|
try
|
|
{
|
|
File.Delete(tmpConcatFile);
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void Output(object sendProcess, DataReceivedEventArgs output)
|
|
{
|
|
if (!String.IsNullOrEmpty(output.Data))
|
|
{
|
|
log.Info(output.Data, null);
|
|
}
|
|
}
|
|
|
|
public void MakeOutPutDir()
|
|
{
|
|
outPut = $"{Path}\\output";
|
|
|
|
if (!Directory.Exists(outPut))
|
|
{
|
|
Directory.CreateDirectory(outPut);
|
|
}
|
|
}
|
|
|
|
public async Task<IEnumerable<string>> MockIOPerformanceAsync(List<List<string>> ls)
|
|
{
|
|
List<string> lss = [];
|
|
List<Task> tasks = [];
|
|
|
|
foreach (var item in ls)
|
|
{
|
|
|
|
Task task = new(() =>
|
|
{
|
|
DateTime now = DateTime.Now;
|
|
Random random = new();
|
|
string randomString = random.Next(100000, 999999).ToString();
|
|
string result = now.ToString("yyyyMMddHHmmss") + randomString;
|
|
CombineMp4WithoutTxt(item, $"{outPut}\\{result}.mp4");
|
|
});
|
|
|
|
tasks.Add(task);
|
|
task.Start();
|
|
|
|
if (tasks.Count >= GenerateVideoCount)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
foreach (var item in tasks)
|
|
{
|
|
await item;
|
|
}
|
|
|
|
return lss;
|
|
}
|
|
|
|
private static 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 = [];
|
|
|
|
// 递归计算全排列的辅助函数
|
|
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([], 0);
|
|
|
|
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public class A
|
|
{
|
|
public int Index { get; set; }
|
|
};
|
|
|
|
}
|