├── ExpertVideoToolbox ├── App.config ├── packages.config ├── MediaInfoDotNet.dll.config ├── Properties │ ├── Settings.settings │ ├── AssemblyInfo.cs │ ├── Settings.Designer.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── ExpertVideoToolbox.csproj.user ├── Program.cs ├── TaskManager │ ├── videoTask.cs │ ├── runningPool.cs │ ├── tasksQueue.cs │ └── Job.cs ├── cmdCodeGenerator │ ├── filePathStorage.cs │ ├── taskSetting.cs │ └── cmdCode.cs ├── MainForm.resx ├── RunningStatusForm.resx ├── ExpertVideoToolbox.csproj ├── ProcessControl.cs ├── RunningStatusForm.cs ├── RunningStatusForm.Designer.cs ├── MainForm.Designer.cs └── MainForm.cs ├── .gitignore ├── ExpertVideoToolbox.sln └── README.md /ExpertVideoToolbox/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/MediaInfoDotNet.dll.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/ExpertVideoToolbox.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 发布\ 5 | 6 | 7 | 8 | 9 | 10 | zh-CN 11 | false 12 | 13 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace ExpertVideoToolbox 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// 应用程序的主入口点。 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new MainForm()); 20 | //Application.EnableVisualStyles(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | 49 | .exe 50 | .dll 51 | 52 | obj/ 53 | x86/ 54 | x64/ 55 | bin/ 56 | packages/ 57 | *.264 58 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/TaskManager/videoTask.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ExpertVideoToolbox.TaskManager 8 | { 9 | class videoTask 10 | { 11 | private string filePath; 12 | private string setting; 13 | 14 | public videoTask(string path) 15 | { 16 | this.filePath = path; 17 | } 18 | 19 | public videoTask(string path, string setting) 20 | { 21 | this.filePath = path; 22 | this.setting = setting; 23 | } 24 | 25 | public string printTask() 26 | { 27 | return this.filePath; 28 | } 29 | 30 | public string getFP() 31 | { 32 | return this.filePath; 33 | } 34 | 35 | public string getSetting() 36 | { 37 | return this.setting; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ExpertVideoToolbox.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExpertVideoToolbox", "ExpertVideoToolbox\ExpertVideoToolbox.csproj", "{6DE600BF-C56C-4E2D-B1DD-73217764A806}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {6DE600BF-C56C-4E2D-B1DD-73217764A806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {6DE600BF-C56C-4E2D-B1DD-73217764A806}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {6DE600BF-C56C-4E2D-B1DD-73217764A806}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {6DE600BF-C56C-4E2D-B1DD-73217764A806}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ExpertVideoToolbox 2 | A lightweight, versatile GUI of x264, x265. Nearly full input formats support, .mkv and .mp4 output support. Avs support has been added. 3 | 4 | = Mandatory Prerequisites = 5 | * NuGet packages: MediaInfoDotNet and Newtonsoft.Json 6 | * Multiple tools in tools/. (See README.jpg or download one of releases to obtain these tools). 7 | Includes ffmpeg.exe, mkvmerge.exe, qaac.exe (need some .dll files to run without QuickTime), mp4Box.exe(libgpac_static.lib needed), x26x. 8 | Currently, 9 | x265 binary comes from http://msystem.waw.pl/x265/ 10 | x264 and ffmpeg binaries come from http://maruko.appinn.me/7mod.html 11 | 12 | = Features = 13 | * Easy to bulk convert videos, even with different parameters. 14 | * Full video conversion process (Audio and Video) in one step. 15 | * For expert, easy to modify x26x command lines parameters. 16 | * Low speed mode. Set CPU affinity to one quarter logcial processors. Users do not need to stop the video converting process when playing games or other tasks need CPU. 17 | * Support .avs script file. Also support audio process (Copy audio & qaac) in avs mode. 18 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("ExpertVideoToolbox")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ExpertVideoToolbox")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("aaced22e-6296-4617-bd9b-ea2318a87d3e")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.2.3")] 36 | [assembly: AssemblyFileVersion("0.2.3.173")] 37 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34014 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ExpertVideoToolbox.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/cmdCodeGenerator/filePathStorage.cs: -------------------------------------------------------------------------------- 1 | using ExpertVideoToolbox.TaskManager; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using System.Windows.Forms; 9 | 10 | namespace ExpertVideoToolbox.cmdCodeGenerator 11 | { 12 | class filePathStorage 13 | { 14 | private videoTask[] storage; 15 | private int count; 16 | private int maxCount; 17 | 18 | public filePathStorage(int maxCount) 19 | { 20 | this.maxCount = maxCount; 21 | this.count = 0; 22 | this.storage = new videoTask[maxCount]; // 根据文件个数分配存储空间 23 | } 24 | 25 | public videoTask get(int index) 26 | { 27 | return storage[index]; 28 | } 29 | 30 | public void add(videoTask t) 31 | { 32 | try 33 | { 34 | if (this.count == maxCount) 35 | { 36 | throw new Exception("Overflow"); 37 | } else 38 | { 39 | this.storage[count++] = t; 40 | } 41 | } 42 | catch (Exception ex) 43 | { 44 | MessageBox.Show("Error: Could not add any more tasks. Original error: " + ex.Message); 45 | } 46 | } 47 | 48 | public int Count() 49 | { 50 | return this.maxCount; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/cmdCodeGenerator/taskSetting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ExpertVideoToolbox.cmdCodeGenerator 8 | { 9 | class taskSetting 10 | { 11 | public string name; 12 | 13 | public string encoder; // 视频编码器 14 | public string outputFormat; // 输出格式 15 | public string encoderSetting; // 参数 16 | 17 | public string audioEncoder; 18 | public string audioProfile; 19 | public string audioCodecMode; 20 | public string audioQuality; 21 | public string audioKbps; 22 | 23 | public taskSetting(string name, // 名称 24 | string e, // 视频编码器 25 | string of, // 输出格式 26 | string es, // 编码器参数 27 | string aE, // 音频编码器 28 | string aP, // 音频Profile 29 | string aMode, // 音频编码模式 30 | string aQ, // 音频质量或码率 31 | string aK) 32 | { 33 | this.encoder = e; 34 | this.outputFormat = of; 35 | this.encoderSetting = es; 36 | this.audioEncoder = aE; 37 | this.audioProfile = aP; 38 | this.audioCodecMode = aMode; 39 | this.audioQuality = aQ; 40 | this.audioKbps = aK; 41 | this.name = name; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/TaskManager/runningPool.cs: -------------------------------------------------------------------------------- 1 | using ExpertVideoToolbox.TaskManager; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ExpertVideoToolbox.taskManager 10 | { 11 | class runningPool 12 | { 13 | public int max; // 最大允许同时运行任务数 14 | public videoTask[] tPool; // 正在运行的任务数组 15 | public int currentCount; // 目前在运行的任务数 16 | 17 | private tasksQueue waitingQueue; 18 | private tasksQueue completedQueue; 19 | private tasksQueue failedQueue; 20 | 21 | public delegate void setFpsHandler(string fps); 22 | public event setFpsHandler setFpsEvent; 23 | 24 | public runningPool(int num, videoTask[] tasks) // 默认构造函数,同时运行1个任务 25 | { 26 | this.max = 1; 27 | this.currentCount = 0; 28 | this.tPool = new videoTask[this.max]; 29 | 30 | // 初始化queue 31 | this.waitingQueue = new tasksQueue(num, tasks); 32 | this.completedQueue = new tasksQueue(num); 33 | this.failedQueue = new tasksQueue(num); 34 | } 35 | 36 | public videoTask getTask() 37 | { 38 | // 取一个任务(取出后该任务即从队列中移除了) 39 | videoTask t = this.waitingQueue.pop(); 40 | if (t != null) 41 | { 42 | // 赋config值 43 | //t.setConfig(); 44 | 45 | return t; 46 | } 47 | return t; // 如果未取得task,返回null,交job处理 48 | } 49 | 50 | public void removeTask(videoTask t, bool isfailed) 51 | { 52 | // 移动到指定的队列 53 | if (!isfailed) 54 | { 55 | this.completedQueue.add(t); 56 | } 57 | else 58 | { 59 | this.failedQueue.add(t); 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本: 4.0.30319.34014 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ExpertVideoToolbox.Properties 12 | { 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// 返回此类使用的、缓存的 ResourceManager 实例。 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExpertVideoToolbox.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// 为所有资源查找重写当前线程的 CurrentUICulture 属性, 56 | /// 方法是使用此强类型资源类。 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/TaskManager/tasksQueue.cs: -------------------------------------------------------------------------------- 1 | using ExpertVideoToolbox.TaskManager; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ExpertVideoToolbox.taskManager 10 | { 11 | class tasksQueue 12 | { 13 | public int length; // 现在的长度(不包含空) 14 | public videoTask[] tQueue; // 队列 15 | public int max; // 最大长度 16 | 17 | private int front; // 队头指针 18 | private int rear; // 队尾指针 19 | 20 | private Object lockObj = new Object(); 21 | 22 | public tasksQueue(int taskLength, videoTask[] tq) 23 | { 24 | this.length = taskLength; 25 | this.max = taskLength; 26 | this.tQueue = new videoTask[taskLength + 1]; // 采用循环队列,浪费一个存储空间 27 | for (int i = 0; i < taskLength; i++) 28 | { 29 | this.tQueue[i] = tq[i]; 30 | } 31 | this.tQueue[taskLength] = null; 32 | this.front = 0; 33 | this.rear = taskLength; // 队尾指针指向队尾元素之后的一个空元素 34 | } 35 | 36 | public tasksQueue(int taskLength) // 只传入值时,队列为空 37 | { 38 | this.length = 0; 39 | this.max = taskLength; 40 | this.tQueue = new videoTask[taskLength + 1]; 41 | for (int i = 0; i < taskLength + 1; i++) 42 | { 43 | this.tQueue[i] = null; 44 | } 45 | this.front = this.rear = 0; 46 | } 47 | 48 | public videoTask pop() 49 | { 50 | lock(lockObj) // 锁定,不允许其他线程同时运行这段代码 51 | { 52 | // 取出队首Task并且从队列中移除 53 | if (this.front == this.rear) 54 | { 55 | return null; // 队列为空返回null由运行池处理 56 | } else 57 | { 58 | videoTask x = this.tQueue[this.front]; 59 | this.front = (this.front + 1) % (this.max + 1); 60 | 61 | this.length--; // 长度-1 62 | return x; 63 | } 64 | } 65 | } 66 | 67 | public void add(videoTask t) 68 | { 69 | lock(lockObj) 70 | { 71 | // 在队列中添加 72 | // 此处不判断队列是否为满,请在上层对象中加以判断 73 | this.tQueue[this.rear] = t; 74 | this.rear = (this.rear + 1) % (this.max + 1); 75 | this.length++; // 长度+1 76 | } 77 | } 78 | 79 | public void clear() 80 | { 81 | lock (lockObj) 82 | { 83 | // 清空队列 84 | for (int i = 0; i < this.max + 1; i++) 85 | { 86 | this.tQueue[i] = null; 87 | } 88 | this.front = this.rear = 0; 89 | this.length = 0; 90 | } 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/MainForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/RunningStatusForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/ExpertVideoToolbox.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6DE600BF-C56C-4E2D-B1DD-73217764A806} 8 | WinExe 9 | Properties 10 | ExpertVideoToolbox 11 | ExpertVideoToolbox 12 | v4.5 13 | 512 14 | 发布\ 15 | true 16 | Disk 17 | false 18 | Foreground 19 | 7 20 | Days 21 | false 22 | false 23 | true 24 | 0 25 | 1.0.0.%2a 26 | false 27 | false 28 | true 29 | 30 | 31 | AnyCPU 32 | true 33 | full 34 | false 35 | bin\Debug\ 36 | DEBUG;TRACE 37 | prompt 38 | 4 39 | 40 | 41 | AnyCPU 42 | pdbonly 43 | true 44 | bin\Release\ 45 | TRACE 46 | prompt 47 | 4 48 | 49 | 50 | 51 | ..\packages\MediaInfoDotNet.0.7.79.40925\lib\net45\MediaInfoDotNet.dll 52 | True 53 | 54 | 55 | False 56 | ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Form 76 | 77 | 78 | MainForm.cs 79 | 80 | 81 | 82 | 83 | 84 | Form 85 | 86 | 87 | RunningStatusForm.cs 88 | 89 | 90 | 91 | 92 | 93 | 94 | MainForm.cs 95 | 96 | 97 | ResXFileCodeGenerator 98 | Resources.Designer.cs 99 | Designer 100 | 101 | 102 | True 103 | Resources.resx 104 | 105 | 106 | RunningStatusForm.cs 107 | 108 | 109 | Always 110 | 111 | 112 | 113 | SettingsSingleFileGenerator 114 | Settings.Designer.cs 115 | 116 | 117 | True 118 | Settings.settings 119 | True 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | Always 128 | 129 | 130 | Always 131 | 132 | 133 | 134 | 135 | False 136 | Microsoft .NET Framework 4.5 %28x86 和 x64%29 137 | true 138 | 139 | 140 | False 141 | .NET Framework 3.5 SP1 Client Profile 142 | false 143 | 144 | 145 | False 146 | .NET Framework 3.5 SP1 147 | false 148 | 149 | 150 | 151 | 152 | IncBuildNo.exe "$(PROJECTDIR)\Properties\AssemblyInfo.cs" "\[assembly: AssemblyFileVersion\(\"\d+\.\d+\.\d+\.(\d+)" 1 153 | 154 | 161 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/ProcessControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Management; 6 | using System.Runtime.InteropServices; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace ExpertVideoToolbox 13 | { 14 | public class ProcessControl 15 | { 16 | const int IDLE = 64; 17 | const int BELOWNORMAL = 16384; 18 | const int NORMAL = 32; 19 | const int ABOVENORMAL = 32768; 20 | const int HIGHPRIORITY = 128; 21 | const int REALTIME = 256; 22 | 23 | private string processName; 24 | 25 | public int numberOfLogicalProcessors = -1; 26 | 27 | private Process cmdProcess; 28 | 29 | public void setProcessName(string name) 30 | { 31 | this.processName = name; 32 | } 33 | 34 | public ProcessControl() 35 | { 36 | cmdProcess = new System.Diagnostics.Process(); 37 | 38 | cmdProcess.StartInfo.FileName = "cmd"; 39 | 40 | // 必须禁用操作系统外壳程序 41 | cmdProcess.StartInfo.UseShellExecute = false; 42 | cmdProcess.StartInfo.CreateNoWindow = true; 43 | cmdProcess.StartInfo.RedirectStandardInput = true; 44 | cmdProcess.Start(); 45 | } 46 | 47 | // 耗时操作 48 | public int GetNumberOfLogicalProcessors() 49 | { 50 | return Environment.ProcessorCount; 51 | } 52 | 53 | // 设置进程的优先级 54 | public void SetProcessPriority(int priority) 55 | { 56 | string command = "wmic process where name=" + "\"" + processName + "\"" + " CALL setpriority "; 57 | switch(priority) 58 | { 59 | case IDLE: 60 | command += IDLE.ToString(); 61 | break; 62 | case BELOWNORMAL: 63 | command += BELOWNORMAL.ToString(); 64 | break; 65 | case NORMAL: 66 | command += NORMAL.ToString(); 67 | break; 68 | case ABOVENORMAL: 69 | command += ABOVENORMAL.ToString(); 70 | break; 71 | case HIGHPRIORITY: 72 | command += HIGHPRIORITY.ToString(); 73 | break; 74 | case REALTIME: 75 | command += REALTIME.ToString(); 76 | break; 77 | } 78 | 79 | MaintainCmdProcessRunning(); 80 | this.cmdProcess.StandardInput.WriteLine(command); 81 | } 82 | 83 | // 设置进程的cpu相关性,限制视频编码器占用逻辑处理器数为满载的1/4(默认值,且至少有一个逻辑处理器) 84 | public void ReduceProcessCpuUsage(int slice = 4) 85 | { 86 | string command = "PowerShell \"$Process = Get-Process " + changeFileExtName(this.processName) + "; $Process.ProcessorAffinity="; 87 | 88 | int affinity = 0; 89 | int k = this.numberOfLogicalProcessors; 90 | 91 | if (slice <= 1) 92 | { 93 | affinity = (int)Math.Pow(2, k) - 1; 94 | } 95 | else 96 | { 97 | int numberOfLimitedLogicalProcessors = k / slice; 98 | if (numberOfLimitedLogicalProcessors < 1) 99 | { 100 | numberOfLimitedLogicalProcessors = 1; 101 | } 102 | 103 | // 设置affinity的值,如有8个处理器,affinity则是8位二进制数,每一位上0、1表示该处理器的开关状态,越高位表示的CPU编号越大。 104 | // 如:测试机i7 四核八线程视为八个处理器,10100000表示打开了CPU7和CPU5 105 | // 在PowerShell命令中affinity值要转换为十进制数 106 | k--; 107 | for (int i = 0; i < numberOfLimitedLogicalProcessors; i++) 108 | { 109 | affinity += (int)Math.Pow(2, k); 110 | k -= 2; 111 | } 112 | } 113 | 114 | command += affinity.ToString() + "\""; 115 | 116 | MaintainCmdProcessRunning(); 117 | this.cmdProcess.StandardInput.WriteLine(command); 118 | } 119 | 120 | public void ResumeDefalutCpuAffinity() 121 | { 122 | ReduceProcessCpuUsage(1); // 设置进程使用的逻辑处理器数量为总数除以1,即恢复到满载状态 123 | } 124 | 125 | // 检查进程是否在运行,如果不是则重新开始 126 | private void MaintainCmdProcessRunning() 127 | { 128 | if (this.cmdProcess.HasExited) // 如果进程已经退出则再次开始 129 | { 130 | this.cmdProcess.Start(); 131 | } 132 | } 133 | 134 | private string changeFileExtName(string originFp, string ext = "") 135 | { 136 | string[] s = originFp.Split(new char[] { '.' }); 137 | int length = s.Length; 138 | s[length - 1] = ext; 139 | string finalFileName = ""; 140 | for (int i = 0; i < length; i++) 141 | { 142 | finalFileName += s[i]; 143 | if (i != length - 1) 144 | { 145 | finalFileName += "."; 146 | } 147 | } 148 | if (string.IsNullOrWhiteSpace(ext)) // 当需要的扩展名为空时,去除字符串最后位置的一个点 149 | { 150 | finalFileName = finalFileName.Substring(0, finalFileName.Length - 1); 151 | } 152 | return finalFileName; 153 | } 154 | 155 | /// 156 | /// A utility class to determine a process parent. 157 | /// 158 | [StructLayout(LayoutKind.Sequential)] 159 | public struct ParentProcessUtilities 160 | { 161 | // These members must match PROCESS_BASIC_INFORMATION 162 | internal IntPtr Reserved1; 163 | internal IntPtr PebBaseAddress; 164 | internal IntPtr Reserved2_0; 165 | internal IntPtr Reserved2_1; 166 | internal IntPtr UniqueProcessId; 167 | internal IntPtr InheritedFromUniqueProcessId; 168 | 169 | [DllImport("ntdll.dll")] 170 | private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength); 171 | 172 | /// 173 | /// Gets the parent process of the current process. 174 | /// 175 | /// An instance of the Process class. 176 | public static Process GetParentProcess() 177 | { 178 | return GetParentProcess(Process.GetCurrentProcess().Handle); 179 | } 180 | 181 | /// 182 | /// Gets the parent process of specified process. 183 | /// 184 | /// The process id. 185 | /// An instance of the Process class. 186 | public static Process GetParentProcess(int id) 187 | { 188 | Process process = Process.GetProcessById(id); 189 | return GetParentProcess(process.Handle); 190 | } 191 | 192 | /// 193 | /// Gets the parent process of a specified process. 194 | /// 195 | /// The process handle. 196 | /// An instance of the Process class or null if an error occurred. 197 | public static Process GetParentProcess(IntPtr handle) 198 | { 199 | ParentProcessUtilities pbi = new ParentProcessUtilities(); 200 | int returnLength; 201 | int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength); 202 | if (status != 0) 203 | return null; 204 | 205 | try 206 | { 207 | return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32()); 208 | } 209 | catch (ArgumentException) 210 | { 211 | // not found 212 | return null; 213 | } 214 | } 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/RunningStatusForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Diagnostics; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Management; 9 | using System.Text; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | using System.Windows.Forms; 13 | 14 | namespace ExpertVideoToolbox 15 | { 16 | public partial class RunningStatusForm : Form 17 | { 18 | const int IDLE = 64; 19 | const int BELOWNORMAL = 16384; 20 | const int NORMAL = 32; 21 | const int ABOVENORMAL = 32768; 22 | const int HIGHPRIORITY = 128; 23 | const int REALTIME = 256; 24 | 25 | delegate void SetTextCallback(string commandLine); 26 | 27 | public delegate void AbortHandler(); //声明委托 28 | public event AbortHandler AbortEvent; //声明事件 29 | 30 | public delegate void ClosingHandler(); //声明委托 31 | public event ClosingHandler ClosingEvent; //声明事件 32 | public Process process = null; 33 | 34 | public int PID; 35 | 36 | const int AUDIOENCODE = 0; 37 | const int VIDEOENCODE = 1; 38 | const int MUXER = 2; 39 | const int AUDIOCOPY = 3; 40 | 41 | public string encodingProgram = ""; 42 | 43 | public ProcessControl processControl; 44 | 45 | public RunningStatusForm() 46 | { 47 | this.processControl = new ProcessControl(); 48 | InitializeComponent(); 49 | } 50 | 51 | public void setPercent(string percent, int mode = VIDEOENCODE) 52 | { 53 | if (!percent.Contains("-")) 54 | { 55 | if (mode == VIDEOENCODE) 56 | { 57 | double videoEncodePst = Convert.ToDouble(percent) / 100.0; 58 | double globelPst100x = 1.0 + 98.0 * videoEncodePst; 59 | this.progress.Value = (int)globelPst100x; 60 | this.progressLabel.Text = globelPst100x.ToString("0.0") + "%"; 61 | } 62 | else 63 | { 64 | this.progressLabel.Text = percent + "%"; // 这一模式下传进来的字符串已经保留一位小数 65 | } 66 | 67 | } 68 | else 69 | { 70 | if (String.Equals(percent, "-1")) 71 | { 72 | this.progress.Value = 0; 73 | } else if (String.Equals(percent, "-2")) 74 | { 75 | this.progress.Value = 99; 76 | } else 77 | { 78 | this.progress.Value = 100; 79 | } 80 | this.progressLabel.Text = ""; 81 | } 82 | } 83 | 84 | public void setTime(string time) 85 | { 86 | this.currentPostionDataTB.Text = time; 87 | this.currentPostionDataTB.Select(this.currentPostionDataTB.TextLength, 0); 88 | } 89 | 90 | public void setFps(string fps) 91 | { 92 | this.fpsDataTB.Text = fps; 93 | } 94 | 95 | public void setEta(string eta) 96 | { 97 | this.estETADataTB.Text = eta; 98 | } 99 | 100 | public void setEstKbps(string kbps) 101 | { 102 | this.estKbpsDataTB.Text = kbps; 103 | } 104 | 105 | private void RunningStatusForm_FormClosed(object sender, FormClosedEventArgs e) 106 | { 107 | if (process != null) 108 | { 109 | process.Close(); 110 | } 111 | } 112 | public void setStopBtnState(bool enabled) 113 | { 114 | this.stopBtn.Enabled = enabled; 115 | } 116 | 117 | public string getCurrentTimeText() 118 | { 119 | return this.currentPostionDataTB.Text; 120 | } 121 | 122 | public void setWindowTitle(string title) 123 | { 124 | this.Text = title; 125 | } 126 | 127 | public void setStatusBarFilesCountLabel(int finished, int all) 128 | { 129 | string suffix = this.filesCountLabel.ForeColor == Color.Red ? " (存在失败任务) 请查询日志" : ""; 130 | string s = finished.ToString() + "/" + all.ToString() + suffix; 131 | this.filesCountLabel.Text = s; 132 | } 133 | 134 | public void setStatusBarLabelTextColorRED() 135 | { 136 | this.filesCountLabel.ForeColor = Color.Red; 137 | } 138 | 139 | public void SetTaskStepsLabel(string tss) 140 | { 141 | this.taskStepsLabel.Text = tss; 142 | } 143 | 144 | public void SetTaskStepsLabel(bool finish, int currentStepIndex = 0, int totalStepsCount = 0, int mode = 0) 145 | { 146 | string tss = ""; 147 | if (finish) 148 | { 149 | tss = "已完成"; 150 | } 151 | else 152 | { 153 | tss = "正在进行:步骤 " + currentStepIndex.ToString() + "/" + totalStepsCount.ToString() + " - "; 154 | string modeName = ""; 155 | switch (mode) 156 | { 157 | case AUDIOENCODE: 158 | modeName = "音频编码"; 159 | break; 160 | case AUDIOCOPY: 161 | modeName = "复制音频"; 162 | break; 163 | case VIDEOENCODE: 164 | modeName = "视频编码"; 165 | break; 166 | case MUXER: 167 | modeName = "封装"; 168 | break; 169 | default: 170 | break; 171 | } 172 | tss += modeName; 173 | } 174 | 175 | this.SetTaskStepsLabel(tss); 176 | } 177 | 178 | private void stopBtn_Click(object sender, EventArgs e) 179 | { 180 | DialogResult dr = MessageBox.Show("确定要中止转换吗?", "确认中止", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); 181 | if (dr == DialogResult.OK) 182 | { 183 | // 点确定的代码 184 | // 传入字符串不可加.exe 185 | //Process[] p = Process.GetProcessesByName(this.encodingProgram.Substring(0, this.encodingProgram.Length - 4)); 186 | 187 | //int count = p.Length; 188 | //for (int i = 0; i < count; i++) 189 | //{ 190 | // p[i].Kill(); 191 | //} 192 | //this.stopBtn.Enabled = false; 193 | 194 | KillProcessAndChildren(PID); 195 | 196 | string stopWindowTitle = "用户中止操作"; 197 | this.setWindowTitle(stopWindowTitle); 198 | 199 | AbortEvent(); 200 | ClosingEvent(); 201 | 202 | this.stopBtn.Enabled = false; 203 | } 204 | else 205 | { 206 | //点取消的代码 207 | } 208 | } 209 | 210 | /** 211 | * 传入参数:父进程id 212 | * 功能:根据父进程id,杀死与之相关的进程树 213 | */ 214 | private static void KillProcessAndChildren(int pid) 215 | { 216 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid); 217 | ManagementObjectCollection moc = searcher.Get(); 218 | foreach (ManagementObject mo in moc) 219 | { 220 | KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"])); 221 | } 222 | try 223 | { 224 | Process proc = Process.GetProcessById(pid); 225 | Console.WriteLine(pid); 226 | proc.Kill(); 227 | } 228 | catch (ArgumentException) 229 | { 230 | /* process already exited */ 231 | } 232 | } 233 | private void RunningStatusForm_FormClosing(object sender, FormClosingEventArgs e) 234 | { 235 | ClosingEvent(); 236 | } 237 | 238 | private void RunningStatusForm_Shown(object sender, EventArgs e) 239 | { 240 | 241 | } 242 | 243 | // 选择低速模式 244 | private void lowSpeedBtn_Click(object sender, EventArgs e) 245 | { 246 | if (this.lowSpeedBtn.ForeColor != Color.White) 247 | { 248 | this.lowSpeedBtn.BackColor = Color.FromArgb(253, 105, 89); 249 | this.lowSpeedBtn.ForeColor = Color.White; 250 | 251 | this.fullSpeedBtn.BackColor = Button.DefaultBackColor; 252 | this.fullSpeedBtn.ForeColor = Button.DefaultForeColor; 253 | 254 | this.lowSpeedBtn.Enabled = false; 255 | this.fullSpeedBtn.Enabled = false; 256 | 257 | this.processControl.ReduceProcessCpuUsage(); 258 | 259 | Thread.Sleep(1500); 260 | 261 | this.lowSpeedBtn.Enabled = true; 262 | this.fullSpeedBtn.Enabled = true; 263 | } 264 | } 265 | 266 | // 选择正常模式 267 | private void fullSpeedBtn_Click(object sender, EventArgs e) 268 | { 269 | if (this.fullSpeedBtn.ForeColor != Color.White) 270 | { 271 | this.fullSpeedBtn.BackColor = Color.FromArgb(18, 173, 30); 272 | this.fullSpeedBtn.ForeColor = Color.White; 273 | 274 | this.lowSpeedBtn.BackColor = Button.DefaultBackColor; 275 | this.lowSpeedBtn.ForeColor = Button.DefaultForeColor; 276 | 277 | this.lowSpeedBtn.Enabled = false; 278 | this.fullSpeedBtn.Enabled = false; 279 | 280 | this.processControl.ResumeDefalutCpuAffinity(); 281 | 282 | Thread.Sleep(1500); 283 | 284 | this.lowSpeedBtn.Enabled = true; 285 | this.fullSpeedBtn.Enabled = true; 286 | } 287 | } 288 | 289 | public void HideVideoEncoderSetting() 290 | { 291 | this.encoderPriority.Visible = false; 292 | this.priorityCB.Visible = false; 293 | this.fullSpeedBtn.Visible = false; 294 | this.lowSpeedBtn.Visible = false; 295 | } 296 | 297 | public void ShowVideoEncoderSetting() 298 | { 299 | this.encoderPriority.Visible = true; 300 | this.priorityCB.Visible = true; 301 | this.fullSpeedBtn.Visible = true; 302 | this.lowSpeedBtn.Visible = true; 303 | 304 | this.fullSpeedBtn.BackColor = Color.FromArgb(18, 173, 30); 305 | this.fullSpeedBtn.ForeColor = Color.White; 306 | 307 | this.lowSpeedBtn.BackColor = Button.DefaultBackColor; 308 | this.lowSpeedBtn.ForeColor = Button.DefaultForeColor; 309 | 310 | this.priorityCB.SelectedIndex = 1; 311 | this.priorityCB.SelectedIndex = 0; 312 | } 313 | 314 | private void priorityCB_SelectedIndexChanged(object sender, EventArgs e) 315 | { 316 | this.processControl.setProcessName(this.encodingProgram); 317 | ComboBox comboBox = (ComboBox)sender; 318 | if (String.Equals(comboBox.Text, "低")) 319 | { 320 | this.processControl.SetProcessPriority(IDLE); 321 | } 322 | else if (String.Equals(comboBox.Text, "低于正常")) 323 | { 324 | this.processControl.SetProcessPriority(BELOWNORMAL); 325 | } 326 | else if (String.Equals(comboBox.Text, "正常")) 327 | { 328 | this.processControl.SetProcessPriority(NORMAL); 329 | } 330 | else if (String.Equals(comboBox.Text, "高于正常")) 331 | { 332 | this.processControl.SetProcessPriority(ABOVENORMAL); 333 | } 334 | else if (String.Equals(comboBox.Text, "高")) 335 | { 336 | this.processControl.SetProcessPriority(HIGHPRIORITY); 337 | } 338 | else if (String.Equals(comboBox.Text, "实时")) 339 | { 340 | this.processControl.SetProcessPriority(REALTIME); 341 | } 342 | } 343 | 344 | private void fullSpeedBtn_VisibleChanged(object sender, EventArgs e) 345 | { 346 | if (((Button)sender).Visible == true && this.processControl.numberOfLogicalProcessors == -1) 347 | { 348 | this.fullSpeedBtn.Enabled = false; 349 | this.lowSpeedBtn.Enabled = false; 350 | InitializeNumberOfLogicalProcessors(); 351 | } 352 | } 353 | 354 | private void InitializeNumberOfLogicalProcessors() 355 | { 356 | this.processControl.numberOfLogicalProcessors = this.processControl.GetNumberOfLogicalProcessors(); 357 | this.fullSpeedBtn.Enabled = true; 358 | this.lowSpeedBtn.Enabled = true; 359 | } 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/cmdCodeGenerator/cmdCode.cs: -------------------------------------------------------------------------------- 1 | using MediaInfoLib; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Forms; 9 | 10 | namespace ExpertVideoToolbox.cmdCodeGenerator 11 | { 12 | class cmdCode 13 | { 14 | const int AUDIOENCODE = 0; 15 | const int VIDEOENCODE = 1; 16 | const int MUXER = 2; 17 | const int AUDIOCOPY = 3; 18 | const int DELETEVIDEOTEMP = 4; 19 | const int DELETEAUDIOTEMP = 5; 20 | 21 | const int ONLYVIDEO = 0; 22 | const int SUPPRESSAUDIO = 1; 23 | const int COPYAUDIO = 2; 24 | 25 | const int NORMAL = 0; 26 | const int AVS = 1; 27 | const int VPY = 2; 28 | 29 | private string filePath; 30 | private taskSetting ts; 31 | private string outputFolderPath; 32 | private string outputAudioFormat; 33 | 34 | private string avsVideoPath; 35 | 36 | public cmdCode(string fp, taskSetting t, string ofp) 37 | { 38 | this.filePath = fp; 39 | this.ts = t; 40 | this.outputFolderPath = ofp; 41 | } 42 | 43 | public void setFilePath(string fp) 44 | { 45 | this.filePath = fp; 46 | } 47 | 48 | public int taskType() 49 | { 50 | if (String.Equals(this.ts.audioEncoder, "无音频流")) 51 | { 52 | return ONLYVIDEO; 53 | } else if (String.Equals(this.ts.audioEncoder, "复制音频流")) 54 | { 55 | // 判断是否为avs文件 56 | 57 | string ext = this.getFileExtName(this.filePath); 58 | if (String.Equals(ext, "avs", StringComparison.CurrentCultureIgnoreCase)) 59 | { 60 | string[] avsLines = File.ReadAllLines(this.filePath); 61 | for (int i = 0; i < avsLines.Length; i++) 62 | { 63 | int startIdx = avsLines[i].IndexOf("Source(\""); 64 | int endIdx; 65 | if (startIdx != -1) 66 | { 67 | endIdx = avsLines[i].IndexOf("\")"); 68 | startIdx += 8; 69 | this.avsVideoPath = avsLines[i].Substring(startIdx, endIdx - startIdx); 70 | break; 71 | } 72 | } 73 | MediaInfo MI = new MediaInfo(); 74 | string duration; 75 | MI.Open(this.avsVideoPath); 76 | duration = MI.Get(StreamKind.Audio, 0, 69); 77 | this.outputAudioFormat = MI.Get(StreamKind.Audio, 0, "Format"); 78 | if (String.IsNullOrWhiteSpace(duration)) 79 | { 80 | return ONLYVIDEO; 81 | } 82 | else 83 | { 84 | if (CheckBoxCompatibility(this.outputAudioFormat, this.ts.outputFormat)) 85 | { 86 | return COPYAUDIO; 87 | } 88 | else 89 | { 90 | this.outputAudioFormat = "aac"; 91 | return SUPPRESSAUDIO; 92 | } 93 | } 94 | } 95 | else 96 | { 97 | MediaInfo MI = new MediaInfo(); 98 | string duration; 99 | MI.Open(this.filePath); 100 | duration = MI.Get(StreamKind.Audio, 0, 69); 101 | this.outputAudioFormat = MI.Get(StreamKind.Audio, 0, "Format"); 102 | if (String.IsNullOrWhiteSpace(duration)) 103 | { 104 | return ONLYVIDEO; 105 | } 106 | else 107 | { 108 | if (CheckBoxCompatibility(this.outputAudioFormat, this.ts.outputFormat)) 109 | { 110 | return COPYAUDIO; 111 | } 112 | else 113 | { 114 | this.outputAudioFormat = "aac"; 115 | return SUPPRESSAUDIO; 116 | } 117 | } 118 | } 119 | } else 120 | { 121 | // 判断是否为avs文件 122 | 123 | string ext = this.getFileExtName(this.filePath); 124 | if (String.Equals(ext, "avs", StringComparison.CurrentCultureIgnoreCase)) 125 | { 126 | string[] avsLines = File.ReadAllLines(this.filePath); 127 | for (int i = 0; i < avsLines.Length; i++) 128 | { 129 | int startIdx = avsLines[i].IndexOf("Source(\""); 130 | int endIdx; 131 | if (startIdx != -1) 132 | { 133 | endIdx = avsLines[i].IndexOf("\")"); 134 | startIdx += 8; 135 | this.avsVideoPath = avsLines[i].Substring(startIdx, endIdx - startIdx); 136 | break; 137 | } 138 | } 139 | MediaInfo MI = new MediaInfo(); 140 | string duration; 141 | MI.Open(this.avsVideoPath); 142 | duration = MI.Get(StreamKind.Audio, 0, 69); 143 | if (String.IsNullOrWhiteSpace(duration)) 144 | { 145 | return ONLYVIDEO; 146 | } 147 | else 148 | { 149 | this.outputAudioFormat = "aac"; 150 | return SUPPRESSAUDIO; 151 | } 152 | } 153 | else 154 | { 155 | MediaInfo MI = new MediaInfo(); 156 | string duration; 157 | MI.Open(this.filePath); 158 | duration = MI.Get(StreamKind.Audio, 0, 69); 159 | if (String.IsNullOrWhiteSpace(duration)) 160 | { 161 | return ONLYVIDEO; 162 | } 163 | else 164 | { 165 | this.outputAudioFormat = "aac"; 166 | return SUPPRESSAUDIO; 167 | } 168 | } 169 | } 170 | } 171 | 172 | public string getAudioSource() 173 | { 174 | string audioSource = String.IsNullOrEmpty(this.avsVideoPath) ? this.filePath : this.avsVideoPath; 175 | return audioSource; 176 | } 177 | 178 | public string cmdCodeGenerate(int mode, int vmode = 0) 179 | { 180 | string fp = this.filePath; 181 | string audioSource = String.IsNullOrEmpty(this.avsVideoPath) ? fp : this.avsVideoPath; 182 | 183 | string qaacPath = System.Windows.Forms.Application.StartupPath + "\\tools\\qaac\\qaac.exe"; 184 | string ffmpegPath = System.Windows.Forms.Application.StartupPath + "\\tools\\ffmpeg\\ffmpeg.exe"; 185 | string x26xPath = System.Windows.Forms.Application.StartupPath + "\\tools\\x26x\\" + ts.encoder; 186 | string mp4BoxPath = System.Windows.Forms.Application.StartupPath + "\\tools\\mp4Box\\MP4Box.exe"; 187 | //string lsmashRemuxerPath = System.Windows.Forms.Application.StartupPath + "\\tools\\L-Smash\\remuxer.exe"; 188 | string mkvmergePath = System.Windows.Forms.Application.StartupPath + "\\tools\\mkvmerge\\mkvmerge.exe"; 189 | string avsPath = System.Windows.Forms.Application.StartupPath + "\\tools\\avs\\avs4x265.exe"; 190 | 191 | string code = ""; 192 | 193 | string suffix = this.taskType() == ONLYVIDEO ? "_evt" : "_temp"; 194 | if (String.IsNullOrWhiteSpace(this.outputFolderPath)) 195 | { 196 | this.outputFolderPath = getPureFolderName(fp); 197 | } 198 | 199 | string outputFilePath = this.outputFolderPath + getPureFileName(fp) + "_" + this.ts.name + "." + ts.outputFormat; 200 | string videoTempExt = ts.encoder == "x265-10bit.exe" ? ".hevc" : ".264"; 201 | string videoTempPath = this.outputFolderPath + ts.name + "_temp" + videoTempExt; 202 | string mp4BoxTempPath = this.outputFolderPath.Substring(0, this.outputFolderPath.Length - 1); // tmp路径末尾不能有斜杠,否则parse出错(坑爹的gpac) 203 | string audioTempPath = this.outputFolderPath + getPureFileName(fp) + "_audioTemp." + this.outputAudioFormat; 204 | 205 | switch (mode) 206 | { 207 | case VIDEOENCODE: 208 | switch (vmode) 209 | { 210 | case NORMAL: 211 | string y4m = ts.encoder == "x265-10bit.exe" ? " --y4m " : " --demuxer y4m "; 212 | code = "\"" + ffmpegPath + "\"" + " -i " + "\"" + fp + "\"" + " -strict -1 -f yuv4mpegpipe -an - | " 213 | + "\"" + x26xPath + "\"" + y4m + ts.encoderSetting + " -o " + "\"" + videoTempPath + "\"" + " -"; 214 | break; 215 | case AVS: 216 | // Example: 217 | // "C:\Users\fdws\Downloads\avs4x265.exe" -L 218 | // "C:\Users\fdws\Desktop\Trans\EVT_alpha\tools\x26x\x264_64-10bit.exe" 219 | // --crf 24.5 -o "C:\Users\fdws\Desktop\Trans\01_batch.mp4" "C:\Users\fdws\Desktop\Trans\01.avs" 220 | 221 | code = "\"" + avsPath + "\"" + " -L " + "\"" + x26xPath + "\" " + ts.encoderSetting + " -o " + "\"" + videoTempPath + "\"" 222 | + " \"" + fp + "\""; 223 | break; 224 | default: 225 | break; 226 | } 227 | 228 | break; 229 | case AUDIOCOPY: 230 | code = "\"" + ffmpegPath + "\"" + " -i " + "\"" + audioSource 231 | + "\"" + " -vn -sn -async 1 -c:a copy -y -map 0:a:0 " + "\"" + audioTempPath + "\""; 232 | break; 233 | case MUXER: 234 | if (String.Equals(ts.outputFormat, "mp4", StringComparison.CurrentCultureIgnoreCase)) 235 | { 236 | if (this.taskType() == ONLYVIDEO) 237 | { 238 | code = "\"" + mp4BoxPath + "\"" + " -add " + "\"" + videoTempPath + "\"" + 239 | " " + "\"" + outputFilePath + "\"" + " -tmp " + "\"" + mp4BoxTempPath + "\""; 240 | } 241 | else 242 | { 243 | code = "\"" + mp4BoxPath + "\"" + " -add " + "\"" + videoTempPath + "\"" + 244 | " -add " + "\"" + audioTempPath + "\"" + " " + "\"" + outputFilePath + "\"" + " -tmp " + "\"" + mp4BoxTempPath + "\""; 245 | } 246 | 247 | // tmp文件夹设定在输出位置,不设置的话默认C盘,当C盘空间不足以存放一个视频压制后的.mp4文件时任务就会失败 248 | } 249 | else if (String.Equals(ts.outputFormat, "mkv", StringComparison.CurrentCultureIgnoreCase)) 250 | { 251 | if (this.taskType() == ONLYVIDEO) 252 | { 253 | code += "\"" + mkvmergePath + "\"" + " -o " + "\"" + outputFilePath + "\"" + " " + "\"" + videoTempPath + 254 | "\""; 255 | } 256 | else 257 | { 258 | code += "\"" + mkvmergePath + "\"" + " -o " + "\"" + outputFilePath + "\"" + " " + "\"" + videoTempPath + 259 | "\"" + " " + "\"" + audioTempPath + "\""; 260 | } 261 | } 262 | 263 | break; 264 | 265 | case DELETEVIDEOTEMP: 266 | code = videoTempPath; 267 | break; 268 | case DELETEAUDIOTEMP: 269 | code = audioTempPath; 270 | break; 271 | 272 | case AUDIOENCODE: 273 | if (String.Equals(this.ts.audioEncoder, "qaac", StringComparison.CurrentCultureIgnoreCase) 274 | || String.Equals(this.ts.audioEncoder, "复制音频流", StringComparison.CurrentCultureIgnoreCase)) 275 | { 276 | code = "\"" + ffmpegPath + "\"" + " -i " + "\"" + audioSource + "\"" + " -vn -sn -v 0 -async 1 -c:a pcm_s16le -f wav pipe:|" + "\"" + qaacPath + "\"" + " - --ignorelength"; 277 | if (string.Equals(this.ts.audioProfile, "HE-AAC")) 278 | { 279 | code += " --he"; 280 | } 281 | 282 | if (string.Equals(this.ts.audioProfile, "ALAC")) 283 | { 284 | code += " -A"; 285 | break; 286 | } 287 | 288 | if (string.Equals(this.ts.audioCodecMode, "TVBR")) 289 | { 290 | code += " -V " + this.ts.audioQuality.ToString(); 291 | } 292 | else if (string.Equals(this.ts.audioCodecMode, "CVBR")) 293 | { 294 | code += " -v " + this.ts.audioKbps.ToString(); 295 | } 296 | else if (string.Equals(this.ts.audioCodecMode, "ABR")) 297 | { 298 | code += " -a " + this.ts.audioKbps.ToString(); 299 | } 300 | else if (string.Equals(this.ts.audioCodecMode, "CBR")) 301 | { 302 | code += " -c " + this.ts.audioKbps.ToString(); 303 | } 304 | 305 | code += " -o " + "\"" + audioTempPath + "\""; 306 | } 307 | break; 308 | default: 309 | break; 310 | } 311 | 312 | //code = "\"" + ffmpegPath + "\"" + " -i " + "\"" + fp + "\"" + " -vn -sn -v 0 -async 1 -c:a pcm_s16le -f wav pipe:|" + "\"" + qaacPath + "\"" + " - --ignorelength"; 313 | 314 | //MessageBox.Show(code); 315 | return code; 316 | } 317 | 318 | private bool CheckBoxCompatibility(string audioFormat, string fileFormat) 319 | { 320 | if (String.Equals(fileFormat, "mkv", StringComparison.CurrentCultureIgnoreCase)) 321 | { 322 | if (String.Equals(audioFormat, "AAC", StringComparison.CurrentCultureIgnoreCase) 323 | || String.Equals(audioFormat, "FLAC", StringComparison.CurrentCultureIgnoreCase) 324 | || String.Equals(audioFormat, "DTS", StringComparison.CurrentCultureIgnoreCase)) 325 | { 326 | return true; 327 | } 328 | else 329 | { 330 | return false; 331 | } 332 | } 333 | else if (String.Equals(fileFormat, "mp4", StringComparison.CurrentCultureIgnoreCase)) 334 | { 335 | if (String.Equals(audioFormat, "AAC", StringComparison.CurrentCultureIgnoreCase)) 336 | { 337 | return true; 338 | } 339 | else 340 | { 341 | return false; 342 | } 343 | } 344 | return false; 345 | } 346 | 347 | private bool losslessCheckByExtension(string extension) 348 | { 349 | string[] losslessExt = { "wav", "flac", "ape" }; 350 | return this.multiStringEqualCheck(losslessExt, extension); 351 | } 352 | 353 | private bool multiStringEqualCheck(string[] targets, string source) 354 | { 355 | int len = targets.Length; 356 | for (int i = 0; i < len; i++) 357 | { 358 | if (string.Equals(targets[i], source)) 359 | { 360 | return true; 361 | } 362 | } 363 | return false; 364 | } 365 | 366 | private string changeFileExtName(string originFp, string ext = "") 367 | { 368 | string[] s = originFp.Split(new char[] { '.' }); 369 | int length = s.Length; 370 | s[length - 1] = ext; 371 | string finalFileName = ""; 372 | for (int i = 0; i < length; i++) 373 | { 374 | finalFileName += s[i]; 375 | if (i != length - 1) 376 | { 377 | finalFileName += "."; 378 | } 379 | } 380 | if (string.IsNullOrWhiteSpace(ext)) // 当需要的扩展名为空时,去除字符串最后位置的一个点 381 | { 382 | finalFileName = finalFileName.Substring(0, finalFileName.Length - 1); 383 | } 384 | return finalFileName; 385 | } 386 | 387 | // 获得纯净的文件名,不含路径和扩展名和点 388 | private string getPureFileName(string fp) 389 | { 390 | string[] s = fp.Split(new char[] { '\\' }); 391 | int length = s.Length; 392 | string fileNameWithExt = s[length - 1]; 393 | return changeFileExtName(fileNameWithExt, ""); 394 | } 395 | 396 | private string getPureFolderName(string fp) 397 | { 398 | string[] s = fp.Split(new char[] { '\\' }); 399 | int length = s.Length; 400 | string dest = ""; 401 | for (int i = 0; i < length - 1; i++) 402 | { 403 | dest += s[i]; 404 | dest += "\\"; 405 | } 406 | return dest; 407 | } 408 | 409 | private string getFileExtName(string originFp) 410 | { 411 | string[] s = originFp.Split(new char[] { '.' }); 412 | int length = s.Length; 413 | return s[length - 1]; 414 | } 415 | } 416 | } 417 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/RunningStatusForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ExpertVideoToolbox 2 | { 3 | partial class RunningStatusForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.stopBtn = new System.Windows.Forms.Button(); 32 | this.statusStrip1 = new System.Windows.Forms.StatusStrip(); 33 | this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel(); 34 | this.filesCountLabel = new System.Windows.Forms.ToolStripStatusLabel(); 35 | this.progress = new System.Windows.Forms.ProgressBar(); 36 | this.estETADataTB = new System.Windows.Forms.TextBox(); 37 | this.estETALabel = new System.Windows.Forms.Label(); 38 | this.currentPositionLabel = new System.Windows.Forms.Label(); 39 | this.fpsDataTB = new System.Windows.Forms.TextBox(); 40 | this.fpsLabel = new System.Windows.Forms.Label(); 41 | this.currentPostionDataTB = new System.Windows.Forms.TextBox(); 42 | this.datagB = new System.Windows.Forms.GroupBox(); 43 | this.estKbpsDataTB = new System.Windows.Forms.TextBox(); 44 | this.estKbpsLabel = new System.Windows.Forms.Label(); 45 | this.progressLabel = new System.Windows.Forms.Label(); 46 | this.taskStepsLabel = new System.Windows.Forms.Label(); 47 | this.fullSpeedBtn = new System.Windows.Forms.Button(); 48 | this.lowSpeedBtn = new System.Windows.Forms.Button(); 49 | this.encoderPriority = new System.Windows.Forms.Label(); 50 | this.priorityCB = new System.Windows.Forms.ComboBox(); 51 | this.statusStrip1.SuspendLayout(); 52 | this.datagB.SuspendLayout(); 53 | this.SuspendLayout(); 54 | // 55 | // stopBtn 56 | // 57 | this.stopBtn.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 58 | this.stopBtn.Location = new System.Drawing.Point(12, 217); 59 | this.stopBtn.Name = "stopBtn"; 60 | this.stopBtn.Size = new System.Drawing.Size(64, 23); 61 | this.stopBtn.TabIndex = 14; 62 | this.stopBtn.Text = "中止"; 63 | this.stopBtn.UseVisualStyleBackColor = true; 64 | this.stopBtn.Click += new System.EventHandler(this.stopBtn_Click); 65 | // 66 | // statusStrip1 67 | // 68 | this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 69 | this.statusLabel, 70 | this.filesCountLabel}); 71 | this.statusStrip1.Location = new System.Drawing.Point(0, 249); 72 | this.statusStrip1.Name = "statusStrip1"; 73 | this.statusStrip1.Size = new System.Drawing.Size(407, 22); 74 | this.statusStrip1.SizingGrip = false; 75 | this.statusStrip1.TabIndex = 13; 76 | this.statusStrip1.Text = "statusStrip1"; 77 | // 78 | // statusLabel 79 | // 80 | this.statusLabel.Name = "statusLabel"; 81 | this.statusLabel.Size = new System.Drawing.Size(39, 17); 82 | this.statusLabel.Text = "状态: "; 83 | // 84 | // filesCountLabel 85 | // 86 | this.filesCountLabel.Name = "filesCountLabel"; 87 | this.filesCountLabel.Size = new System.Drawing.Size(27, 17); 88 | this.filesCountLabel.Text = "0/1"; 89 | // 90 | // progress 91 | // 92 | this.progress.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 93 | | System.Windows.Forms.AnchorStyles.Right))); 94 | this.progress.Location = new System.Drawing.Point(12, 186); 95 | this.progress.Name = "progress"; 96 | this.progress.Size = new System.Drawing.Size(377, 23); 97 | this.progress.TabIndex = 12; 98 | // 99 | // estETADataTB 100 | // 101 | this.estETADataTB.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 102 | | System.Windows.Forms.AnchorStyles.Right))); 103 | this.estETADataTB.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 104 | this.estETADataTB.Location = new System.Drawing.Point(94, 73); 105 | this.estETADataTB.Name = "estETADataTB"; 106 | this.estETADataTB.ReadOnly = true; 107 | this.estETADataTB.Size = new System.Drawing.Size(283, 25); 108 | this.estETADataTB.TabIndex = 21; 109 | this.estETADataTB.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; 110 | // 111 | // estETALabel 112 | // 113 | this.estETALabel.AutoSize = true; 114 | this.estETALabel.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 115 | this.estETALabel.Location = new System.Drawing.Point(8, 79); 116 | this.estETALabel.Name = "estETALabel"; 117 | this.estETALabel.Size = new System.Drawing.Size(80, 17); 118 | this.estETALabel.TabIndex = 6; 119 | this.estETALabel.Text = "预计剩余时间"; 120 | // 121 | // currentPositionLabel 122 | // 123 | this.currentPositionLabel.AutoSize = true; 124 | this.currentPositionLabel.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 125 | this.currentPositionLabel.Location = new System.Drawing.Point(8, 23); 126 | this.currentPositionLabel.Name = "currentPositionLabel"; 127 | this.currentPositionLabel.Size = new System.Drawing.Size(73, 17); 128 | this.currentPositionLabel.TabIndex = 0; 129 | this.currentPositionLabel.Text = "已完成/总计"; 130 | // 131 | // fpsDataTB 132 | // 133 | this.fpsDataTB.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 134 | | System.Windows.Forms.AnchorStyles.Right))); 135 | this.fpsDataTB.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 136 | this.fpsDataTB.Location = new System.Drawing.Point(94, 45); 137 | this.fpsDataTB.Name = "fpsDataTB"; 138 | this.fpsDataTB.ReadOnly = true; 139 | this.fpsDataTB.Size = new System.Drawing.Size(283, 25); 140 | this.fpsDataTB.TabIndex = 17; 141 | this.fpsDataTB.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; 142 | // 143 | // fpsLabel 144 | // 145 | this.fpsLabel.AutoSize = true; 146 | this.fpsLabel.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 147 | this.fpsLabel.Location = new System.Drawing.Point(8, 50); 148 | this.fpsLabel.Name = "fpsLabel"; 149 | this.fpsLabel.Size = new System.Drawing.Size(56, 17); 150 | this.fpsLabel.TabIndex = 2; 151 | this.fpsLabel.Text = "编码速度"; 152 | // 153 | // currentPostionDataTB 154 | // 155 | this.currentPostionDataTB.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 156 | | System.Windows.Forms.AnchorStyles.Right))); 157 | this.currentPostionDataTB.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 158 | this.currentPostionDataTB.ForeColor = System.Drawing.SystemColors.WindowText; 159 | this.currentPostionDataTB.Location = new System.Drawing.Point(94, 18); 160 | this.currentPostionDataTB.Name = "currentPostionDataTB"; 161 | this.currentPostionDataTB.ReadOnly = true; 162 | this.currentPostionDataTB.Size = new System.Drawing.Size(283, 25); 163 | this.currentPostionDataTB.TabIndex = 15; 164 | this.currentPostionDataTB.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; 165 | // 166 | // datagB 167 | // 168 | this.datagB.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 169 | | System.Windows.Forms.AnchorStyles.Right))); 170 | this.datagB.Controls.Add(this.estKbpsDataTB); 171 | this.datagB.Controls.Add(this.estKbpsLabel); 172 | this.datagB.Controls.Add(this.estETADataTB); 173 | this.datagB.Controls.Add(this.estETALabel); 174 | this.datagB.Controls.Add(this.currentPositionLabel); 175 | this.datagB.Controls.Add(this.fpsDataTB); 176 | this.datagB.Controls.Add(this.fpsLabel); 177 | this.datagB.Controls.Add(this.currentPostionDataTB); 178 | this.datagB.Location = new System.Drawing.Point(12, 36); 179 | this.datagB.Name = "datagB"; 180 | this.datagB.Size = new System.Drawing.Size(383, 138); 181 | this.datagB.TabIndex = 11; 182 | this.datagB.TabStop = false; 183 | // 184 | // estKbpsDataTB 185 | // 186 | this.estKbpsDataTB.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 187 | | System.Windows.Forms.AnchorStyles.Right))); 188 | this.estKbpsDataTB.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 189 | this.estKbpsDataTB.Location = new System.Drawing.Point(94, 102); 190 | this.estKbpsDataTB.Name = "estKbpsDataTB"; 191 | this.estKbpsDataTB.ReadOnly = true; 192 | this.estKbpsDataTB.Size = new System.Drawing.Size(283, 25); 193 | this.estKbpsDataTB.TabIndex = 23; 194 | this.estKbpsDataTB.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; 195 | // 196 | // estKbpsLabel 197 | // 198 | this.estKbpsLabel.AutoSize = true; 199 | this.estKbpsLabel.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 200 | this.estKbpsLabel.Location = new System.Drawing.Point(8, 107); 201 | this.estKbpsLabel.Name = "estKbpsLabel"; 202 | this.estKbpsLabel.Size = new System.Drawing.Size(56, 17); 203 | this.estKbpsLabel.TabIndex = 22; 204 | this.estKbpsLabel.Text = "预计码率"; 205 | // 206 | // progressLabel 207 | // 208 | this.progressLabel.Font = new System.Drawing.Font("Microsoft YaHei UI", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 209 | this.progressLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; 210 | this.progressLabel.Location = new System.Drawing.Point(327, 218); 211 | this.progressLabel.Name = "progressLabel"; 212 | this.progressLabel.Size = new System.Drawing.Size(62, 20); 213 | this.progressLabel.TabIndex = 15; 214 | this.progressLabel.Text = "0.00%"; 215 | this.progressLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 216 | // 217 | // taskStepsLabel 218 | // 219 | this.taskStepsLabel.AutoSize = true; 220 | this.taskStepsLabel.Font = new System.Drawing.Font("微软雅黑", 11.25F); 221 | this.taskStepsLabel.Location = new System.Drawing.Point(12, 13); 222 | this.taskStepsLabel.Name = "taskStepsLabel"; 223 | this.taskStepsLabel.Size = new System.Drawing.Size(216, 20); 224 | this.taskStepsLabel.TabIndex = 16; 225 | this.taskStepsLabel.Text = "正在进行:步骤 1/3 - 复制音频"; 226 | // 227 | // fullSpeedBtn 228 | // 229 | this.fullSpeedBtn.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 230 | this.fullSpeedBtn.Location = new System.Drawing.Point(230, 217); 231 | this.fullSpeedBtn.Name = "fullSpeedBtn"; 232 | this.fullSpeedBtn.Size = new System.Drawing.Size(46, 23); 233 | this.fullSpeedBtn.TabIndex = 17; 234 | this.fullSpeedBtn.Text = "正常"; 235 | this.fullSpeedBtn.UseVisualStyleBackColor = true; 236 | this.fullSpeedBtn.VisibleChanged += new System.EventHandler(this.fullSpeedBtn_VisibleChanged); 237 | this.fullSpeedBtn.Click += new System.EventHandler(this.fullSpeedBtn_Click); 238 | // 239 | // lowSpeedBtn 240 | // 241 | this.lowSpeedBtn.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 242 | this.lowSpeedBtn.Location = new System.Drawing.Point(274, 217); 243 | this.lowSpeedBtn.Name = "lowSpeedBtn"; 244 | this.lowSpeedBtn.Size = new System.Drawing.Size(45, 23); 245 | this.lowSpeedBtn.TabIndex = 18; 246 | this.lowSpeedBtn.Text = "低速"; 247 | this.lowSpeedBtn.UseVisualStyleBackColor = true; 248 | this.lowSpeedBtn.Click += new System.EventHandler(this.lowSpeedBtn_Click); 249 | // 250 | // encoderPriority 251 | // 252 | this.encoderPriority.AutoSize = true; 253 | this.encoderPriority.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); 254 | this.encoderPriority.Location = new System.Drawing.Point(82, 218); 255 | this.encoderPriority.Name = "encoderPriority"; 256 | this.encoderPriority.Size = new System.Drawing.Size(51, 20); 257 | this.encoderPriority.TabIndex = 19; 258 | this.encoderPriority.Text = "优先级"; 259 | // 260 | // priorityCB 261 | // 262 | this.priorityCB.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 263 | this.priorityCB.FormattingEnabled = true; 264 | this.priorityCB.Items.AddRange(new object[] { 265 | "低", 266 | "低于正常", 267 | "正常", 268 | "高于正常", 269 | "高", 270 | "实时"}); 271 | this.priorityCB.Location = new System.Drawing.Point(137, 218); 272 | this.priorityCB.Name = "priorityCB"; 273 | this.priorityCB.Size = new System.Drawing.Size(79, 20); 274 | this.priorityCB.TabIndex = 20; 275 | this.priorityCB.SelectedIndexChanged += new System.EventHandler(this.priorityCB_SelectedIndexChanged); 276 | // 277 | // RunningStatusForm 278 | // 279 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 280 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 281 | this.ClientSize = new System.Drawing.Size(407, 271); 282 | this.Controls.Add(this.priorityCB); 283 | this.Controls.Add(this.encoderPriority); 284 | this.Controls.Add(this.lowSpeedBtn); 285 | this.Controls.Add(this.fullSpeedBtn); 286 | this.Controls.Add(this.taskStepsLabel); 287 | this.Controls.Add(this.progressLabel); 288 | this.Controls.Add(this.stopBtn); 289 | this.Controls.Add(this.statusStrip1); 290 | this.Controls.Add(this.progress); 291 | this.Controls.Add(this.datagB); 292 | this.Name = "RunningStatusForm"; 293 | this.Text = "RunningStatusForm"; 294 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.RunningStatusForm_FormClosing); 295 | this.Shown += new System.EventHandler(this.RunningStatusForm_Shown); 296 | this.statusStrip1.ResumeLayout(false); 297 | this.statusStrip1.PerformLayout(); 298 | this.datagB.ResumeLayout(false); 299 | this.datagB.PerformLayout(); 300 | this.ResumeLayout(false); 301 | this.PerformLayout(); 302 | 303 | } 304 | 305 | #endregion 306 | 307 | private System.Windows.Forms.Button stopBtn; 308 | private System.Windows.Forms.StatusStrip statusStrip1; 309 | private System.Windows.Forms.ToolStripStatusLabel statusLabel; 310 | private System.Windows.Forms.ToolStripStatusLabel filesCountLabel; 311 | private System.Windows.Forms.ProgressBar progress; 312 | private System.Windows.Forms.TextBox estETADataTB; 313 | private System.Windows.Forms.Label estETALabel; 314 | private System.Windows.Forms.Label currentPositionLabel; 315 | private System.Windows.Forms.TextBox fpsDataTB; 316 | private System.Windows.Forms.Label fpsLabel; 317 | private System.Windows.Forms.TextBox currentPostionDataTB; 318 | private System.Windows.Forms.GroupBox datagB; 319 | private System.Windows.Forms.Label progressLabel; 320 | private System.Windows.Forms.Label taskStepsLabel; 321 | private System.Windows.Forms.Button fullSpeedBtn; 322 | private System.Windows.Forms.Button lowSpeedBtn; 323 | private System.Windows.Forms.Label encoderPriority; 324 | private System.Windows.Forms.ComboBox priorityCB; 325 | private System.Windows.Forms.TextBox estKbpsDataTB; 326 | private System.Windows.Forms.Label estKbpsLabel; 327 | } 328 | } -------------------------------------------------------------------------------- /ExpertVideoToolbox/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ExpertVideoToolbox 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// 必需的设计器变量。 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// 清理所有正在使用的资源。 12 | /// 13 | /// 如果应释放托管资源,为 true;否则为 false。 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows 窗体设计器生成的代码 24 | 25 | /// 26 | /// 设计器支持所需的方法 - 不要 27 | /// 使用代码编辑器修改此方法的内容。 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.removeAllBtn = new System.Windows.Forms.Button(); 32 | this.removeFileBtn = new System.Windows.Forms.Button(); 33 | this.addFolderBtn = new System.Windows.Forms.Button(); 34 | this.addFileBtn = new System.Windows.Forms.Button(); 35 | this.videoSetgB = new System.Windows.Forms.GroupBox(); 36 | this.cmdCodeTB = new System.Windows.Forms.TextBox(); 37 | this.encoderCB = new System.Windows.Forms.ComboBox(); 38 | this.encoderLabel = new System.Windows.Forms.Label(); 39 | this.brORqLabel = new System.Windows.Forms.Label(); 40 | this.fileFormatCB = new System.Windows.Forms.ComboBox(); 41 | this.fileFormatLabel = new System.Windows.Forms.Label(); 42 | this.removeSettingBtn = new System.Windows.Forms.Button(); 43 | this.addSettingBtn = new System.Windows.Forms.Button(); 44 | this.encodeSettinglabel = new System.Windows.Forms.Label(); 45 | this.encodeSettingCB = new System.Windows.Forms.ComboBox(); 46 | this.set2SelectedBtn = new System.Windows.Forms.Button(); 47 | this.set2AllBtn = new System.Windows.Forms.Button(); 48 | this.StartBtn = new System.Windows.Forms.Button(); 49 | this.fileListView = new System.Windows.Forms.ListView(); 50 | this.outputFilePathlabel = new System.Windows.Forms.Label(); 51 | this.outputFilePathTB = new System.Windows.Forms.TextBox(); 52 | this.chooseOutputPathBtn = new System.Windows.Forms.Button(); 53 | this.audioSetgB = new System.Windows.Forms.GroupBox(); 54 | this.profileCB = new System.Windows.Forms.ComboBox(); 55 | this.profileLabel = new System.Windows.Forms.Label(); 56 | this.bitrateOrQualityCB = new System.Windows.Forms.ComboBox(); 57 | this.bitrateOrQualityLabel = new System.Windows.Forms.Label(); 58 | this.codecModeCB = new System.Windows.Forms.ComboBox(); 59 | this.codecModeLabel = new System.Windows.Forms.Label(); 60 | this.audioEncoderCB = new System.Windows.Forms.ComboBox(); 61 | this.audioEncoder = new System.Windows.Forms.Label(); 62 | this.label3 = new System.Windows.Forms.Label(); 63 | this.videoSetgB.SuspendLayout(); 64 | this.audioSetgB.SuspendLayout(); 65 | this.SuspendLayout(); 66 | // 67 | // removeAllBtn 68 | // 69 | this.removeAllBtn.Location = new System.Drawing.Point(395, 178); 70 | this.removeAllBtn.Name = "removeAllBtn"; 71 | this.removeAllBtn.Size = new System.Drawing.Size(75, 23); 72 | this.removeAllBtn.TabIndex = 8; 73 | this.removeAllBtn.Text = "移除所有"; 74 | this.removeAllBtn.UseVisualStyleBackColor = true; 75 | this.removeAllBtn.Click += new System.EventHandler(this.removeAllBtn_Click); 76 | // 77 | // removeFileBtn 78 | // 79 | this.removeFileBtn.Location = new System.Drawing.Point(314, 178); 80 | this.removeFileBtn.Name = "removeFileBtn"; 81 | this.removeFileBtn.Size = new System.Drawing.Size(75, 23); 82 | this.removeFileBtn.TabIndex = 7; 83 | this.removeFileBtn.Text = "移除文件"; 84 | this.removeFileBtn.UseVisualStyleBackColor = true; 85 | this.removeFileBtn.Click += new System.EventHandler(this.removeFileBtn_Click); 86 | // 87 | // addFolderBtn 88 | // 89 | this.addFolderBtn.Location = new System.Drawing.Point(93, 178); 90 | this.addFolderBtn.Name = "addFolderBtn"; 91 | this.addFolderBtn.Size = new System.Drawing.Size(75, 23); 92 | this.addFolderBtn.TabIndex = 6; 93 | this.addFolderBtn.Text = "添加文件夹"; 94 | this.addFolderBtn.UseVisualStyleBackColor = true; 95 | this.addFolderBtn.Click += new System.EventHandler(this.addFolderBtn_Click); 96 | // 97 | // addFileBtn 98 | // 99 | this.addFileBtn.Location = new System.Drawing.Point(12, 178); 100 | this.addFileBtn.Name = "addFileBtn"; 101 | this.addFileBtn.Size = new System.Drawing.Size(75, 23); 102 | this.addFileBtn.TabIndex = 5; 103 | this.addFileBtn.Text = "添加文件"; 104 | this.addFileBtn.UseVisualStyleBackColor = true; 105 | this.addFileBtn.Click += new System.EventHandler(this.addFileBtn_Click); 106 | // 107 | // videoSetgB 108 | // 109 | this.videoSetgB.Controls.Add(this.cmdCodeTB); 110 | this.videoSetgB.Controls.Add(this.encoderCB); 111 | this.videoSetgB.Controls.Add(this.encoderLabel); 112 | this.videoSetgB.Controls.Add(this.brORqLabel); 113 | this.videoSetgB.Controls.Add(this.fileFormatCB); 114 | this.videoSetgB.Controls.Add(this.fileFormatLabel); 115 | this.videoSetgB.Location = new System.Drawing.Point(14, 279); 116 | this.videoSetgB.Name = "videoSetgB"; 117 | this.videoSetgB.Size = new System.Drawing.Size(377, 143); 118 | this.videoSetgB.TabIndex = 9; 119 | this.videoSetgB.TabStop = false; 120 | this.videoSetgB.Text = "视频流设置"; 121 | // 122 | // cmdCodeTB 123 | // 124 | this.cmdCodeTB.Font = new System.Drawing.Font("微软雅黑", 9F); 125 | this.cmdCodeTB.Location = new System.Drawing.Point(6, 46); 126 | this.cmdCodeTB.Multiline = true; 127 | this.cmdCodeTB.Name = "cmdCodeTB"; 128 | this.cmdCodeTB.Size = new System.Drawing.Size(357, 91); 129 | this.cmdCodeTB.TabIndex = 11; 130 | this.cmdCodeTB.Text = "--crf 20 --level 4.1 --bframes 7 --b-adapt 2 --ref 4 --aq-mode 1 --aq-strength 0." + 131 | "7 --merange 32 --me umh --subme 10 --partitions all --trellis 2 --psy-rd 0.7:0 -" + 132 | "-deblock 0:0"; 133 | // 134 | // encoderCB 135 | // 136 | this.encoderCB.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 137 | this.encoderCB.FormattingEnabled = true; 138 | this.encoderCB.Items.AddRange(new object[] { 139 | "x264_64-8bit.exe", 140 | "x264_64-10bit.exe", 141 | "x265-10bit.exe"}); 142 | this.encoderCB.Location = new System.Drawing.Point(76, 20); 143 | this.encoderCB.Name = "encoderCB"; 144 | this.encoderCB.Size = new System.Drawing.Size(152, 20); 145 | this.encoderCB.TabIndex = 6; 146 | // 147 | // encoderLabel 148 | // 149 | this.encoderLabel.AutoSize = true; 150 | this.encoderLabel.Location = new System.Drawing.Point(7, 23); 151 | this.encoderLabel.Name = "encoderLabel"; 152 | this.encoderLabel.Size = new System.Drawing.Size(53, 12); 153 | this.encoderLabel.TabIndex = 5; 154 | this.encoderLabel.Text = "编码程序"; 155 | // 156 | // brORqLabel 157 | // 158 | this.brORqLabel.AutoSize = true; 159 | this.brORqLabel.Location = new System.Drawing.Point(6, 55); 160 | this.brORqLabel.Name = "brORqLabel"; 161 | this.brORqLabel.Size = new System.Drawing.Size(0, 12); 162 | this.brORqLabel.TabIndex = 3; 163 | // 164 | // fileFormatCB 165 | // 166 | this.fileFormatCB.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 167 | this.fileFormatCB.FormattingEnabled = true; 168 | this.fileFormatCB.Items.AddRange(new object[] { 169 | "mp4", 170 | "mkv"}); 171 | this.fileFormatCB.Location = new System.Drawing.Point(289, 20); 172 | this.fileFormatCB.Name = "fileFormatCB"; 173 | this.fileFormatCB.Size = new System.Drawing.Size(73, 20); 174 | this.fileFormatCB.TabIndex = 1; 175 | // 176 | // fileFormatLabel 177 | // 178 | this.fileFormatLabel.AutoSize = true; 179 | this.fileFormatLabel.Location = new System.Drawing.Point(231, 23); 180 | this.fileFormatLabel.Name = "fileFormatLabel"; 181 | this.fileFormatLabel.Size = new System.Drawing.Size(53, 12); 182 | this.fileFormatLabel.TabIndex = 0; 183 | this.fileFormatLabel.Text = "文件格式"; 184 | // 185 | // removeSettingBtn 186 | // 187 | this.removeSettingBtn.Location = new System.Drawing.Point(314, 250); 188 | this.removeSettingBtn.Name = "removeSettingBtn"; 189 | this.removeSettingBtn.Size = new System.Drawing.Size(75, 23); 190 | this.removeSettingBtn.TabIndex = 10; 191 | this.removeSettingBtn.Text = "移除预设"; 192 | this.removeSettingBtn.UseVisualStyleBackColor = true; 193 | this.removeSettingBtn.Click += new System.EventHandler(this.removeSettingBtn_Click); 194 | // 195 | // addSettingBtn 196 | // 197 | this.addSettingBtn.Location = new System.Drawing.Point(223, 250); 198 | this.addSettingBtn.Name = "addSettingBtn"; 199 | this.addSettingBtn.Size = new System.Drawing.Size(85, 23); 200 | this.addSettingBtn.TabIndex = 9; 201 | this.addSettingBtn.Text = "添加预设"; 202 | this.addSettingBtn.UseVisualStyleBackColor = true; 203 | this.addSettingBtn.Click += new System.EventHandler(this.addSettingBtn_Click); 204 | // 205 | // encodeSettinglabel 206 | // 207 | this.encodeSettinglabel.AutoSize = true; 208 | this.encodeSettinglabel.Location = new System.Drawing.Point(21, 255); 209 | this.encodeSettinglabel.Name = "encodeSettinglabel"; 210 | this.encodeSettinglabel.Size = new System.Drawing.Size(53, 12); 211 | this.encodeSettinglabel.TabIndex = 8; 212 | this.encodeSettinglabel.Text = "编码预设"; 213 | // 214 | // encodeSettingCB 215 | // 216 | this.encodeSettingCB.FormattingEnabled = true; 217 | this.encodeSettingCB.Location = new System.Drawing.Point(90, 252); 218 | this.encodeSettingCB.Name = "encodeSettingCB"; 219 | this.encodeSettingCB.Size = new System.Drawing.Size(122, 20); 220 | this.encodeSettingCB.TabIndex = 7; 221 | this.encodeSettingCB.SelectedIndexChanged += new System.EventHandler(this.encodeSettingCB_SelectedIndexChanged); 222 | // 223 | // set2SelectedBtn 224 | // 225 | this.set2SelectedBtn.Location = new System.Drawing.Point(395, 250); 226 | this.set2SelectedBtn.Name = "set2SelectedBtn"; 227 | this.set2SelectedBtn.Size = new System.Drawing.Size(74, 23); 228 | this.set2SelectedBtn.TabIndex = 10; 229 | this.set2SelectedBtn.Text = "应用到选中"; 230 | this.set2SelectedBtn.UseVisualStyleBackColor = true; 231 | this.set2SelectedBtn.Click += new System.EventHandler(this.set2SelectedBtn_Click); 232 | // 233 | // set2AllBtn 234 | // 235 | this.set2AllBtn.Location = new System.Drawing.Point(394, 281); 236 | this.set2AllBtn.Name = "set2AllBtn"; 237 | this.set2AllBtn.Size = new System.Drawing.Size(75, 23); 238 | this.set2AllBtn.TabIndex = 11; 239 | this.set2AllBtn.Text = "全部应用"; 240 | this.set2AllBtn.UseVisualStyleBackColor = true; 241 | this.set2AllBtn.Click += new System.EventHandler(this.set2AllBtn_Click); 242 | // 243 | // StartBtn 244 | // 245 | this.StartBtn.Location = new System.Drawing.Point(397, 457); 246 | this.StartBtn.Name = "StartBtn"; 247 | this.StartBtn.Size = new System.Drawing.Size(74, 53); 248 | this.StartBtn.TabIndex = 12; 249 | this.StartBtn.Text = "开始任务"; 250 | this.StartBtn.UseVisualStyleBackColor = true; 251 | this.StartBtn.Click += new System.EventHandler(this.StartBtn_Click); 252 | // 253 | // fileListView 254 | // 255 | this.fileListView.AllowDrop = true; 256 | this.fileListView.Font = new System.Drawing.Font("微软雅黑", 8F); 257 | this.fileListView.Location = new System.Drawing.Point(12, 12); 258 | this.fileListView.Name = "fileListView"; 259 | this.fileListView.Size = new System.Drawing.Size(457, 160); 260 | this.fileListView.TabIndex = 13; 261 | this.fileListView.UseCompatibleStateImageBehavior = false; 262 | this.fileListView.DragDrop += new System.Windows.Forms.DragEventHandler(this.fileListView_DragDrop); 263 | this.fileListView.DragEnter += new System.Windows.Forms.DragEventHandler(this.fileListView_DragEnter); 264 | // 265 | // outputFilePathlabel 266 | // 267 | this.outputFilePathlabel.AutoSize = true; 268 | this.outputFilePathlabel.Location = new System.Drawing.Point(21, 225); 269 | this.outputFilePathlabel.Name = "outputFilePathlabel"; 270 | this.outputFilePathlabel.Size = new System.Drawing.Size(53, 12); 271 | this.outputFilePathlabel.TabIndex = 14; 272 | this.outputFilePathlabel.Text = "输出路径"; 273 | // 274 | // outputFilePathTB 275 | // 276 | this.outputFilePathTB.Location = new System.Drawing.Point(90, 222); 277 | this.outputFilePathTB.Name = "outputFilePathTB"; 278 | this.outputFilePathTB.Size = new System.Drawing.Size(299, 21); 279 | this.outputFilePathTB.TabIndex = 15; 280 | // 281 | // chooseOutputPathBtn 282 | // 283 | this.chooseOutputPathBtn.Location = new System.Drawing.Point(395, 222); 284 | this.chooseOutputPathBtn.Name = "chooseOutputPathBtn"; 285 | this.chooseOutputPathBtn.Size = new System.Drawing.Size(75, 23); 286 | this.chooseOutputPathBtn.TabIndex = 16; 287 | this.chooseOutputPathBtn.Text = "浏览"; 288 | this.chooseOutputPathBtn.UseVisualStyleBackColor = true; 289 | this.chooseOutputPathBtn.Click += new System.EventHandler(this.chooseOutputPathBtn_Click); 290 | // 291 | // audioSetgB 292 | // 293 | this.audioSetgB.Controls.Add(this.profileCB); 294 | this.audioSetgB.Controls.Add(this.profileLabel); 295 | this.audioSetgB.Controls.Add(this.bitrateOrQualityCB); 296 | this.audioSetgB.Controls.Add(this.bitrateOrQualityLabel); 297 | this.audioSetgB.Controls.Add(this.codecModeCB); 298 | this.audioSetgB.Controls.Add(this.codecModeLabel); 299 | this.audioSetgB.Controls.Add(this.audioEncoderCB); 300 | this.audioSetgB.Controls.Add(this.audioEncoder); 301 | this.audioSetgB.Controls.Add(this.label3); 302 | this.audioSetgB.Location = new System.Drawing.Point(14, 428); 303 | this.audioSetgB.Name = "audioSetgB"; 304 | this.audioSetgB.Size = new System.Drawing.Size(377, 82); 305 | this.audioSetgB.TabIndex = 17; 306 | this.audioSetgB.TabStop = false; 307 | this.audioSetgB.Text = "音频流设置"; 308 | // 309 | // profileCB 310 | // 311 | this.profileCB.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 312 | this.profileCB.FormattingEnabled = true; 313 | this.profileCB.Location = new System.Drawing.Point(289, 24); 314 | this.profileCB.Name = "profileCB"; 315 | this.profileCB.Size = new System.Drawing.Size(75, 20); 316 | this.profileCB.TabIndex = 12; 317 | this.profileCB.SelectedIndexChanged += new System.EventHandler(this.profileCB_SelectedIndexChanged); 318 | // 319 | // profileLabel 320 | // 321 | this.profileLabel.AutoSize = true; 322 | this.profileLabel.Location = new System.Drawing.Point(236, 27); 323 | this.profileLabel.Name = "profileLabel"; 324 | this.profileLabel.Size = new System.Drawing.Size(47, 12); 325 | this.profileLabel.TabIndex = 11; 326 | this.profileLabel.Text = "Profile"; 327 | // 328 | // bitrateOrQualityCB 329 | // 330 | this.bitrateOrQualityCB.FormattingEnabled = true; 331 | this.bitrateOrQualityCB.Items.AddRange(new object[] { 332 | "0", 333 | "9", 334 | "18", 335 | "27", 336 | "36", 337 | "45", 338 | "54", 339 | "63", 340 | "73", 341 | "82", 342 | "91", 343 | "100", 344 | "109", 345 | "118", 346 | "127"}); 347 | this.bitrateOrQualityCB.Location = new System.Drawing.Point(255, 52); 348 | this.bitrateOrQualityCB.Name = "bitrateOrQualityCB"; 349 | this.bitrateOrQualityCB.Size = new System.Drawing.Size(110, 20); 350 | this.bitrateOrQualityCB.TabIndex = 10; 351 | // 352 | // bitrateOrQualityLabel 353 | // 354 | this.bitrateOrQualityLabel.AutoSize = true; 355 | this.bitrateOrQualityLabel.Location = new System.Drawing.Point(220, 55); 356 | this.bitrateOrQualityLabel.Name = "bitrateOrQualityLabel"; 357 | this.bitrateOrQualityLabel.Size = new System.Drawing.Size(29, 12); 358 | this.bitrateOrQualityLabel.TabIndex = 9; 359 | this.bitrateOrQualityLabel.Text = "质量"; 360 | // 361 | // codecModeCB 362 | // 363 | this.codecModeCB.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 364 | this.codecModeCB.FormattingEnabled = true; 365 | this.codecModeCB.Location = new System.Drawing.Point(75, 52); 366 | this.codecModeCB.Name = "codecModeCB"; 367 | this.codecModeCB.Size = new System.Drawing.Size(121, 20); 368 | this.codecModeCB.TabIndex = 8; 369 | this.codecModeCB.SelectedIndexChanged += new System.EventHandler(this.codecModeCB_SelectedIndexChanged); 370 | // 371 | // codecModeLabel 372 | // 373 | this.codecModeLabel.AutoSize = true; 374 | this.codecModeLabel.Location = new System.Drawing.Point(5, 55); 375 | this.codecModeLabel.Name = "codecModeLabel"; 376 | this.codecModeLabel.Size = new System.Drawing.Size(53, 12); 377 | this.codecModeLabel.TabIndex = 7; 378 | this.codecModeLabel.Text = "编码模式"; 379 | // 380 | // audioEncoderCB 381 | // 382 | this.audioEncoderCB.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 383 | this.audioEncoderCB.FormattingEnabled = true; 384 | this.audioEncoderCB.Items.AddRange(new object[] { 385 | "复制音频流", 386 | "无音频流", 387 | "qaac"}); 388 | this.audioEncoderCB.Location = new System.Drawing.Point(75, 24); 389 | this.audioEncoderCB.Name = "audioEncoderCB"; 390 | this.audioEncoderCB.Size = new System.Drawing.Size(151, 20); 391 | this.audioEncoderCB.TabIndex = 6; 392 | this.audioEncoderCB.SelectedIndexChanged += new System.EventHandler(this.audioEncoderCB_SelectedIndexChanged); 393 | // 394 | // audioEncoder 395 | // 396 | this.audioEncoder.AutoSize = true; 397 | this.audioEncoder.Location = new System.Drawing.Point(6, 27); 398 | this.audioEncoder.Name = "audioEncoder"; 399 | this.audioEncoder.Size = new System.Drawing.Size(53, 12); 400 | this.audioEncoder.TabIndex = 5; 401 | this.audioEncoder.Text = "编码程序"; 402 | // 403 | // label3 404 | // 405 | this.label3.AutoSize = true; 406 | this.label3.Location = new System.Drawing.Point(6, 55); 407 | this.label3.Name = "label3"; 408 | this.label3.Size = new System.Drawing.Size(0, 12); 409 | this.label3.TabIndex = 3; 410 | // 411 | // MainForm 412 | // 413 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 414 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 415 | this.ClientSize = new System.Drawing.Size(482, 521); 416 | this.Controls.Add(this.audioSetgB); 417 | this.Controls.Add(this.removeSettingBtn); 418 | this.Controls.Add(this.chooseOutputPathBtn); 419 | this.Controls.Add(this.addSettingBtn); 420 | this.Controls.Add(this.outputFilePathTB); 421 | this.Controls.Add(this.encodeSettinglabel); 422 | this.Controls.Add(this.encodeSettingCB); 423 | this.Controls.Add(this.outputFilePathlabel); 424 | this.Controls.Add(this.fileListView); 425 | this.Controls.Add(this.StartBtn); 426 | this.Controls.Add(this.set2AllBtn); 427 | this.Controls.Add(this.set2SelectedBtn); 428 | this.Controls.Add(this.videoSetgB); 429 | this.Controls.Add(this.removeAllBtn); 430 | this.Controls.Add(this.removeFileBtn); 431 | this.Controls.Add(this.addFolderBtn); 432 | this.Controls.Add(this.addFileBtn); 433 | this.Name = "MainForm"; 434 | this.Text = "Expert Video Toolbox"; 435 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); 436 | this.videoSetgB.ResumeLayout(false); 437 | this.videoSetgB.PerformLayout(); 438 | this.audioSetgB.ResumeLayout(false); 439 | this.audioSetgB.PerformLayout(); 440 | this.ResumeLayout(false); 441 | this.PerformLayout(); 442 | 443 | } 444 | 445 | #endregion 446 | 447 | private System.Windows.Forms.Button removeAllBtn; 448 | private System.Windows.Forms.Button removeFileBtn; 449 | private System.Windows.Forms.Button addFolderBtn; 450 | private System.Windows.Forms.Button addFileBtn; 451 | private System.Windows.Forms.GroupBox videoSetgB; 452 | private System.Windows.Forms.ComboBox encoderCB; 453 | private System.Windows.Forms.Label encoderLabel; 454 | private System.Windows.Forms.Label brORqLabel; 455 | private System.Windows.Forms.ComboBox fileFormatCB; 456 | private System.Windows.Forms.Label fileFormatLabel; 457 | private System.Windows.Forms.ComboBox encodeSettingCB; 458 | private System.Windows.Forms.TextBox cmdCodeTB; 459 | private System.Windows.Forms.Button removeSettingBtn; 460 | private System.Windows.Forms.Button addSettingBtn; 461 | private System.Windows.Forms.Label encodeSettinglabel; 462 | private System.Windows.Forms.Button set2SelectedBtn; 463 | private System.Windows.Forms.Button set2AllBtn; 464 | private System.Windows.Forms.Button StartBtn; 465 | private System.Windows.Forms.ListView fileListView; 466 | private System.Windows.Forms.Label outputFilePathlabel; 467 | private System.Windows.Forms.TextBox outputFilePathTB; 468 | private System.Windows.Forms.Button chooseOutputPathBtn; 469 | private System.Windows.Forms.GroupBox audioSetgB; 470 | private System.Windows.Forms.ComboBox profileCB; 471 | private System.Windows.Forms.Label profileLabel; 472 | private System.Windows.Forms.ComboBox bitrateOrQualityCB; 473 | private System.Windows.Forms.Label bitrateOrQualityLabel; 474 | private System.Windows.Forms.ComboBox codecModeCB; 475 | private System.Windows.Forms.Label codecModeLabel; 476 | private System.Windows.Forms.ComboBox audioEncoderCB; 477 | private System.Windows.Forms.Label audioEncoder; 478 | private System.Windows.Forms.Label label3; 479 | } 480 | } 481 | 482 | -------------------------------------------------------------------------------- /ExpertVideoToolbox/MainForm.cs: -------------------------------------------------------------------------------- 1 | using ExpertVideoToolbox.cmdCodeGenerator; 2 | using ExpertVideoToolbox.taskManager; 3 | using ExpertVideoToolbox.TaskManager; 4 | using Newtonsoft.Json; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.ComponentModel; 8 | using System.Data; 9 | using System.Diagnostics; 10 | using System.Drawing; 11 | using System.IO; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Threading.Tasks; 15 | using System.Windows.Forms; 16 | 17 | namespace ExpertVideoToolbox 18 | { 19 | public partial class MainForm : Form 20 | { 21 | taskSetting[] settings; 22 | Job j; 23 | 24 | public MainForm() 25 | { 26 | InitializeComponent(); 27 | 28 | CheckForIllegalCrossThreadCalls = false; 29 | 30 | string fileNameColumnText = "文件名"; 31 | string settingColumnText = "编码预设"; 32 | 33 | this.fileListView.View = View.Details; 34 | 35 | int settingColumnWidth = 100; 36 | int reservedWidth = 5; 37 | 38 | // 显示的文件名列,优化了省略号的位置 39 | ColumnHeader visualFileNameCH = new ColumnHeader(); 40 | visualFileNameCH.Text = fileNameColumnText; 41 | visualFileNameCH.Width = this.fileListView.Width - settingColumnWidth - reservedWidth; 42 | 43 | ColumnHeader settingCH = new ColumnHeader(); 44 | settingCH.Text = settingColumnText; 45 | settingCH.Width = settingColumnWidth; 46 | 47 | // 真实文件名列,不显示在UI上,宽度为0 48 | ColumnHeader realFileNameCH = new ColumnHeader(); 49 | realFileNameCH.Text = ""; 50 | realFileNameCH.Width = 0; 51 | 52 | this.fileListView.Columns.Add(visualFileNameCH); 53 | this.fileListView.Columns.Add(settingCH); 54 | this.fileListView.Columns.Add(realFileNameCH); 55 | 56 | //this.outputFilePathTB.Text = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\trans"; 57 | 58 | // 从文件中读取已存储的预设 59 | int i = readAllSettingsFromFiles(); 60 | 61 | // 将读到的预设加载到combobox中 62 | for (int j = 0; j < i; j++) 63 | { 64 | this.encodeSettingCB.Items.Add(settings[j].name); 65 | } 66 | 67 | this.encodeSettingCB.SelectedIndex = 0; 68 | 69 | //ListViewItem gg = new ListViewItem(new string[] { "test01", "test" }); //这是至关重要的一点。 70 | //this.fileListView.Items.Add(gg); 71 | } 72 | 73 | // !!点击开始转换 74 | private void StartBtn_Click(object sender, EventArgs e) 75 | { 76 | if (this.fileListView.Items.Count == 0) 77 | { 78 | string noFileMsg = "未添加任何文件"; 79 | MessageBox.Show(noFileMsg); 80 | } 81 | else 82 | { 83 | if (checkSettingChange() == -1) 84 | { 85 | MessageBox.Show("一个或多个任务的预设已被删除,请重新添加预设!"); 86 | return; 87 | } 88 | 89 | if (checkSettingChange() == 1) // 1为真,表示有变化 90 | { 91 | string note = "检测到预设已修改,是否覆盖当前选中的预设?\n点击“确定”将覆盖并应用该预设到全部任务。点击“取消”将中止任务且不做改动。"; 92 | DialogResult dr = MessageBox.Show(note, "检测到预设修改", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); 93 | if (dr == DialogResult.OK) 94 | { 95 | //点确定的代码 96 | saveSetting2File(this.encodeSettingCB.Text); 97 | readAllSettingsFromFiles(); 98 | 99 | for (int i = 0; i < this.fileListView.Items.Count; i++) 100 | { 101 | fileListView.Items[i].SubItems[1].Text = this.encodeSettingCB.Text; 102 | } 103 | } 104 | else 105 | { 106 | //点取消的代码 107 | return; 108 | } 109 | } 110 | 111 | int count = fileListView.Items.Count; 112 | filePathStorage q = new filePathStorage(count); 113 | for (int i = 0; i < count; i++) 114 | { 115 | if (!CheckSettingExist(fileListView.Items[i].SubItems[1].Text)) 116 | { 117 | MessageBox.Show("一个或多个任务的预设已被删除,请检查编码设置!"); 118 | return; 119 | } 120 | 121 | // subitems[2]中保存着完整文件名 122 | videoTask t = new videoTask(fileListView.Items[i].SubItems[2].Text, fileListView.Items[i].SubItems[1].Text); 123 | q.add(t); 124 | } 125 | 126 | this.j = new Job(q); 127 | //this.j.ErrorEvent += DisposeJob; 128 | this.j.runJob(this.outputFilePathTB.Text); 129 | } 130 | } 131 | 132 | private void fileListView_DragDrop(object sender, DragEventArgs e) 133 | { 134 | Array files = ((System.Array)e.Data.GetData(DataFormats.FileDrop)); 135 | int count = files.Length; 136 | for (int i = 0; i < count; i++) 137 | { 138 | string fp = files.GetValue(i).ToString(); 139 | string setting = this.encodeSettingCB.Text; 140 | 141 | addItem2FileListView(fp, setting); 142 | } 143 | } 144 | 145 | // 必须添加这一事件才可以拖动进来 146 | private void fileListView_DragEnter(object sender, DragEventArgs e) 147 | { 148 | e.Effect = DragDropEffects.Copy; 149 | } 150 | 151 | private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 152 | { 153 | Application.Exit(); 154 | Process p = Process.GetCurrentProcess(); 155 | p.Kill(); 156 | } 157 | 158 | private void addFileBtn_Click(object sender, EventArgs e) 159 | { 160 | Stream myStream = null; 161 | OpenFileDialog openFileDialog1 = new OpenFileDialog(); 162 | 163 | openFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // 默认打开显示我的文档 164 | openFileDialog1.Filter = "mp4视频文件 (*.mp4)|*.mp4|All files (*.*)|*.*"; 165 | openFileDialog1.FilterIndex = 2; 166 | openFileDialog1.RestoreDirectory = false; 167 | 168 | if (openFileDialog1.ShowDialog() == DialogResult.OK) 169 | { 170 | try 171 | { 172 | if ((myStream = openFileDialog1.OpenFile()) != null) 173 | { 174 | using (myStream) 175 | { 176 | // Insert code to read the stream here. 177 | string fp = openFileDialog1.FileName; 178 | string setting = this.encodeSettingCB.Text; 179 | addItem2FileListView(fp, setting); 180 | } 181 | } 182 | } 183 | catch (Exception ex) 184 | { 185 | MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); 186 | } 187 | } 188 | } 189 | 190 | private void addFolderBtn_Click(object sender, EventArgs e) 191 | { 192 | FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog(); 193 | if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) 194 | { 195 | string folderPath = folderBrowserDialog1.SelectedPath; 196 | 197 | string[] files = System.IO.Directory.GetFiles(folderPath); 198 | int filesCount = files.Length; 199 | int videoFilesCount = 0; 200 | for (int i = 0; i < filesCount; i++) 201 | { 202 | string fp = files[i]; 203 | string[] s = fp.Split(new char[] { '.' }); 204 | string ext = s[s.Length - 1]; 205 | if (videoFileCheckByExtension(ext)) 206 | { 207 | videoFilesCount++; 208 | 209 | string setting = this.encodeSettingCB.Text; 210 | 211 | addItem2FileListView(fp, setting); 212 | } 213 | 214 | } 215 | string msg = "目录搜索完成,找到" + videoFilesCount.ToString() + "个支持的文件"; 216 | MessageBox.Show(msg); 217 | } 218 | } 219 | 220 | private bool videoFileCheckByExtension(string extension) 221 | { 222 | string[] videoExt = { "mp4", "wmv", "avi", "mkv", "rm", "rmvb", "vob", "dat", "asf", "mpg", "ts", "mpeg", "mpe", "mov", "flv", "f4v", "3gp" }; 223 | return this.multiStringEqualCheck(videoExt, extension); 224 | } 225 | 226 | private bool multiStringEqualCheck(string[] targets, string source) 227 | { 228 | int len = targets.Length; 229 | for (int i = 0; i < len; i++) 230 | { 231 | if (string.Equals(targets[i], source)) 232 | { 233 | return true; 234 | } 235 | } 236 | return false; 237 | } 238 | 239 | private void removeFileBtn_Click(object sender, EventArgs e) 240 | { 241 | ListView.SelectedIndexCollection indexesREADONLY = fileListView.SelectedIndices; 242 | 243 | int count = indexesREADONLY.Count; 244 | int[] indexes = new int[count]; 245 | for (int i = 0; i < count; i++) 246 | { 247 | indexes[i] = indexesREADONLY[i]; 248 | } 249 | 250 | if (count == 0) 251 | { 252 | MessageBox.Show("未选择任何任务!"); 253 | return; 254 | } 255 | for (int i = 0; i < count; ) 256 | { 257 | int removeIndex = indexes[i++]; 258 | fileListView.Items.RemoveAt(removeIndex); 259 | 260 | // 此时i是刚刚处理的indexes数组元素索引值 +1 ,遍历还未处理的indexes数组 261 | for (int j = i; j < count; j++) 262 | { 263 | // 如果此索引值大于刚刚删除的item的索引值,说明该位置的元素要前移一位 264 | // 如果不大于就不用管,对其位置没有影响 265 | if (indexes[j] > removeIndex) 266 | { 267 | indexes[j]--; 268 | } 269 | } 270 | } 271 | } 272 | 273 | // 编码预设改变时更新所有信息 274 | private void encodeSettingCB_SelectedIndexChanged(object sender, EventArgs e) 275 | { 276 | foreach (taskSetting ts in settings) 277 | { 278 | if (ts != null && String.Equals(this.encodeSettingCB.Text, ts.name)) 279 | { 280 | // Items集合中有此项值才能通过这种方法添加(DropList模式) 281 | this.encoderCB.Text = ts.encoder; 282 | this.audioEncoderCB.Text = ts.audioEncoder; 283 | this.fileFormatCB.Text = ts.outputFormat; 284 | this.cmdCodeTB.Text = ts.encoderSetting; 285 | 286 | this.profileCB.Text = ts.audioProfile; 287 | this.codecModeCB.Text = ts.audioCodecMode; 288 | if (String.Equals(this.bitrateOrQualityLabel, "质量")) 289 | { 290 | this.bitrateOrQualityCB.Text = ts.audioQuality; 291 | } 292 | else 293 | { 294 | this.bitrateOrQualityCB.Text = ts.audioKbps; 295 | } 296 | 297 | break; 298 | } 299 | } 300 | } 301 | 302 | // 点击添加预设按钮 303 | private void addSettingBtn_Click(object sender, EventArgs e) 304 | { 305 | for (int i = 0; i < this.encodeSettingCB.Items.Count; i++) 306 | { 307 | // 如果要添加的预设名称和已有的任意一个相同 308 | if (String.Equals(this.encodeSettingCB.Text, this.encodeSettingCB.Items[i].ToString())) 309 | { 310 | DialogResult dr = MessageBox.Show("确定要覆盖预设" + this.encodeSettingCB.Text + "吗?", "确认覆盖", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); 311 | if (dr == DialogResult.OK) 312 | { 313 | //点确定的代码 314 | saveSetting2File(this.encodeSettingCB.Text); 315 | readAllSettingsFromFiles(); 316 | return; 317 | } 318 | else 319 | { 320 | //点取消的代码 321 | return; 322 | } 323 | } 324 | } 325 | 326 | // 如果没有重复不仅要存储预设,还要更新UI 327 | saveSetting2File(this.encodeSettingCB.Text); 328 | this.encodeSettingCB.Items.Add(this.encodeSettingCB.Text); 329 | readAllSettingsFromFiles(); 330 | } 331 | 332 | private void saveSetting2File(string name) 333 | { 334 | taskSetting ts = new taskSetting(name, this.encoderCB.Text, this.fileFormatCB.Text, this.cmdCodeTB.Text, 335 | this.audioEncoderCB.Text, this.profileCB.Text, this.codecModeCB.Text, this.bitrateOrQualityCB.Text, 336 | this.bitrateOrQualityCB.Text); 337 | string fp = System.Windows.Forms.Application.StartupPath + "\\taskSettings\\" + name + ".json"; 338 | File.WriteAllText(fp, JsonConvert.SerializeObject(ts)); 339 | } 340 | 341 | private int readAllSettingsFromFiles() 342 | { 343 | DirectoryInfo folder = new DirectoryInfo(System.Windows.Forms.Application.StartupPath + "\\taskSettings"); 344 | FileInfo[] fis = folder.GetFiles(); 345 | 346 | settings = new taskSetting[fis.Length]; 347 | int i = 0; 348 | foreach (FileInfo fi in fis) 349 | { 350 | if (String.Equals(fi.Extension, ".json")) // 文件的扩展名要包括.(点) 351 | { 352 | settings[i++] = JsonConvert.DeserializeObject(File.ReadAllText(fi.FullName)); 353 | } 354 | } 355 | return i; 356 | } 357 | 358 | // 音频编码器选项变化时 359 | private void audioEncoderCB_SelectedIndexChanged(object sender, EventArgs e) 360 | { 361 | if (this.audioEncoderCB.SelectedIndex == 0 || this.audioEncoderCB.SelectedIndex == 1) 362 | { 363 | this.profileCB.Enabled = false; 364 | this.codecModeCB.Enabled = false; 365 | this.bitrateOrQualityCB.Enabled = false; 366 | } 367 | else 368 | { 369 | this.profileCB.Enabled = true; 370 | this.addProfileItems(); 371 | this.codecModeCB.Enabled = true; 372 | this.bitrateOrQualityCB.Enabled = true; 373 | } 374 | } 375 | 376 | // 点击移除预设按钮 377 | private void removeSettingBtn_Click(object sender, EventArgs e) 378 | { 379 | // 需要做的事: 380 | // 1.删除保存的json文件(必须先删除,不然文件名就会错误) 381 | // 2.从combobox中删除,并显示另一个预设的参数 382 | // 不需要从setting数组中删除对应的元素,因为不可能选到被删除的预设了,如果再次添加同名的预设,会重新读取到setting数组(详见添加预设按钮的代码) 383 | DialogResult dr = MessageBox.Show("确定要删除预设" + this.encodeSettingCB.Text + "吗?", "确认删除", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); 384 | if (dr == DialogResult.OK) 385 | { 386 | //点确定的代码 387 | string fp = System.Windows.Forms.Application.StartupPath + "\\taskSettings\\" + this.encodeSettingCB.Text + ".json"; 388 | File.Delete(fp); 389 | this.encodeSettingCB.Items.Remove(this.encodeSettingCB.Text); 390 | this.encodeSettingCB.SelectedIndex = 0; 391 | } 392 | else 393 | { 394 | //点取消的代码 395 | } 396 | } 397 | 398 | // 点击移除所有按钮 399 | private void removeAllBtn_Click(object sender, EventArgs e) 400 | { 401 | fileListView.Items.Clear(); 402 | } 403 | 404 | // 选择输出文件夹 405 | private void chooseOutputPathBtn_Click(object sender, EventArgs e) 406 | { 407 | FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog(); 408 | if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) 409 | { 410 | string folderPath = folderBrowserDialog1.SelectedPath; 411 | this.outputFilePathTB.Text = folderPath; 412 | } 413 | } 414 | 415 | // 点击应用到选中 416 | private void set2SelectedBtn_Click(object sender, EventArgs e) 417 | { 418 | ListView.SelectedIndexCollection indexes = fileListView.SelectedIndices; 419 | int count = indexes.Count; 420 | if (count == 0) 421 | { 422 | MessageBox.Show("未选择任何任务!"); 423 | return; 424 | } 425 | for (int i = 0; i < count; i++) 426 | { 427 | fileListView.Items[indexes[i]].SubItems[1].Text = this.encodeSettingCB.Text; 428 | } 429 | } 430 | 431 | // 点击全部应用 432 | private void set2AllBtn_Click(object sender, EventArgs e) 433 | { 434 | for (int i = 0; i < this.fileListView.Items.Count; i++) 435 | { 436 | fileListView.Items[i].SubItems[1].Text = this.encodeSettingCB.Text; 437 | } 438 | } 439 | 440 | // 检查预设与UI显示的有无不同, 结果1和0分别表示真和假,-1表示预设不存在 441 | private int checkSettingChange() 442 | { 443 | string fp = System.Windows.Forms.Application.StartupPath + "\\taskSettings\\" + this.encodeSettingCB.Text + ".json"; 444 | try 445 | { 446 | taskSetting ts = JsonConvert.DeserializeObject(File.ReadAllText(fp)); 447 | if (String.Equals(this.encoderCB.Text, ts.encoder) 448 | && String.Equals(this.fileFormatCB.Text, ts.outputFormat) 449 | && String.Equals(this.cmdCodeTB.Text, ts.encoderSetting) 450 | && String.Equals(this.audioEncoderCB.Text, ts.audioEncoder) 451 | && (String.Equals(this.profileCB.Text, ts.audioProfile) || this.profileCB.Enabled == false) 452 | && (String.Equals(this.codecModeCB.Text, ts.audioCodecMode) || this.codecModeCB.Enabled == false) 453 | && (String.Equals(this.bitrateOrQualityCB.Text, ts.audioQuality) || this.bitrateOrQualityCB.Enabled == false)) 454 | { 455 | return 0; // false表示没有变化 456 | } 457 | return 1; 458 | } 459 | catch (System.IO.IOException) 460 | { 461 | return -1; 462 | } 463 | } 464 | 465 | // 检查预设是否存在 466 | private bool CheckSettingExist(string s) 467 | { 468 | string fp = System.Windows.Forms.Application.StartupPath + "\\taskSettings\\" + s + ".json"; 469 | return File.Exists(fp); 470 | } 471 | 472 | private void DisposeJob() 473 | { 474 | this.j = null; 475 | GC.Collect(); 476 | } 477 | 478 | private void profileCB_SelectedIndexChanged(object sender, EventArgs e) 479 | { 480 | ComboBox comboBox = (ComboBox)sender; 481 | if (string.Equals(comboBox.Text, "HE-AAC")) 482 | { 483 | //this.bitrateOrQualityCB.Enabled = true; 484 | //this.codecModeCB.Enabled = true; 485 | this.addCodecModeItems(); 486 | this.codecModeCB.SelectedIndex = 0; 487 | this.brORqLabel.Text = "码率"; 488 | this.addBitrateItems(); 489 | this.bitrateOrQualityCB.Text = "48"; // 设置默认值 490 | } 491 | else if (string.Equals(comboBox.Text, "LC-AAC")) 492 | { 493 | //this.bitrateOrQualityCB.Enabled = true; 494 | //this.codecModeCB.Enabled = true; 495 | this.addCodecModeItems(); 496 | this.codecModeCB.SelectedIndex = 3; 497 | this.brORqLabel.Text = "质量"; 498 | this.addQualityItems(); 499 | this.bitrateOrQualityCB.Text = "91"; // 设置默认值 500 | } else 501 | { 502 | this.bitrateOrQualityCB.Enabled = false; 503 | this.codecModeCB.Enabled = false; 504 | } 505 | } 506 | 507 | private void addQualityItems() 508 | { 509 | this.bitrateOrQualityCB.Items.Clear(); 510 | this.bitrateOrQualityCB.Items.Add("0"); 511 | this.bitrateOrQualityCB.Items.Add("9"); 512 | this.bitrateOrQualityCB.Items.Add("18"); 513 | this.bitrateOrQualityCB.Items.Add("27"); 514 | this.bitrateOrQualityCB.Items.Add("36"); 515 | this.bitrateOrQualityCB.Items.Add("45"); 516 | this.bitrateOrQualityCB.Items.Add("54"); 517 | this.bitrateOrQualityCB.Items.Add("63"); 518 | this.bitrateOrQualityCB.Items.Add("73"); 519 | this.bitrateOrQualityCB.Items.Add("82"); 520 | this.bitrateOrQualityCB.Items.Add("91"); 521 | this.bitrateOrQualityCB.Items.Add("100"); 522 | this.bitrateOrQualityCB.Items.Add("109"); 523 | this.bitrateOrQualityCB.Items.Add("118"); 524 | this.bitrateOrQualityCB.Items.Add("127"); 525 | } 526 | 527 | private void addBitrateItems() 528 | { 529 | this.bitrateOrQualityCB.Items.Clear(); 530 | this.bitrateOrQualityCB.Items.Add("32"); 531 | this.bitrateOrQualityCB.Items.Add("64"); 532 | this.bitrateOrQualityCB.Items.Add("96"); 533 | this.bitrateOrQualityCB.Items.Add("128"); 534 | this.bitrateOrQualityCB.Items.Add("192"); 535 | this.bitrateOrQualityCB.Items.Add("256"); 536 | this.bitrateOrQualityCB.Items.Add("320"); 537 | } 538 | 539 | private void addCodecModeItems() 540 | { 541 | this.codecModeCB.Items.Clear(); 542 | this.codecModeCB.Items.Add("CBR"); 543 | this.codecModeCB.Items.Add("ABR"); 544 | this.codecModeCB.Items.Add("CVBR"); 545 | if (this.profileCB.SelectedIndex == 0) 546 | { 547 | this.codecModeCB.Items.Add("TVBR"); 548 | } 549 | } 550 | 551 | private void addProfileItems() 552 | { 553 | if (this.audioEncoderCB.SelectedIndex == 2) 554 | { 555 | this.profileCB.Items.Clear(); 556 | this.profileCB.Items.Add("LC-AAC"); 557 | this.profileCB.Items.Add("HE-AAC"); 558 | this.profileCB.Items.Add("ALAC"); 559 | this.profileCB.SelectedIndex = 0; 560 | } 561 | } 562 | 563 | private void codecModeCB_SelectedIndexChanged(object sender, EventArgs e) 564 | { 565 | ComboBox comboBox = (ComboBox)sender; 566 | if (string.Equals(comboBox.Text, "TVBR")) 567 | { 568 | this.brORqLabel.Text = "质量"; 569 | this.addQualityItems(); 570 | this.bitrateOrQualityCB.Text = "91"; // 设置默认值 571 | } 572 | else 573 | { 574 | if (string.Equals(this.brORqLabel.Text, "质量")) 575 | { 576 | this.brORqLabel.Text = "码率"; 577 | this.addBitrateItems(); 578 | 579 | this.bitrateOrQualityCB.Text = "256"; // 设置默认值 580 | } 581 | } 582 | } 583 | 584 | // 将文件名和预设数据添加到UI,并优化显示模式 585 | private void addItem2FileListView(string fp, string setting) 586 | { 587 | // 生成显示在UI上的字符串 588 | string dot = "."; 589 | 590 | var fpFullWidth = this.CreateGraphics().MeasureString(fp, this.fileListView.Font).Width; // 获取文本的显示宽度 591 | var dotWidth = this.CreateGraphics().MeasureString(dot, this.fileListView.Font).Width; 592 | 593 | var columnWidth = this.fileListView.Columns[0].Width - (int)dotWidth; 594 | 595 | string visualfp = ""; 596 | if (fpFullWidth <= columnWidth) // 文本不大于列宽度,则全部显示,不做处理 597 | { 598 | visualfp = fp; 599 | } 600 | else 601 | { 602 | int length = fp.Length; // 文字字符长度 603 | double averageWidth = fpFullWidth / length; // 平均每个字符的显示宽度 604 | 605 | double frontRatio = 0.2; // 文本前部占有效信息的比例,0.5表示前后各一半 606 | int dotCount = 6; 607 | double frontTextWidth = (columnWidth - dotWidth * dotCount) * frontRatio; 608 | int frontTextLength = (int)Math.Round(frontTextWidth / averageWidth); 609 | frontTextLength = frontTextLength >= 3 ? frontTextLength : 3; // 文本前部长度最小为3,至少要能显示盘符 610 | int rearTextLength = (int)Math.Round(frontTextLength * (1 - frontRatio) / frontRatio); 611 | 612 | int rearStartIndex = length - rearTextLength; 613 | visualfp = fp.Substring(0, frontTextLength) + ("").PadLeft(dotCount, '0').Replace("0", dot) + fp.Substring(rearStartIndex, rearTextLength); 614 | 615 | // 以上为初步生成,如果不符合要求,则继续修剪 616 | var tempWidth = this.CreateGraphics().MeasureString(visualfp, this.fileListView.Font).Width; 617 | bool trimTooMuch = false; 618 | 619 | // 两种情况下要修剪,1.超出宽度 2.宽度少一个点以上 620 | while( tempWidth > columnWidth || (trimTooMuch = (columnWidth - tempWidth > dotWidth)) ) 621 | { 622 | if (trimTooMuch == false) // 第一种情况 623 | { 624 | if (frontTextLength <= 3) // 文本前部即将小于最小宽度,只能修建文本后部 625 | { 626 | // 已知问题:遇到超长字符串时,修剪完前部文本再修剪后部文本时,函数直接从这里跳出,没有异常,界面上也显示不了这个文件。 627 | // 准备先加异常处理看看。20180531 1320 628 | try 629 | { 630 | visualfp = fp.Substring(0, frontTextLength) + ("").PadLeft(dotCount, '0').Replace("0", dot) + fp.Substring(++rearStartIndex, rearTextLength); 631 | } 632 | catch (Exception e) 633 | { 634 | //MessageBox.Show(e.ToString()); 635 | break; 636 | } 637 | 638 | } 639 | else // 否则修剪文本前部 640 | { 641 | visualfp = fp.Substring(0, --frontTextLength) + ("").PadLeft(dotCount, '0').Replace("0", dot) + fp.Substring(rearStartIndex, rearTextLength); 642 | } 643 | } 644 | else // 第二种情况,直接前移文本后部的起始索引 645 | { 646 | visualfp = fp.Substring(0, frontTextLength) + ("").PadLeft(dotCount, '0').Replace("0", dot) + fp.Substring(--rearStartIndex, ++rearTextLength); 647 | trimTooMuch = false; // 重置判断状态 648 | } 649 | tempWidth = this.CreateGraphics().MeasureString(visualfp, this.fileListView.Font).Width; 650 | } 651 | } 652 | ListViewItem item = new ListViewItem(new string[] { visualfp, setting, fp }); 653 | this.fileListView.Items.Add(item); 654 | } 655 | } 656 | } -------------------------------------------------------------------------------- /ExpertVideoToolbox/TaskManager/Job.cs: -------------------------------------------------------------------------------- 1 | using MediaInfoLib; 2 | using ExpertVideoToolbox.cmdCodeGenerator; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using System.Windows.Forms; 12 | using ExpertVideoToolbox.TaskManager; 13 | using Newtonsoft.Json; 14 | 15 | namespace ExpertVideoToolbox.taskManager 16 | { 17 | class Job 18 | { 19 | public delegate void ErrorHandler(); //声明委托 20 | public event ErrorHandler ErrorEvent; //声明事件 21 | 22 | delegate void InnerMethodDelagate(); 23 | 24 | const int AUDIOENCODE = 0; 25 | const int VIDEOENCODE = 1; 26 | const int MUXER = 2; 27 | const int AUDIOCOPY = 3; 28 | const int DELETEVIDEOTEMP = 4; 29 | const int DELETEAUDIOTEMP = 5; 30 | 31 | const int ONLYVIDEO = 0; 32 | const int SUPPRESSAUDIO = 1; 33 | const int COPYAUDIO = 2; 34 | 35 | const int NORMAL = 0; 36 | const int AVS = 1; 37 | const int VPY = 2; 38 | 39 | long outPutCmdCount = 0; 40 | long outPutCmdCheckCount = 0; 41 | 42 | private runningPool rp; 43 | public videoTask[] tasks; 44 | public int num; 45 | public int finishedNum; 46 | public int threadsNum; 47 | private bool[] isfinished; 48 | private string outputFolderPath; 49 | private int videoType; 50 | 51 | private RunningStatusForm rsForm; 52 | 53 | private int[] PIDs; 54 | private int subTaskPID; 55 | 56 | private int startTime = 0; 57 | private int endTime; 58 | 59 | private int checkPattern; 60 | private int[] checkTime; 61 | private int[] checkFrame; 62 | private double[] fps; 63 | 64 | private bool audioProcessing; 65 | private bool encoding; 66 | private bool postProcessing; 67 | private bool muxing; 68 | private bool isfailed; 69 | 70 | private StringBuilder log; 71 | private string miniLog; 72 | private int reportCount; 73 | 74 | private Thread ctrlThread; 75 | Thread[] threads; 76 | 77 | //private Process process = null; 78 | 79 | public Job(filePathStorage tempQueue) 80 | { 81 | // 从storage读取num 82 | this.num = tempQueue.Count(); 83 | this.threadsNum = 1; 84 | 85 | this.finishedNum = 0; 86 | 87 | encoding = false; 88 | audioProcessing = false; 89 | muxing = false; 90 | 91 | // 初始化task数组来feed下面的queue 92 | this.tasks = new videoTask[num]; 93 | this.PIDs = new int[threadsNum]; 94 | this.subTaskPID = Int32.MaxValue; 95 | this.isfinished = new bool[threadsNum]; 96 | 97 | reportCount = 0; 98 | checkPattern = 80; 99 | int cpx2 = checkPattern + checkPattern; 100 | checkTime = new int[cpx2]; 101 | checkFrame = new int[cpx2]; 102 | this.fps = new double[cpx2]; 103 | for (int i = 0; i < cpx2; i++) 104 | { 105 | this.fps[i] = 0; 106 | } 107 | 108 | for (int i = 0; i < num; i++ ) 109 | { 110 | this.tasks[i] = tempQueue.get(i); 111 | } 112 | 113 | // 初始化运行池pool 114 | this.rp = new runningPool(this.num, this.tasks); // 运行池持有队列,需传递队列的相关参数 115 | 116 | // 初始化运行状态窗口 117 | this.rsForm = new RunningStatusForm(); 118 | 119 | log = new StringBuilder(""); 120 | this.rsForm.AbortEvent += saveLog2File; 121 | this.rsForm.ClosingEvent += AllThreadKill; 122 | 123 | } 124 | 125 | public void runJob(string ofp) 126 | { 127 | this.rsForm.Show(); 128 | this.rsForm.setStatusBarFilesCountLabel(this.finishedNum, this.num); 129 | 130 | this.outputFolderPath = ofp; 131 | 132 | this.threads = new Thread[this.threadsNum]; 133 | for (int i = 0; i < threadsNum; i++) 134 | { 135 | int p = i; 136 | Thread th = new Thread(()=> 137 | { 138 | this.isfinished[p] = false; 139 | this.threadRun(p); 140 | }); 141 | threads[p] = th; 142 | } 143 | for (int i = 0; i < threadsNum; i++) 144 | { 145 | threads[i].Start(); 146 | } 147 | 148 | } 149 | 150 | public int getPID() 151 | { 152 | return this.PIDs[0]; 153 | } 154 | 155 | private void threadRun(int threadIndex) 156 | { 157 | videoTask t = rp.getTask(); 158 | videoTask next; 159 | 160 | for (int i = 0; i < this.num; i++) 161 | { 162 | this.isfailed = false; // 将任务失败状态设为否 163 | if (i != 0) 164 | { 165 | rp.removeTask(t, false); // false表示成功完成编码没有失败 166 | } 167 | 168 | this.runTask(t, this.rsForm.process); 169 | 170 | next = rp.getTask(); // get之后任务已从运行池的等待队列中pop出了,无需再次get 171 | //MessageBox.Show(next.printTask()); 172 | if (next == null) 173 | { 174 | rp.removeTask(t, false); 175 | break; 176 | } 177 | t = next; 178 | } 179 | } 180 | 181 | private void runTask(videoTask t, Process process) 182 | { 183 | this.rsForm.setPercent("0.0"); 184 | this.rsForm.setTime(""); 185 | this.rsForm.setFps(""); 186 | this.rsForm.setEta(""); 187 | 188 | string fp = t.getFP(); 189 | 190 | process = new System.Diagnostics.Process(); 191 | 192 | process.StartInfo.FileName = "cmd"; 193 | 194 | // 必须禁用操作系统外壳程序 195 | process.StartInfo.UseShellExecute = false; 196 | process.StartInfo.CreateNoWindow = true; 197 | process.StartInfo.RedirectStandardError = true; 198 | process.StartInfo.RedirectStandardOutput = true; 199 | process.StartInfo.RedirectStandardInput = true; 200 | 201 | process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler); 202 | process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); 203 | 204 | process.Start(); 205 | 206 | this.PIDs[0] = process.Id; 207 | this.rsForm.PID = process.Id; 208 | this.rsForm.setStopBtnState(true); 209 | 210 | // 找到预设存储的文件并提取到taskSetting中 211 | string tsfp = System.Windows.Forms.Application.StartupPath + "\\taskSettings\\" + t.getSetting() + ".json"; 212 | taskSetting ts = JsonConvert.DeserializeObject(File.ReadAllText(tsfp)); 213 | 214 | // 将encoder信息传给信息显示界面 215 | this.rsForm.encodingProgram = ts.encoder; 216 | this.rsForm.HideVideoEncoderSetting(); 217 | 218 | cmdCode c = new cmdCode(fp, ts, this.outputFolderPath); 219 | string cmd; 220 | 221 | int type = c.taskType(); 222 | int checkNum = 0; 223 | 224 | int beforeProcessCheckTime = 3500; 225 | int processCheckInterval = 1000; 226 | const int checkF = 20; 227 | 228 | // 定义一个内部(匿名)方法 229 | // 整个视频转换过程结束时 230 | InnerMethodDelagate afterSuccess = delegate() 231 | { 232 | this.finishedNum++; 233 | this.rsForm.setStatusBarFilesCountLabel(this.finishedNum, this.num); 234 | 235 | try 236 | { 237 | process.CancelErrorRead(); 238 | process.CancelOutputRead(); 239 | } 240 | catch (Exception e) 241 | { 242 | //saveLog2File(); 243 | } 244 | 245 | this.rsForm.setEta(""); 246 | this.rsForm.setFps(""); 247 | this.rsForm.setTime(""); 248 | this.rsForm.setEstKbps(""); 249 | this.rsForm.SetTaskStepsLabel(true); 250 | 251 | Process p = Process.GetProcessById(this.PIDs[0]); 252 | p.Kill(); 253 | this.rsForm.setStopBtnState(false); 254 | this.rsForm.setPercent("-3"); 255 | this.isfinished[0] = true; 256 | this.reportCount = 0; 257 | this.log.Clear(); 258 | 259 | miniLog += t.getFP() + Environment.NewLine + Environment.NewLine + Environment.NewLine; 260 | saveMiniLog2File(); 261 | }; 262 | 263 | // 运行失败时调用 264 | InnerMethodDelagate afterFailed = delegate() 265 | { 266 | this.isfailed = true; 267 | 268 | saveLog2File(); 269 | 270 | this.rsForm.setPercent("-1"); 271 | this.rsForm.setTime("发生错误"); 272 | this.rsForm.setFps("日志保存在程序目录"); 273 | 274 | int sleepTime = 5; // 设置失败后继续下一个任务的时间 275 | this.rsForm.setEta(sleepTime.ToString() + "秒后继续运行"); 276 | 277 | this.rsForm.setStatusBarLabelTextColorRED(); 278 | this.finishedNum++; 279 | this.rsForm.setStatusBarFilesCountLabel(this.finishedNum, this.num); 280 | this.rsForm.HideVideoEncoderSetting(); 281 | 282 | try 283 | { 284 | process.CancelErrorRead(); 285 | process.CancelOutputRead(); 286 | } 287 | catch (Exception e) 288 | { 289 | //saveLog2File(); 290 | } 291 | 292 | Thread.Sleep(sleepTime * 1000); 293 | 294 | Process p = Process.GetProcessById(this.PIDs[0]); 295 | p.Kill(); 296 | this.rsForm.setStopBtnState(false); 297 | this.rsForm.setPercent("-3"); 298 | this.isfinished[0] = true; 299 | this.reportCount = 0; 300 | this.log.Clear(); 301 | }; 302 | 303 | // 视频编码前更新UI(显示视频总帧数) 304 | InnerMethodDelagate DispVideoFrames = delegate() 305 | { 306 | // MediaInfo读取视频帧数 307 | MediaInfo MI = new MediaInfo(); 308 | string duration; 309 | string frameRate; 310 | string frames; 311 | MI.Open(t.getFP()); 312 | duration = MI.Get(StreamKind.Video, 0, "Duration"); 313 | try 314 | { 315 | double totalTime = Double.Parse(duration) / 1000.0; 316 | frameRate = MI.Get(StreamKind.Video, 0, "FrameRate"); 317 | frames = ((int)(totalTime * Double.Parse(frameRate))).ToString(); 318 | 319 | if (!String.IsNullOrWhiteSpace(frames)) 320 | { 321 | this.rsForm.setTime("0/" + frames); 322 | } 323 | } 324 | catch (Exception e) 325 | { 326 | //saveLog2File(); 327 | } 328 | }; 329 | 330 | InnerMethodDelagate VideoEncode = delegate() 331 | { 332 | // 视频编码 333 | this.encoding = true; 334 | this.rsForm.setPercent("0.0"); 335 | 336 | string ext = this.getFileExtName(t.getFP()); 337 | if (String.Equals(ext, "avs", StringComparison.CurrentCultureIgnoreCase)) 338 | { 339 | this.videoType = AVS; 340 | } 341 | else 342 | { 343 | this.videoType = NORMAL; 344 | DispVideoFrames(); 345 | } 346 | 347 | cmd = c.cmdCodeGenerate(VIDEOENCODE, this.videoType); 348 | process.StandardInput.WriteLine(cmd); 349 | 350 | try 351 | { 352 | process.BeginErrorReadLine(); 353 | process.BeginOutputReadLine(); 354 | } 355 | catch (Exception e) 356 | { 357 | //saveLog2File(); 358 | } 359 | 360 | checkNum = 0; 361 | this.reportCount = 0; 362 | int cpx2 = this.checkPattern + this.checkPattern; 363 | for (int i = 0; i < cpx2; i++) 364 | { 365 | checkFrame[i] = 0; 366 | } 367 | for (int i = 0; i < cpx2; i++) 368 | { 369 | this.fps[i] = 0; 370 | } 371 | 372 | Thread.Sleep(beforeProcessCheckTime); 373 | 374 | Process p; 375 | switch (videoType) 376 | { 377 | case NORMAL: 378 | p = GetSubTaskProcess(ts.encoder); 379 | if (p != null) 380 | { 381 | this.subTaskPID = p.Id; 382 | } 383 | else 384 | { 385 | this.subTaskPID = -1; 386 | } 387 | break; 388 | case AVS: 389 | Process avsP = GetSubTaskProcess("avs4x265.exe"); 390 | int avsId = avsP.Id; 391 | if (avsP != null) 392 | { 393 | bool hasFound = false; 394 | 395 | // 等待视频编码进程启动,最长等待1小时 396 | for (int i = 0; i < 7200; i++) 397 | { 398 | // 确认avs进程仍在运行 399 | try 400 | { 401 | Process.GetProcessById(avsId); 402 | } 403 | catch (Exception e) 404 | { 405 | if (this.encoding == true || ConfirmFailed()) 406 | { 407 | afterFailed(); 408 | } 409 | return; 410 | } 411 | 412 | // 每隔500ms寻找视频编码进程 413 | p = GetSubTaskProcess(ts.encoder, avsId); 414 | if (p != null) 415 | { 416 | this.subTaskPID = p.Id; 417 | hasFound = true; 418 | break; 419 | } 420 | else 421 | { 422 | Thread.Sleep(500); 423 | } 424 | } 425 | 426 | if (!hasFound) 427 | { 428 | this.subTaskPID = -1; 429 | } 430 | } 431 | else 432 | { 433 | this.subTaskPID = -1; 434 | } 435 | break; 436 | default: 437 | break; 438 | } 439 | 440 | this.rsForm.ShowVideoEncoderSetting(); 441 | 442 | while (this.encoding == true || this.postProcessing == true) 443 | { 444 | try 445 | { 446 | Process.GetProcessById(this.subTaskPID); 447 | } 448 | catch (Exception e) 449 | { 450 | if (this.encoding == true || ConfirmFailed()) 451 | { 452 | afterFailed(); 453 | } 454 | return; 455 | } 456 | 457 | Thread.Sleep(processCheckInterval); 458 | } 459 | try 460 | { 461 | process.CancelErrorRead(); 462 | process.CancelOutputRead(); 463 | } 464 | catch (Exception e) 465 | { 466 | //saveLog2File(); 467 | } 468 | 469 | this.rsForm.HideVideoEncoderSetting(); 470 | }; 471 | 472 | InnerMethodDelagate Mux = delegate() 473 | { 474 | // muxer 475 | this.muxing = true; 476 | int stepIdx = type == ONLYVIDEO ? 2 : 3; 477 | this.rsForm.SetTaskStepsLabel(false, stepIdx, stepIdx, MUXER); 478 | 479 | cmd = c.cmdCodeGenerate(MUXER); 480 | process.StandardInput.WriteLine(cmd); 481 | 482 | try 483 | { 484 | process.BeginErrorReadLine(); 485 | process.BeginOutputReadLine(); 486 | } 487 | catch (Exception e) 488 | { 489 | //saveLog2File(); 490 | } 491 | 492 | checkNum = 0; 493 | 494 | Thread.Sleep(beforeProcessCheckTime); // 有些超短的视频(1-2M),如果不加这句就会直接判定为任务已失败,疑似原因:没等判断完进程就已经结束 495 | 496 | string muxerProcessName = ""; 497 | if (String.Equals("mp4", ts.outputFormat)) 498 | { 499 | muxerProcessName = "mp4Box"; 500 | } 501 | else if (String.Equals("mkv", ts.outputFormat)) 502 | { 503 | muxerProcessName = "mkvmerge"; 504 | } 505 | 506 | Process p = GetSubTaskProcess(muxerProcessName); 507 | if (p != null) 508 | { 509 | this.subTaskPID = p.Id; 510 | } 511 | else 512 | { 513 | this.subTaskPID = -1; 514 | } 515 | 516 | while (this.muxing == true) 517 | { 518 | try 519 | { 520 | Process.GetProcessById(this.subTaskPID); 521 | } 522 | catch (Exception e) 523 | { 524 | Thread.Sleep(1000); 525 | if (this.muxing == true) 526 | { 527 | afterFailed(); 528 | } 529 | return; 530 | } 531 | 532 | Thread.Sleep(processCheckInterval); 533 | //checkNum = checkCmdRunning(checkNum, checkF); 534 | //if (checkNum == -1) 535 | //{ 536 | // return; 537 | //} 538 | } 539 | 540 | afterSuccess(); 541 | 542 | string tempVideoFp = c.cmdCodeGenerate(DELETEVIDEOTEMP); 543 | string tempAudioFp = c.cmdCodeGenerate(DELETEAUDIOTEMP); 544 | try 545 | { 546 | File.Delete(tempVideoFp); 547 | File.Delete(tempAudioFp); 548 | } 549 | catch (System.IO.IOException ex) 550 | { 551 | this.log.AppendLine("出现异常:" + ex); 552 | saveLog2File(); 553 | } 554 | }; 555 | 556 | // 音频编码或复制开始前更新UI(显示音频总时长) 557 | InnerMethodDelagate DispAudioDuration = delegate() 558 | { 559 | // MediaInfo读取音频时长 560 | MediaInfo MI = new MediaInfo(); 561 | string duration; 562 | MI.Open(c.getAudioSource()); 563 | duration = MI.Get(StreamKind.Audio, 0, 69); 564 | 565 | if (!String.IsNullOrWhiteSpace(duration)) 566 | { 567 | this.rsForm.setTime("0/" + duration); 568 | } 569 | 570 | this.rsForm.setPercent("0.0", AUDIOENCODE); 571 | }; 572 | 573 | InnerMethodDelagate ClearUIAfterAudioProcessing = delegate() 574 | { 575 | this.rsForm.setPercent("0.0"); 576 | this.rsForm.setTime(""); 577 | this.rsForm.setFps(""); 578 | }; 579 | 580 | switch (type) 581 | { 582 | case ONLYVIDEO: 583 | 584 | this.rsForm.SetTaskStepsLabel(false, 1, 2, VIDEOENCODE); 585 | 586 | VideoEncode(); 587 | 588 | // 一个子任务失败了意味着这个文件的编码任务失败,所以在所有子任务开始时都要检查checkNum是否为-1 589 | if (isfailed) 590 | { 591 | return; 592 | } 593 | //afterSuccess(); 594 | 595 | Mux(); 596 | 597 | break; 598 | case COPYAUDIO: 599 | // 复制音频 600 | cmd = c.cmdCodeGenerate(AUDIOCOPY); 601 | process.StandardInput.WriteLine(cmd); 602 | process.BeginErrorReadLine(); 603 | process.BeginOutputReadLine(); 604 | this.audioProcessing = true; 605 | this.rsForm.SetTaskStepsLabel(false, 1, 3, AUDIOCOPY); 606 | DispAudioDuration(); 607 | 608 | checkNum = 0; 609 | 610 | Thread.Sleep(beforeProcessCheckTime); 611 | 612 | Process p = GetSubTaskProcess("ffmpeg"); 613 | if (p != null) 614 | { 615 | this.subTaskPID = p.Id; 616 | } 617 | else 618 | { 619 | this.subTaskPID = -1; 620 | } 621 | 622 | while (this.audioProcessing == true) 623 | { 624 | try 625 | { 626 | Process.GetProcessById(this.subTaskPID); 627 | } 628 | catch (Exception e) 629 | { 630 | Thread.Sleep(1000); 631 | if (this.audioProcessing == true) 632 | { 633 | afterFailed(); 634 | } 635 | return; 636 | } 637 | 638 | Thread.Sleep(processCheckInterval); 639 | //checkNum = checkCmdRunning(checkNum, checkF); 640 | //if (checkNum == -1) 641 | //{ 642 | // return; 643 | //} 644 | } 645 | ClearUIAfterAudioProcessing(); 646 | 647 | process.CancelErrorRead(); 648 | process.CancelOutputRead(); 649 | 650 | this.rsForm.SetTaskStepsLabel(false, 2, 3, VIDEOENCODE); 651 | 652 | // 一个子任务失败了意味着这个文件的编码任务失败,所以在所有子任务开始时都要检查checkNum是否为-1 653 | if (isfailed) 654 | { 655 | return; 656 | } 657 | VideoEncode(); 658 | 659 | // 一个子任务失败了意味着这个文件的编码任务失败,所以在所有子任务开始时都要检查checkNum是否为-1 660 | if (isfailed) 661 | { 662 | return; 663 | } 664 | Mux(); 665 | 666 | break; 667 | case SUPPRESSAUDIO: 668 | // 音频编码 669 | cmd = c.cmdCodeGenerate(AUDIOENCODE); 670 | process.StandardInput.WriteLine(cmd); 671 | process.BeginErrorReadLine(); 672 | process.BeginOutputReadLine(); 673 | this.audioProcessing = true; 674 | this.rsForm.SetTaskStepsLabel(false, 1, 3, AUDIOENCODE); 675 | DispAudioDuration(); 676 | 677 | checkNum = 0; 678 | 679 | Thread.Sleep(beforeProcessCheckTime); 680 | 681 | Process p2 = GetSubTaskProcess(ts.audioEncoder); 682 | if (p2 != null) 683 | { 684 | this.subTaskPID = p2.Id; 685 | } 686 | else 687 | { 688 | this.subTaskPID = -1; 689 | } 690 | 691 | while (this.audioProcessing == true) 692 | { 693 | try 694 | { 695 | Process.GetProcessById(this.subTaskPID); 696 | } 697 | catch (Exception e) 698 | { 699 | Thread.Sleep(1000); 700 | if (this.audioProcessing == true) 701 | { 702 | afterFailed(); 703 | } 704 | return; 705 | } 706 | 707 | Thread.Sleep(processCheckInterval); 708 | //checkNum = checkCmdRunning(checkNum, checkF); 709 | //if (checkNum == -1) 710 | //{ 711 | // return; 712 | //} 713 | } 714 | ClearUIAfterAudioProcessing(); 715 | 716 | process.CancelErrorRead(); 717 | process.CancelOutputRead(); 718 | 719 | this.rsForm.SetTaskStepsLabel(false, 2, 3, VIDEOENCODE); 720 | 721 | // 一个子任务失败了意味着这个文件的编码任务失败,所以在所有子任务开始时都要检查checkNum是否为-1 722 | if (isfailed) 723 | { 724 | return; 725 | } 726 | VideoEncode(); 727 | 728 | // 一个子任务失败了意味着这个文件的编码任务失败,所以在所有子任务开始时都要检查checkNum是否为-1 729 | if (isfailed) 730 | { 731 | return; 732 | } 733 | Mux(); 734 | 735 | break; 736 | default: 737 | cmd = ""; 738 | break; 739 | } 740 | 741 | //MessageBox.Show(cmd); 742 | } 743 | 744 | private void ResetRsForm() 745 | { 746 | this.rsForm.setEta(""); 747 | this.rsForm.setFps(""); 748 | this.rsForm.setTime(""); 749 | 750 | this.rsForm.setStatusBarFilesCountLabel(this.finishedNum, this.num); 751 | } 752 | 753 | public void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 754 | { 755 | this.outPutCmdCount++; 756 | if (!String.IsNullOrEmpty(outLine.Data) && this.num != this.finishedNum) 757 | { 758 | string o = outLine.Data.ToString(); 759 | log.AppendLine(o); 760 | 761 | // 音频编码解析 762 | if (this.audioProcessing == true) 763 | { 764 | string audioCopyFinishFlag = "video:0kB audio:"; 765 | string audioEncodeFinishFlag = "Optimizing...done"; 766 | this.rsForm.setPercent("-1"); 767 | 768 | string time = ""; 769 | string totalTime = ""; 770 | 771 | InnerMethodDelagate CalculateAndDispProgress = delegate() 772 | { 773 | string[] splitTemp = totalTime.Split(new char[] { ':' }); 774 | 775 | string HH = "0"; 776 | string MM = "0"; 777 | string SSMMM = "0"; 778 | 779 | if (splitTemp.Length == 3) 780 | { 781 | HH = splitTemp[0]; 782 | MM = splitTemp[1]; 783 | SSMMM = splitTemp[2]; 784 | } else if (splitTemp.Length == 3) 785 | { 786 | HH = "00"; 787 | MM = splitTemp[0]; 788 | SSMMM = splitTemp[1]; 789 | } 790 | 791 | int hr = Convert.ToInt32(HH); 792 | int min = Convert.ToInt32(MM); 793 | double sec = Convert.ToDouble(SSMMM); 794 | double totalTimeValue = hr * 3600 + min * 60 + sec; 795 | 796 | splitTemp = time.Split(new char[] { ':' }); 797 | if (splitTemp.Length == 2) 798 | { 799 | HH = "00"; 800 | MM = splitTemp[0]; 801 | SSMMM = splitTemp[1]; 802 | } 803 | else if (splitTemp.Length == 3) 804 | { 805 | HH = splitTemp[0]; 806 | MM = splitTemp[1]; 807 | SSMMM = splitTemp[2]; 808 | } 809 | hr = Convert.ToInt32(HH); 810 | min = Convert.ToInt32(MM); 811 | sec = Convert.ToDouble(SSMMM); 812 | double currentTimeValue = hr * 3600 + min * 60 + sec; 813 | double percent = currentTimeValue / totalTimeValue; 814 | this.rsForm.setPercent(percent.ToString("0.0"), AUDIOENCODE); //这一模式需要保留一位小数 815 | }; 816 | 817 | if (o.Contains(audioCopyFinishFlag) || o.Contains(audioEncodeFinishFlag)) 818 | { 819 | this.audioProcessing = false; 820 | } 821 | else 822 | { 823 | if (o.Contains("time=")) // 表示是音频复制模式 824 | { 825 | int timeIndex = o.IndexOf("time=") + 5; 826 | int timeLength = 11; 827 | time = o.Substring(timeIndex, timeLength); 828 | 829 | string currentTimeText = this.rsForm.getCurrentTimeText(); 830 | int splitIndex = currentTimeText.IndexOf("/"); 831 | totalTime = currentTimeText.Substring(splitIndex + 1, currentTimeText.Length - splitIndex - 1); 832 | if (String.IsNullOrWhiteSpace(totalTime)) 833 | { 834 | totalTime = time; 835 | } 836 | this.rsForm.setTime(time + "/" + totalTime); 837 | CalculateAndDispProgress(); 838 | } 839 | else // 音频编码模式 840 | { 841 | // 通过ffmpeg读取送到qaac转码 842 | // o 的格式 = 时间(速度x) 特征是x) 843 | int endIndex = o.IndexOf("x)"); 844 | int startIndex = o.IndexOf("("); 845 | // 速度 xxx.x 最多5位字符,间隔不应大于5 846 | if (startIndex != -1 && endIndex != -1 && endIndex - startIndex < 6 && endIndex - startIndex > 0) 847 | { 848 | string speed = o.Substring(startIndex + 1, endIndex - startIndex - 1); // 第二个参数是子串的长度 849 | this.rsForm.setFps(speed + "x"); 850 | 851 | // 从UI获取音频时长 852 | string lastCurrentTimeText = this.rsForm.getCurrentTimeText(); 853 | int totalTimeStartIndex = lastCurrentTimeText.IndexOf("/") + 1; 854 | int totalTimeLength = lastCurrentTimeText.Length - totalTimeStartIndex; 855 | totalTime = lastCurrentTimeText.Substring(totalTimeStartIndex, totalTimeLength); 856 | 857 | time = o.Substring(0, startIndex - 1); 858 | 859 | if (String.IsNullOrWhiteSpace(totalTime)) 860 | { 861 | totalTime = time; 862 | } 863 | this.rsForm.setTime(time + "/" + totalTime); 864 | 865 | CalculateAndDispProgress(); 866 | } 867 | } 868 | } 869 | return; 870 | } 871 | 872 | // postProcessing解析 873 | if (this.postProcessing == true) 874 | { 875 | string ppfinishFlag01 = "encoded "; 876 | string ppfinishFlag02 = " frames"; 877 | this.rsForm.setPercent("-2"); 878 | if (o.Contains(ppfinishFlag01) && o.Contains(ppfinishFlag02)) 879 | { 880 | this.postProcessing = false; 881 | miniLog += o + Environment.NewLine; 882 | } 883 | } 884 | 885 | // muxer解析 886 | if (this.muxing == true) 887 | { 888 | string muxingFinishFlag_mp401 = "ISO File Writing: "; 889 | string muxingFinishFlag_mp402 = "| (99/100)"; 890 | string muxingFinishFlag_mkv = "Muxing took "; 891 | this.rsForm.setPercent("-2"); 892 | if ((o.Contains(muxingFinishFlag_mp401) && o.Contains(muxingFinishFlag_mp402)) 893 | || o.Contains(muxingFinishFlag_mkv)) 894 | { 895 | this.muxing = false; 896 | } 897 | return; 898 | } 899 | 900 | // 视频编码解析 901 | string finishFlag01 = "x264 [info]: kb/s:"; 902 | string finishFlag02 = "x265 [info]: consecutive B-frames:"; 903 | //string finishFlag02 = " frames"; 904 | 905 | if (this.encoding) 906 | { 907 | if (this.startTime == 0) // 仅在开始时运行,编码结束后要重置为0 908 | { 909 | this.startTime = System.Environment.TickCount; 910 | } 911 | 912 | if (o.Contains(finishFlag01) || o.Contains(finishFlag02)) // 视频编码结束了 913 | { 914 | miniLog += o + Environment.NewLine; 915 | 916 | this.endTime = System.Environment.TickCount; 917 | 918 | int timeElapsed = this.endTime - this.startTime; 919 | 920 | this.startTime = 0; 921 | 922 | this.rsForm.setPercent("100"); 923 | this.rsForm.setFps(""); 924 | this.rsForm.setEta(""); 925 | this.rsForm.setTime(""); 926 | 927 | // 视频编码结束后,x264可能先对视频流单独混流一次 928 | this.postProcessing = true; 929 | this.encoding = false; 930 | } 931 | else // 编码未结束更新进度 932 | { 933 | if (!o.Contains("[info]") && !o.Contains("q=-0.0 size=")) 934 | { 935 | int checkIndex = this.reportCount % (checkPattern + checkPattern); 936 | checkTime[checkIndex] = System.Environment.TickCount; 937 | string encodedFrames = ""; 938 | string totalFrames = ""; 939 | int kbpsStartIndex, kbpsEndIndex; 940 | 941 | switch (this.videoType) 942 | { 943 | case NORMAL: 944 | // o 的格式 = xx frames: xx.xx fps, xxxx kb/s 945 | 946 | kbpsStartIndex = o.IndexOf("fps, ") + 5; 947 | kbpsEndIndex = o.IndexOf("kb/s") + 4; 948 | 949 | if (kbpsStartIndex != -1 && kbpsEndIndex != -1 && kbpsEndIndex - kbpsStartIndex > 6 && kbpsEndIndex - kbpsStartIndex < 14) 950 | { 951 | string estKbps = o.Substring(kbpsStartIndex, kbpsEndIndex - kbpsStartIndex); 952 | this.rsForm.setEstKbps(estKbps); 953 | } 954 | 955 | // 从UI获取视频总帧数 956 | string lastCurrentTimeText = this.rsForm.getCurrentTimeText(); 957 | int totalTimeStartIndex = lastCurrentTimeText.IndexOf("/") + 1; 958 | int totalTimeLength = lastCurrentTimeText.Length - totalTimeStartIndex; 959 | totalFrames = lastCurrentTimeText.Substring(totalTimeStartIndex, totalTimeLength); 960 | 961 | // 从cmd中读取已经编码的帧数 962 | int framesIndex = o.IndexOf("frames:"); 963 | 964 | // 帧数小于7位数 965 | if (framesIndex != -1 && framesIndex <= 8) 966 | { 967 | string frames = ""; 968 | try 969 | { 970 | frames = o.Substring(0, framesIndex - 1); 971 | } 972 | catch (Exception e) 973 | { 974 | saveLog2File(); 975 | } 976 | // endIndex = -1 977 | this.rsForm.setTime(frames + "/" + totalFrames); 978 | 979 | //string[] splitTemp = frames.Split(new char[] { '/' }); 980 | encodedFrames = frames; 981 | //totalFrames = splitTemp[1]; 982 | 983 | checkFrame[checkIndex] = Convert.ToInt32(encodedFrames); 984 | 985 | this.reportCount++; 986 | 987 | try 988 | { 989 | double percent = (double)(checkFrame[checkIndex]) / (Double.Parse(totalFrames)) * 100.0; 990 | 991 | this.rsForm.setPercent(percent.ToString()); 992 | 993 | if (percent >= 99.9) 994 | { 995 | miniLog += o + Environment.NewLine; 996 | } 997 | } 998 | catch (Exception e) 999 | { 1000 | //saveLog2File(); 1001 | } 1002 | } 1003 | break; 1004 | 1005 | case AVS: 1006 | // o 的格式 = [xx.x%] 已完成帧数/总帧数, ... 1007 | 1008 | int endIndex = o.IndexOf("%]"); 1009 | int startIndex = o.IndexOf("["); 1010 | // 进度 xx.x 最多4位字符,间隔不应大于4 (index之间差值不得大于5) 1011 | if (startIndex != -1 && endIndex != -1 && endIndex - startIndex < 6 && endIndex - startIndex > 0) 1012 | { 1013 | string progress = o.Substring(startIndex + 1, endIndex - startIndex - 1); // 第二个参数是子串的长度 1014 | this.rsForm.setPercent(progress); 1015 | if (Convert.ToDouble(progress) >= 99.9) 1016 | { 1017 | miniLog += o + Environment.NewLine; 1018 | } 1019 | } 1020 | 1021 | // 从cmd中读取已经编码的帧数 1022 | 1023 | int framesIndexCaseAVS = o.IndexOf(" frames"); 1024 | 1025 | if (framesIndexCaseAVS != -1) 1026 | { 1027 | // frames 格式: xxx/xxxxx (a/b, a的位数小于等于b的位数) 1028 | string frames = o.Substring(endIndex + 3, framesIndexCaseAVS - endIndex - 3); 1029 | this.rsForm.setTime(frames); 1030 | 1031 | string[] splitTemp = frames.Split(new char[] { '/' }); 1032 | encodedFrames = splitTemp[0]; 1033 | totalFrames = splitTemp[1]; 1034 | 1035 | checkFrame[checkIndex] = Convert.ToInt32(encodedFrames); 1036 | 1037 | this.reportCount++; 1038 | } 1039 | 1040 | kbpsStartIndex = o.IndexOf("fps, ") + 5; 1041 | kbpsEndIndex = o.IndexOf("kb/s") + 4; 1042 | 1043 | if (kbpsStartIndex != -1 && kbpsEndIndex != -1 && kbpsEndIndex - kbpsStartIndex > 6 && kbpsEndIndex - kbpsStartIndex < 14) 1044 | { 1045 | string estKbps = o.Substring(kbpsStartIndex, kbpsEndIndex - kbpsStartIndex); 1046 | this.rsForm.setEstKbps(estKbps); 1047 | } 1048 | 1049 | break; 1050 | 1051 | default: 1052 | break; 1053 | } 1054 | 1055 | if (this.reportCount >= checkPattern) 1056 | { 1057 | // 定义一个内部(匿名)方法 1058 | // 分析并计算fps和ETA 1059 | InnerMethodDelagate processFpsAndETA = delegate() 1060 | { 1061 | // 取两位小数的方法 1062 | System.Globalization.NumberFormatInfo nfi = new System.Globalization.NumberFormatInfo(); 1063 | nfi.NumberDecimalDigits = 2; 1064 | this.rsForm.setFps(fps[checkIndex].ToString("N", nfi) + " fps"); 1065 | 1066 | // 计算优化后的ETA 1067 | double avgFps = NonZeroAverage(this.fps); 1068 | double eta = (double)(Convert.ToInt32(totalFrames) - checkFrame[checkIndex]) / avgFps / 60.0; 1069 | 1070 | double i = Math.Floor(eta); // 去除小数部分 1071 | double d = eta - i; 1072 | 1073 | double sec = d * 60.0; 1074 | 1075 | d = i / 60.0; 1076 | double h = Math.Floor(d); 1077 | double min = i - h * 60; 1078 | 1079 | string etaStr = ((int)h).ToString("00") + ":" + ((int)min).ToString("00") + ":" + ((int)sec).ToString("00"); 1080 | 1081 | this.rsForm.setEta(etaStr); 1082 | }; 1083 | 1084 | if (checkIndex >= checkPattern) 1085 | { 1086 | // 注意:下两句和另一部分是不一样的,不能复制 1087 | int timeIntetval = checkTime[checkIndex] - checkTime[checkIndex - checkPattern]; 1088 | int framesInteval = checkFrame[checkIndex] - checkFrame[checkIndex - checkPattern]; 1089 | fps[checkIndex] = (double)framesInteval / (double)timeIntetval * 1000; 1090 | 1091 | if (fps[checkIndex] > 0) 1092 | { 1093 | processFpsAndETA(); 1094 | } 1095 | } 1096 | else 1097 | { 1098 | // 注意:下两句和另一部分是不一样的,不能复制 1099 | int timeIntetval = checkTime[checkIndex] - checkTime[checkIndex + checkPattern]; 1100 | int framesInteval = checkFrame[checkIndex] - checkFrame[checkIndex + checkPattern]; 1101 | fps[checkIndex] = (double)framesInteval / (double)timeIntetval * 1000; 1102 | 1103 | if (fps[checkIndex] > 0) 1104 | { 1105 | processFpsAndETA(); 1106 | } 1107 | } 1108 | } 1109 | else 1110 | { 1111 | this.rsForm.setEta("正在计算..."); 1112 | this.rsForm.setFps("正在统计..."); 1113 | } 1114 | } 1115 | else 1116 | { 1117 | //miniLog += o + Environment.NewLine; 1118 | //this.rsForm.setPercent("0.0"); 1119 | //this.rsForm.setTime("索引中"); 1120 | } 1121 | } 1122 | } 1123 | } 1124 | } 1125 | 1126 | private string convertToTimerFormat(string s) 1127 | { 1128 | if (s.Length == 1) 1129 | { 1130 | return "0" + s; 1131 | } else 1132 | { 1133 | return s; 1134 | } 1135 | } 1136 | 1137 | private void AllThreadKill() 1138 | { 1139 | for (int i = 0; i < threadsNum; i++) 1140 | { 1141 | threads[i].Abort(); 1142 | } 1143 | } 1144 | 1145 | private void saveLog2File() 1146 | { 1147 | string dateAndTime = DateTime.Now.ToString("yyyyMMdd_HHmmss"); 1148 | string fp = System.Windows.Forms.Application.StartupPath + "\\" + "EVTLog_" 1149 | + dateAndTime + ".log"; 1150 | System.IO.File.WriteAllText(fp, this.log.ToString(), Encoding.UTF8); 1151 | } 1152 | 1153 | private void saveMiniLog2File() 1154 | { 1155 | string fp = System.Windows.Forms.Application.StartupPath + "\\" + "EVTminiLog" + ".log"; 1156 | System.IO.File.AppendAllText(fp, this.miniLog, Encoding.UTF8); 1157 | } 1158 | 1159 | // 成功完成一个任务时才会调用的debug方法 1160 | private void debugLog2File() 1161 | { 1162 | string dateAndTime = DateTime.Now.ToString("yyyyMMdd_HHmmss"); 1163 | string fp = System.Windows.Forms.Application.StartupPath + "\\" + "EVTLog_" 1164 | + dateAndTime + ".log"; 1165 | System.IO.File.WriteAllText(fp, this.log.ToString(), Encoding.UTF8); 1166 | } 1167 | 1168 | private int checkCmdRunning(int t, int _t) 1169 | { 1170 | // 判断_t次循环内有没有新的命令行信息输出 1171 | t = (++t == _t) ? t - _t : t; 1172 | if (t == 0 && this.outPutCmdCount == this.outPutCmdCheckCount) // && (this.encoding || this.muxing || this.audioProcessing) 1173 | { 1174 | saveLog2File(); 1175 | 1176 | this.rsForm.setPercent("-1"); 1177 | this.rsForm.setTime("发生错误"); 1178 | this.rsForm.setFps("日志保存在程序目录"); 1179 | 1180 | int sleepTime = 5; // 设置失败后继续下一个任务的时间 1181 | this.rsForm.setEta(sleepTime.ToString() + "秒后继续运行"); 1182 | 1183 | t = -1; 1184 | this.rsForm.setStatusBarLabelTextColorRED(); 1185 | this.finishedNum++; 1186 | this.rsForm.setStatusBarFilesCountLabel(this.finishedNum, this.num); 1187 | 1188 | Thread.Sleep(sleepTime * 1000); 1189 | 1190 | Process p = Process.GetProcessById(this.PIDs[0]); 1191 | p.Kill(); 1192 | this.rsForm.setStopBtnState(false); 1193 | this.rsForm.setPercent("-3"); 1194 | this.isfinished[0] = true; 1195 | this.reportCount = 0; 1196 | this.log.Clear(); 1197 | } 1198 | else if (t == 0) 1199 | { 1200 | this.outPutCmdCheckCount = this.outPutCmdCount; 1201 | } 1202 | return t; 1203 | } 1204 | 1205 | // 新版的检查子任务是否正常运行的方法(Not used) 1206 | private bool checkCmdRunning(string processName) 1207 | { 1208 | Process[] ps = Process.GetProcessesByName(changeFileExtName(processName)); // 必须输入不含.exe的进程名 1209 | 1210 | Process p = null; 1211 | 1212 | for (int i = 0; i < ps.Length; i++) 1213 | { 1214 | Process parent = ExpertVideoToolbox.ProcessControl.ParentProcessUtilities.GetParentProcess(ps[i].Id); 1215 | if (parent != null && parent.Id == this.getPID()) 1216 | { 1217 | p = ps[i]; 1218 | break; 1219 | } 1220 | } 1221 | 1222 | if (p == null) // p为null表示要么没进入上述循环,要么ps为空 1223 | { 1224 | return false; 1225 | } 1226 | return true; 1227 | } 1228 | 1229 | private bool ConfirmFailed() 1230 | { 1231 | Thread.Sleep(1000); 1232 | if (this.postProcessing == false) 1233 | { 1234 | return false; 1235 | } 1236 | else 1237 | { 1238 | return true; 1239 | } 1240 | } 1241 | 1242 | // 得到指定进程的子进程(默认为返回本程序创建的cmd进程的子进程) 1243 | private Process GetSubTaskProcess(string processName, int parentId = -1) 1244 | { 1245 | Process[] ps = Process.GetProcessesByName(changeFileExtName(processName)); // 必须输入不含.exe的进程名 1246 | 1247 | Process p = null; 1248 | 1249 | int targetParentId = parentId == -1 ? this.getPID() : parentId; 1250 | 1251 | for (int i = 0; i < ps.Length; i++) 1252 | { 1253 | Process parent = ExpertVideoToolbox.ProcessControl.ParentProcessUtilities.GetParentProcess(ps[i].Id); 1254 | if (parent != null && parent.Id == targetParentId) 1255 | { 1256 | p = ps[i]; 1257 | break; 1258 | } 1259 | } 1260 | return p; 1261 | } 1262 | 1263 | // 求剔除零之后数组的平均值 1264 | private double NonZeroAverage(double[] d) 1265 | { 1266 | int count = d.Length; 1267 | int nonZeroCount = 0; 1268 | double sum = 0.0; 1269 | for (int i = 0; i < count; i++) 1270 | { 1271 | if (d[i] != 0) 1272 | { 1273 | nonZeroCount++; 1274 | sum += d[i]; 1275 | } 1276 | } 1277 | return sum / (double)nonZeroCount; 1278 | } 1279 | 1280 | // 已知问题:如果输入为无扩展名的文件名而且其路径中含有.,就会替换最后一个点后所有字符 1281 | private string changeFileExtName(string originFp, string ext = "") 1282 | { 1283 | if (!originFp.Contains('.')) 1284 | { 1285 | if (!String.IsNullOrWhiteSpace(ext)) 1286 | { 1287 | return originFp + "." + ext; 1288 | } 1289 | else 1290 | { 1291 | return originFp; 1292 | } 1293 | } 1294 | 1295 | string[] s = originFp.Split(new char[] { '.' }); 1296 | int length = s.Length; 1297 | s[length - 1] = ext; 1298 | string finalFileName = ""; 1299 | for (int i = 0; i < length; i++) 1300 | { 1301 | finalFileName += s[i]; 1302 | if (i != length - 1) 1303 | { 1304 | finalFileName += "."; 1305 | } 1306 | } 1307 | if (string.IsNullOrWhiteSpace(ext)) // 当需要的扩展名为空时,去除字符串最后位置的一个点 1308 | { 1309 | finalFileName = finalFileName.Substring(0, finalFileName.Length - 1); 1310 | } 1311 | return finalFileName; 1312 | } 1313 | 1314 | private string getFileExtName(string originFp) 1315 | { 1316 | string[] s = originFp.Split(new char[] { '.' }); 1317 | int length = s.Length; 1318 | return s[length - 1]; 1319 | } 1320 | } 1321 | } 1322 | --------------------------------------------------------------------------------