一种适用于Linux和Windows的解决方案是在代码中使用控制台ffmpeg。我堆叠线程,编写一个简单的线程控制器类,然后您可以轻松地利用ffmpeg的任何功能。
例如,这包含了使用ffmpeg从我指定的时间创建缩略图的部分。
在线程控制器中,您可以有类似以下的内容:
List<ThrdFfmpeg> threads = new List<ThrdFfmpeg>();
您正在运行的线程列表是哪些,我使用计时器来轮询这些线程,如果轮询对您的应用程序不适用,您也可以设置事件。在这种情况下,Thrdffmpeg类包含以下内容:
public class ThrdFfmpeg
{
public FfmpegStuff ffm { get; set; }
public Thread thrd { get; set; }
}
FFmpegStuff包含各种ffmpeg功能,thrd显然是线程。
FfmpegStuff中的一个属性是FilesToProcess类,用于向调用的进程传递信息,并在线程停止后接收信息。
public class FileToProcess
{
public int videoID { get; set; }
public string fname { get; set; }
public int durationSeconds { get; set; }
public List<string> imgFiles { get; set; }
}
VideoID(我使用数据库)告诉线程处理程序从数据库中取出哪个视频。
fname在我的其他函数中用于使用FilesToProcess,但此处未使用。
durationSeconds-由仅收集视频持续时间的线程填充。
imgFiles用于返回创建的任何缩略图。
我不想在代码中陷入泥潭,因为这是鼓励使用易于控制的线程中的ffmpeg的目的。
现在我们有了我们的组件,我们可以添加到我们的线程列表中,在我们的控制器中执行以下操作,例如,
AddThread()
{
ThrdFfmpeg thrd;
FileToProcess ftp;
foreach(FileToProcess ff in `dbhelper.GetFileNames(txtCategory.Text))`
{
ftp = new FileToProcess();
ftp = ff;
ftp.imgFiles = new List<string>();
thrd = new ThrdFfmpeg();
thrd.ffm = new FfmpegStuff();
thrd.ffm.filetoprocess = ftp;
thrd.thrd = new `System.Threading.Thread(thrd.ffm.CollectVideoLength);`
threads.Add(thrd);
}
if(timerNotStarted)
StartThreadTimer();
}
现在,对我们的线程进行Pole操作已经变得很简单。
private void timerThreads_Tick(object sender, EventArgs e)
{
int runningCount = 0;
int finishedThreads = 0;
foreach(ThrdFfmpeg thrd in threads)
{
switch (thrd.thrd.ThreadState)
{
case System.Threading.ThreadState.Running:
++runningCount;
break;
case System.Threading.ThreadState.StopRequested:
break;
case System.Threading.ThreadState.SuspendRequested:
break;
case System.Threading.ThreadState.Background:
break;
case System.Threading.ThreadState.Unstarted:
thrd.thrd.Start();
++runningCount;
break;
case System.Threading.ThreadState.Stopped:
++finishedThreads;
ThumbnailsReadyEvent( thrd.ffm );
break;
case System.Threading.ThreadState.WaitSleepJoin:
break;
case System.Threading.ThreadState.Suspended:
break;
case System.Threading.ThreadState.AbortRequested:
break;
case System.Threading.ThreadState.Aborted:
break;
default:
break;
}
}
if(flash)
{
lbThreadStatus.BackColor = Color.White;
flash = false;
}
else
{
lbThreadStatus.BackColor = this.BackColor;
flash = true;
}
if(finishedThreads >= threads.Count())
{
StopThreadTimer();
ShowSample();
MakeJoinedThumb();
}
}
将自己的事件放入控制器类中效果很好,但在视频工作中,当我的代码实际上没有处理任何视频文件时,在控制类中轮询并调用事件同样有效。使用这种方法,我已经逐渐构建了几乎所有可能需要使用的视频和静态功能,并将它们都包含在一个类中,而该类作为文本文件可以在Lunux和Windows版本中使用,只需要一小部分预处理指令即可。