我知道在 C++ 中对视频文件进行适当的分解并自己做是非常诱人的。但是,尽管信息已经存在,但是构建类来处理每种文件格式是一个冗长的过程,并且很容易改变以考虑未来的结构变化,坦率地说,这是不值得的。
相反,我推荐 ffmpeg。上面有提到,但是说难,不难。有比大多数人需要的更多的选择,这使得它看起来比实际更困难。对于大多数操作,您可以让 ffmpeg 自行解决。
比如一个文件转换 ffmpeg -i inputFile.mp4 outputFile.avi
从一开始就决定让 ffmpeg 操作在线程中运行,或者更准确地说是在线程库中运行。但是让你自己的线程类包装它,这样你就可以拥有自己的 EventAgs 和检查线程是否完成的方法。就像是 :-
ThreadLibManager()
{
List<MyThreads> listOfActiveThreads;
public AddThread(MyThreads);
}
Your thread class is something like:-
class MyThread
{
public Thread threadForThisInstance { get; set; }
public MyFFMpegTools mpegTools { get; set; }
}
MyFFMpegTools performs many different video operations, so you want your own event
args to tell your parent code precisely what type of operation has just raised and
event.
enum MyFmpegArgs
{
public int thisThreadID { get; set; } //Set as a new MyThread is added to the List<>
public MyFfmpegType operationType {get; set;}
//output paths etc that the parent handler will need to find output files
}
enum MyFfmpegType
{
FF_CONVERTFILE = 0, FF_CREATETHUMBNAIL, FF_EXTRACTFRAMES ...
}
这是我的 ffmpeg 工具类的一小段,这部分收集有关视频的信息。我把 FFmpeg 放在一个特定的位置,并在软件开始运行时确保它在那里。对于这个版本,我已将其移至桌面,我很确定我已经为您正确编写了路径(我真的很讨厌 MS 的特殊文件夹系统,所以我尽可能地忽略它)。
无论如何,这是一个使用无窗口ffmpeg的例子。
public string GetVideoInfo(FileInfo fi)
{
outputBuilder.Clear();
string strCommand = string.Concat(" -i \"", fi.FullName, "\"");
string ffPath =
System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\ffmpeg.exe";
string oStr = "";
try
{
Process build = new Process();
//build.StartInfo.WorkingDirectory = @"dir";
build.StartInfo.Arguments = strCommand;
build.StartInfo.FileName = ffPath;
build.StartInfo.UseShellExecute = false;
build.StartInfo.RedirectStandardOutput = true;
build.StartInfo.RedirectStandardError = true;
build.StartInfo.CreateNoWindow = true;
build.ErrorDataReceived += build_ErrorDataReceived;
build.OutputDataReceived += build_ErrorDataReceived;
build.EnableRaisingEvents = true;
build.Start();
build.BeginOutputReadLine();
build.BeginErrorReadLine();
build.WaitForExit();
string findThis = "start";
int offset = 0;
foreach (string str in outputBuilder)
{
if (str.Contains("Duration"))
{
offset = str.IndexOf(findThis);
oStr = str.Substring(0, offset);
}
}
}
catch
{
oStr = "Error collecting file information";
}
return oStr;
}
private void build_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
string strMessage = e.Data;
if (outputBuilder != null && strMessage != null)
{
outputBuilder.Add(string.Concat(strMessage, "\n"));
}
}