diff --git a/FFMpegCore.Test/ArgumentBuilderTest.cs b/FFMpegCore.Test/ArgumentBuilderTest.cs index a06a951..54620a5 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/KeyValuePairExtensions.cs b/FFMpegCore/Extend/KeyValuePairExtensions.cs index 28cc087..c2c6813 100644 --- a/FFMpegCore/Extend/KeyValuePairExtensions.cs +++ b/FFMpegCore/Extend/KeyValuePairExtensions.cs @@ -16,7 +16,7 @@ internal static class KeyValuePairExtensions public static string FormatArgumentPair(this KeyValuePair pair, bool enclose) { var key = pair.Key; - var value = enclose ? pair.Value.EncloseIfContainsSpace() : pair.Value; + var value = enclose ? StringExtensions.EncloseIfContainsSpace(pair.Value) : pair.Value; return $"{key}={value}"; } diff --git a/FFMpegCore/Extend/StringExtensions.cs b/FFMpegCore/Extend/StringExtensions.cs index ddcf54b..29c8d42 100644 --- a/FFMpegCore/Extend/StringExtensions.cs +++ b/FFMpegCore/Extend/StringExtensions.cs @@ -1,15 +1,70 @@ -namespace FFMpegCore.Extend +using System.Collections.Generic; +using System.Text; + +namespace FFMpegCore.Extend { internal static class StringExtensions { + private static Dictionary CharactersSubstitution { get; } = new Dictionary + { + { '\\', @"\\" }, + { ':', @"\:" }, + { '[', @"\[" }, + { ']', @"\]" }, + { '\'', @"'\\\''" } + }; + /// /// Enclose string between quotes if contains an space character /// /// The input /// The enclosed string - public static string EncloseIfContainsSpace(this string input) + public static string EncloseIfContainsSpace(string input) { return input.Contains(" ") ? $"'{input}'" : input; } + + /// + /// Enclose an string in quotes + /// + /// + /// + public static string EncloseInQuotes(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(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..2acd7ca 100644 --- a/FFMpegCore/FFMpeg/Arguments/SubtitleHardBurnArgument.cs +++ b/FFMpegCore/FFMpeg/Arguments/SubtitleHardBurnArgument.cs @@ -103,7 +103,9 @@ 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[] { StringExtensions.EncloseInQuotes(StringExtensions.ToFFmpegLibavfilterPath(_subtitle)) } + .Concat(Parameters.Select(parameter => parameter.FormatArgumentPair(enclose: true)))); } public class StyleOptions