From 4678d6c9b5b6c63accc5068b7b54961ddbd9f5fd Mon Sep 17 00:00:00 2001 From: Jaex Date: Fri, 9 May 2014 04:16:43 +0300 Subject: [PATCH] ffmpeg cli recording works now --- HelpersLib/CLI/ExternalCLIManager.cs | 10 +-- HelpersLib/Helpers/RegistryHelpers.cs | 66 +++++++++++-------- ScreenCaptureLib/ScreenCaptureLib.csproj | 1 - ScreenCaptureLib/Screencast/CLIEncoder.cs | 38 ----------- .../Screencast/FFmpegCLIHelper.cs | 46 +++++++++++-- ScreenCaptureLib/Screencast/ScreenRecorder.cs | 2 +- 6 files changed, 84 insertions(+), 79 deletions(-) delete mode 100644 ScreenCaptureLib/Screencast/CLIEncoder.cs diff --git a/HelpersLib/CLI/ExternalCLIManager.cs b/HelpersLib/CLI/ExternalCLIManager.cs index e2299ae50..4f7fb76db 100644 --- a/HelpersLib/CLI/ExternalCLIManager.cs +++ b/HelpersLib/CLI/ExternalCLIManager.cs @@ -43,21 +43,23 @@ public abstract class ExternalCLIManager : IDisposable private Process process = new Process(); - public virtual int Open(string cliPath, string args = null) + public virtual int Open(string path, string args = null) { - if (File.Exists(cliPath)) + DebugHelper.WriteLine("CLI path: \"{0}\" args: \"{1}\"", path, args); + + if (File.Exists(path)) { Output = new StringBuilder(); Errors = new StringBuilder(); - ProcessStartInfo psi = new ProcessStartInfo(cliPath); + ProcessStartInfo psi = new ProcessStartInfo(path); psi.UseShellExecute = false; psi.CreateNoWindow = true; psi.RedirectStandardInput = true; psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; psi.Arguments = args; - psi.WorkingDirectory = Path.GetDirectoryName(cliPath); + psi.WorkingDirectory = Path.GetDirectoryName(path); process.EnableRaisingEvents = true; process.OutputDataReceived += cli_OutputDataReceived; diff --git a/HelpersLib/Helpers/RegistryHelpers.cs b/HelpersLib/Helpers/RegistryHelpers.cs index 17605e09a..5fb00d430 100644 --- a/HelpersLib/Helpers/RegistryHelpers.cs +++ b/HelpersLib/Helpers/RegistryHelpers.cs @@ -125,23 +125,23 @@ public static void SetShellContextMenu(bool register) public static void RegisterShellContextMenu() { - CreateRegistryKey(ShellExtMenuFiles, ShellExtDesc); - AddRegistryValue(ShellExtMenuFiles, "Icon", ShellExtIcon); - CreateRegistryKey(ShellExtMenuFilesCmd, ShellExtPath); + CreateRegistry(ShellExtMenuFiles, ShellExtDesc); + CreateRegistry(ShellExtMenuFiles, "Icon", ShellExtIcon); + CreateRegistry(ShellExtMenuFilesCmd, ShellExtPath); - CreateRegistryKey(ShellExtMenuDirectory, ShellExtDesc); - AddRegistryValue(ShellExtMenuDirectory, "Icon", ShellExtIcon); - CreateRegistryKey(ShellExtMenuDirectoryCmd, ShellExtPath); + CreateRegistry(ShellExtMenuDirectory, ShellExtDesc); + CreateRegistry(ShellExtMenuDirectory, "Icon", ShellExtIcon); + CreateRegistry(ShellExtMenuDirectoryCmd, ShellExtPath); } public static void UnregisterShellContextMenu() { - RemoveRegistryKey(ShellExtMenuFilesCmd); - RemoveRegistryKey(ShellExtMenuFiles); - RemoveRegistryKey(ShellExtMenuDirectoryCmd); - RemoveRegistryKey(ShellExtMenuDirectory); - RemoveRegistryKey(ShellExtMenuFoldersCmd); - RemoveRegistryKey(ShellExtMenuFolders); + RemoveRegistry(ShellExtMenuFilesCmd); + RemoveRegistry(ShellExtMenuFiles); + RemoveRegistry(ShellExtMenuDirectoryCmd); + RemoveRegistry(ShellExtMenuDirectory); + RemoveRegistry(ShellExtMenuFoldersCmd); + RemoveRegistry(ShellExtMenuFolders); } public static ExternalProgram FindProgram(string name, string filename) @@ -192,18 +192,39 @@ public static ExternalProgram FindProgram(string name, string filename) return null; } - private static void CreateRegistryKey(string path, string value, string name = null) + public static void CreateRegistry(string path, string value) + { + CreateRegistry(path, null, value); + } + + public static void CreateRegistry(string path, string name, string value) { using (RegistryKey rk = Registry.CurrentUser.CreateSubKey(path)) { if (rk != null) { - rk.SetValue(name, value); + rk.SetValue(name, value, RegistryValueKind.String); } } } - private static void RemoveRegistryKey(string path) + public static void CreateRegistry(string path, int value) + { + CreateRegistry(path, null, value); + } + + public static void CreateRegistry(string path, string name, int value) + { + using (RegistryKey rk = Registry.CurrentUser.CreateSubKey(path)) + { + if (rk != null) + { + rk.SetValue(name, value, RegistryValueKind.DWord); + } + } + } + + public static void RemoveRegistry(string path) { using (RegistryKey rk = Registry.CurrentUser.OpenSubKey(path)) { @@ -214,18 +235,7 @@ private static void RemoveRegistryKey(string path) } } - private static void AddRegistryValue(string path, string name, string value) - { - using (RegistryKey rk = Registry.CurrentUser.OpenSubKey(path, true)) - { - if (rk != null) - { - rk.SetValue(name, value); - } - } - } - - private static bool CheckRegistry(string path, string name = null, string value = null) + public static bool CheckRegistry(string path, string name = null, string value = null) { string registryValue = GetRegistryValue(path, name); @@ -237,7 +247,7 @@ private static bool CheckRegistry(string path, string name = null, string value return false; } - private static string GetRegistryValue(string path, string name = null) + public static string GetRegistryValue(string path, string name = null) { using (RegistryKey rk = Registry.CurrentUser.OpenSubKey(path)) { diff --git a/ScreenCaptureLib/ScreenCaptureLib.csproj b/ScreenCaptureLib/ScreenCaptureLib.csproj index d8d6222da..ffdbe5d57 100644 --- a/ScreenCaptureLib/ScreenCaptureLib.csproj +++ b/ScreenCaptureLib/ScreenCaptureLib.csproj @@ -63,7 +63,6 @@ - diff --git a/ScreenCaptureLib/Screencast/CLIEncoder.cs b/ScreenCaptureLib/Screencast/CLIEncoder.cs deleted file mode 100644 index 6acfc7944..000000000 --- a/ScreenCaptureLib/Screencast/CLIEncoder.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region License Information (GPL v3) - -/* - ShareX - A program that allows you to take screenshots and share any file type - Copyright (C) 2008-2014 ShareX Developers - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - Optionally you can also view the license at . -*/ - -#endregion License Information (GPL v3) - -using HelpersLib; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ScreenCaptureLib -{ - public abstract class CLIEncoder : ExternalCLIManager - { - public abstract bool Record(); - } -} \ No newline at end of file diff --git a/ScreenCaptureLib/Screencast/FFmpegCLIHelper.cs b/ScreenCaptureLib/Screencast/FFmpegCLIHelper.cs index 636b77dfa..6a7c0815c 100644 --- a/ScreenCaptureLib/Screencast/FFmpegCLIHelper.cs +++ b/ScreenCaptureLib/Screencast/FFmpegCLIHelper.cs @@ -27,6 +27,7 @@ You should have received a copy of the GNU General Public License using System; using System.Collections.Generic; using System.Diagnostics; +using System.Drawing; using System.IO; using System.Linq; using System.Text; @@ -34,7 +35,7 @@ You should have received a copy of the GNU General Public License namespace ScreenCaptureLib { - public class FFmpegCLIHelper : CLIEncoder + public class FFmpegCLIHelper : ExternalCLIManager { public ScreencastOptions Options { get; private set; } @@ -50,23 +51,54 @@ public FFmpegCLIHelper(ScreencastOptions options) Helpers.CreateDirectoryIfNotExist(Options.OutputPath); // It is actually output data - ErrorDataReceived += FFmpegCLIHelper_ErrorDataReceived; + ErrorDataReceived += FFmpegCLIHelper_OutputDataReceived; } - private void FFmpegCLIHelper_ErrorDataReceived(object sender, DataReceivedEventArgs e) + private void FFmpegCLIHelper_OutputDataReceived(object sender, DataReceivedEventArgs e) { //DebugHelper.WriteLine(e.Data); } - public override bool Record() + public bool Record(Rectangle captureRectangle) { + // https://github.com/rdp/screen-capture-recorder-to-video-windows-free configuration section + string dshowRegistryPath = "Software\\screen-capture-recorder"; + RegistryHelpers.CreateRegistry(dshowRegistryPath, "start_x", captureRectangle.X); + RegistryHelpers.CreateRegistry(dshowRegistryPath, "start_y", captureRectangle.Y); + RegistryHelpers.CreateRegistry(dshowRegistryPath, "capture_width", captureRectangle.Width); + RegistryHelpers.CreateRegistry(dshowRegistryPath, "capture_height", captureRectangle.Height); + StringBuilder args = new StringBuilder(); - args.Append("-f dshow -i video=\"screen-capture-recorder\""); + if (Options.FPS > 0) { - args.Append(string.Format(" -r {0}", Options.FPS)); + // input FPS + args.AppendFormat("-r {0} ", Options.FPS); } - args.Append(string.Format(" -c:v libx264 -crf 23 -preset medium -pix_fmt yuv420p -y \"{0}\"", Options.OutputPath)); + + args.Append("-f dshow -i "); + + // dshow audio/video device: https://github.com/rdp/screen-capture-recorder-to-video-windows-free + //args.AppendFormat("audio=\"{0}\":", "virtual-audio-capturer"); + args.AppendFormat("video=\"{0}\" ", "screen-capture-recorder"); + + if (Options.FPS > 0) + { + // output FPS + args.AppendFormat("-r {0} ", Options.FPS); + } + + // x264 encoder + args.Append("-c:v libx264 "); + + // TODO: Add crf, preset etc. to options + // https://trac.ffmpeg.org/wiki/x264EncodingGuide + args.AppendFormat("-crf {0} ", 23); + args.AppendFormat("-preset {0} ", "medium"); + + // -pix_fmt yuv420p required otherwise can't stream in Chrome + // -y for overwrite file + args.AppendFormat("-pix_fmt yuv420p -y \"{0}\"", Options.OutputPath); int result = Open(Options.FFmpeg.CLIPath, args.ToString()); return result == 0; diff --git a/ScreenCaptureLib/Screencast/ScreenRecorder.cs b/ScreenCaptureLib/Screencast/ScreenRecorder.cs index f2b0e7331..76f30aee7 100644 --- a/ScreenCaptureLib/Screencast/ScreenRecorder.cs +++ b/ScreenCaptureLib/Screencast/ScreenRecorder.cs @@ -159,7 +159,7 @@ public void StartRecording() private void RecordUsingFFmpegCLI() { ffMpegCli = new FFmpegCLIHelper(Options); - ffMpegCli.Record(); + ffMpegCli.Record(CaptureRectangle); } private void RecordUsingCache()