diff --git a/FFMpegCore.Test/ArgumentBuilderTest.cs b/FFMpegCore.Test/ArgumentBuilderTest.cs index 082d9bf..5f2ce5c 100644 --- a/FFMpegCore.Test/ArgumentBuilderTest.cs +++ b/FFMpegCore.Test/ArgumentBuilderTest.cs @@ -341,7 +341,22 @@ public void Builder_BuildString_SubtitleHardBurnFilter() .WithParameter("PrimaryColour", "&HAA00FF00"))))) .Arguments; - Assert.AreEqual("-i \"input.mp4\" -vf \"subtitles=sample.srt:charenc=UTF-8:original_size=1366x768:stream_index=0:force_style='FontName=DejaVu Serif\\,PrimaryColour=&HAA00FF00'\" \"output.mp4\"", + Assert.AreEqual("-i \"input.mp4\" -vf \"subtitles='sample.srt':charenc=UTF-8:original_size=1366x768:stream_index=0:force_style='FontName=DejaVu Serif\\,PrimaryColour=&HAA00FF00'\" \"output.mp4\"", + str); + } + + [TestMethod] + public void Builder_BuildString_SubtitleHardBurnFilterFixedPaths() + { + var str = FFMpegArguments + .FromFileInput("input.mp4") + .OutputToFile("output.mp4", false, opt => opt + .WithVideoFilters(filterOptions => filterOptions + .HardBurnSubtitle(SubtitleHardBurnOptions + .Create(subtitlePath: @"sample( \ : [ ] , ).srt")))) + .Arguments; + + Assert.AreEqual(@"-i ""input.mp4"" -vf ""subtitles='sample( \\ \: \[ \] \, ).srt'"" ""output.mp4""", str); } diff --git a/FFMpegCore/Extend/StringExtensions.cs b/FFMpegCore/Extend/StringExtensions.cs index ddcf54b..7afcc34 100644 --- a/FFMpegCore/Extend/StringExtensions.cs +++ b/FFMpegCore/Extend/StringExtensions.cs @@ -1,7 +1,19 @@ -namespace FFMpegCore.Extend +using System.Collections.Generic; +using System.Text; + +namespace FFMpegCore.Extend { internal static class StringExtensions { + private static Dictionary CharactersSubstitution { get; } = new Dictionary + { + {'\\', @"\\"}, + {':', @"\:"}, + {'[', @"\["}, + {']', @"\]"}, + // {'\'', @"\'"} TODO: Quotes need to be escaped but i failed miserably + }; + /// /// Enclose string between quotes if contains an space character /// @@ -11,5 +23,48 @@ public static string EncloseIfContainsSpace(this string input) { return input.Contains(" ") ? $"'{input}'" : input; } + + /// + /// Enclose an string in quotes + /// + /// + /// + public static string EncloseInQuotes(this string input) + { + return $"'{input}'"; + } + + /// + /// Scape several characters in subtitle path used by FFmpeg + /// + /// + /// This is needed because internally FFmpeg use Libav Filters + /// and the info send to it must be in an specific format + /// + /// + /// Scaped path + public static string ToFFmpegLibavfilterPath(this string source) + { + return source.Replace(CharactersSubstitution); + } + + public static string Replace(this string str, Dictionary replaceList) + { + var parsedString = new StringBuilder(); + + foreach (var l in str) + { + if (replaceList.ContainsKey(l)) + { + parsedString.Append(replaceList[l]); + } + else + { + parsedString.Append(l); + } + } + + return parsedString.ToString(); + } } } \ No newline at end of file diff --git a/FFMpegCore/FFMpeg/Arguments/SubtitleHardBurnArgument.cs b/FFMpegCore/FFMpeg/Arguments/SubtitleHardBurnArgument.cs index a48f845..d7ec3aa 100644 --- a/FFMpegCore/FFMpeg/Arguments/SubtitleHardBurnArgument.cs +++ b/FFMpegCore/FFMpeg/Arguments/SubtitleHardBurnArgument.cs @@ -103,7 +103,7 @@ public SubtitleHardBurnOptions WithParameter(string key, string value) return this; } - internal string TextInternal => string.Join(":", new[] { _subtitle.EncloseIfContainsSpace() }.Concat(Parameters.Select(parameter => parameter.FormatArgumentPair(enclose: true)))); + internal string TextInternal => string.Join(":", new[] { _subtitle.ToFFmpegLibavfilterPath().EncloseInQuotes() }.Concat(Parameters.Select(parameter => parameter.FormatArgumentPair(enclose: true)))); } public class StyleOptions