using System; using System.Collections.Generic; using System.Linq; using System.Text; using EMISOnline.WinService.Common; using System.IO; using System.Diagnostics; namespace EMISOnline.WinService { public class M3u8Timer { public M3u8Timer() { } public void doingM3u8() { Log.Info(this.GetType().ToString(), "Start m3u8..."); //获取所有可以转换的文件 string convertPath = "", Comments = ""; List lists = FileHelper.GetAllFiles(Config.FtpPath,Config.FtpFileType); foreach (FileInfo file in lists) { Comments = FileHelper.GetFilePropertiesComments(file.FullName); if (string.IsNullOrEmpty(Comments)) Comments = ""; //已经标识为上传完成的文件,且没有转换过的文件才进行转换。 if (Comments.IndexOf("UploadOver") < 0 || Comments.IndexOf("ConvertM3u8") >= 0) continue; //每次时序 只转换一个文件,转换完成释放时序。 convertPath = file.FullName; break; } //没有需要转换的文件 if (convertPath.Length == 0) return; //开始进行 m3u8转换 string m3u8Path = ""; string[] comArys = Comments.Split('|'); //为m3u8创建文件夹 if (comArys.Length == 1) { m3u8Path = Config.M3U8Path + "\\" + DateTime.Now.ToString("yyyyMMdd") + "\\" + DateTime.Now.Ticks.ToString(); if (!Directory.Exists(m3u8Path))//若文件夹不存在则新建文件夹 { Directory.CreateDirectory(m3u8Path); //新建文件夹 } //把该文件对应的m3u8文件路径保存起来 Comments += "|" + m3u8Path; FileHelper.SaveFilePropertiesComments(convertPath, Comments); } else m3u8Path = comArys[1]; Log.Info(this.GetType().ToString(), "Find File:" + convertPath + "。try to Convert。M3u8Path:" + m3u8Path); //通知教学平台有这样的一个文件正在进行m3u8转换 M3u8Timer.SaveFtpFile(convertPath, m3u8Path + "\\x.m3u8", "", "", "", 2); //开始进行转换 runJpg(convertPath, m3u8Path + "\\x.jpg"); runM3u8(convertPath, m3u8Path + "\\x.m3u8"); //保存状态,下次将不在进行转换检查 Comments += "|ConvertM3u8"; FileHelper.SaveFilePropertiesComments(convertPath, Comments); //通知教学平台有这样的一个文件m3u8转换完成 string m3u8Url = Config.M3u8Server + m3u8Path.Replace(Config.M3U8Path, "").Replace("\\","/")+"/x.m3u8"; M3u8Timer.SaveFtpFile(convertPath, "", "", m3u8Url , "", 3); } public bool runM3u8(string sourcePath, string mPath) { string cmd = string.Format(" -i \"{0}\" -c:v libx264 -c:a aac -strict -2 -hls_list_size 0 -f hls \"{1}\"", sourcePath, mPath); Log.Info(this.GetType().ToString(), "RunCmd: " + cmd); cmd = RunCmd(cmd); if (cmd == "-1") { return false; } return true; } public bool runJpg(string sourcePath, string mPicPath) { string cmd = string.Format(" -i \"{0}\" -f image2 -ss 1 -vframes 1 \"{1}\"", sourcePath, mPicPath); Log.Info(this.GetType().ToString(), "RunCmd: " + cmd); cmd = RunCmd(cmd); if (cmd == "-1") { return false; } return true; } public string RunCmd(string cmdStr) { try { using (Process p = new Process()) { p.StartInfo.FileName = Config.FfmpegExe+"\\bin\\ffmpeg.exe";//要调用外部程序的绝对路径 p.StartInfo.Arguments = cmdStr;//参数(这里就是FFMPEG的参数了) p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN) p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的) p.StartInfo.CreateNoWindow = false;//不创建进程窗口 p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN p.OutputDataReceived += new DataReceivedEventHandler(Output); p.Start();//启动线程 p.BeginErrorReadLine();//开始异步读取 //p.BeginOutputReadLine(); p.WaitForExit();//阻塞等待进程结束 p.Close();//关闭进程 p.Dispose();//释放资源 return "0"; } } catch (Exception ex) { Log.Info(this.GetType().ToString(),"RunCmd error: " + ex.Message + ex.StackTrace); } return "-1"; } private void Output(object sendProcess, DataReceivedEventArgs output) { if (!String.IsNullOrEmpty(output.Data)) { Log.Info(this.GetType().ToString(), "RunCmd: " + output.Data); } } public static string SaveFtpFile(string FTPPath, string M3u8Path, string FTPUrl, string M3u8Url, string Name, int Status) { string param = "FTPPath=" + FTPPath; param += "&M3u8Path=" + M3u8Path; param += "&FTPUrl=" + FTPUrl; param += "&M3u8Url=" + M3u8Url; param += "&Name=" + Name; param += "&Status=" + Status.ToString(); return HttpHelper.PostWebRequest(Config.DataServer + "/FtpFile/SaveFtpFile", param, Encoding.UTF8); } } }