Merge branch 'master' into ffprobe-frames

This commit is contained in:
Malte Rosenbjerg 2021-10-21 20:47:25 +02:00 committed by GitHub
commit 40235db7ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 6 deletions

View file

@ -341,7 +341,22 @@ public void Builder_BuildString_SubtitleHardBurnFilter()
.WithParameter("PrimaryColour", "&HAA00FF00"))))) .WithParameter("PrimaryColour", "&HAA00FF00")))))
.Arguments; .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); str);
} }

View file

@ -16,7 +16,7 @@ internal static class KeyValuePairExtensions
public static string FormatArgumentPair(this KeyValuePair<string, string> pair, bool enclose) public static string FormatArgumentPair(this KeyValuePair<string, string> pair, bool enclose)
{ {
var key = pair.Key; var key = pair.Key;
var value = enclose ? pair.Value.EncloseIfContainsSpace() : pair.Value; var value = enclose ? StringExtensions.EncloseIfContainsSpace(pair.Value) : pair.Value;
return $"{key}={value}"; return $"{key}={value}";
} }

View file

@ -1,15 +1,70 @@
namespace FFMpegCore.Extend using System.Collections.Generic;
using System.Text;
namespace FFMpegCore.Extend
{ {
internal static class StringExtensions internal static class StringExtensions
{ {
private static Dictionary<char, string> CharactersSubstitution { get; } = new Dictionary<char, string>
{
{ '\\', @"\\" },
{ ':', @"\:" },
{ '[', @"\[" },
{ ']', @"\]" },
{ '\'', @"'\\\''" }
};
/// <summary> /// <summary>
/// Enclose string between quotes if contains an space character /// Enclose string between quotes if contains an space character
/// </summary> /// </summary>
/// <param name="input">The input</param> /// <param name="input">The input</param>
/// <returns>The enclosed string</returns> /// <returns>The enclosed string</returns>
public static string EncloseIfContainsSpace(this string input) public static string EncloseIfContainsSpace(string input)
{ {
return input.Contains(" ") ? $"'{input}'" : input; return input.Contains(" ") ? $"'{input}'" : input;
} }
/// <summary>
/// Enclose an string in quotes
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string EncloseInQuotes(string input)
{
return $"'{input}'";
}
/// <summary>
/// Scape several characters in subtitle path used by FFmpeg
/// </summary>
/// <remarks>
/// This is needed because internally FFmpeg use Libav Filters
/// and the info send to it must be in an specific format
/// </remarks>
/// <param name="source"></param>
/// <returns>Scaped path</returns>
public static string ToFFmpegLibavfilterPath(string source)
{
return source.Replace(CharactersSubstitution);
}
public static string Replace(this string str, Dictionary<char, string> 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();
}
} }
} }

View file

@ -103,7 +103,9 @@ public SubtitleHardBurnOptions WithParameter(string key, string value)
return this; 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 public class StyleOptions

View file

@ -116,7 +116,9 @@ private static (FFMpegArguments, Action<FFMpegArgumentOptions> outputOptions) Bu
{ {
captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3); captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
size = PrepareSnapshotSize(source, size); size = PrepareSnapshotSize(source, size);
streamIndex = streamIndex == null ? 0 : source.VideoStreams.FirstOrDefault(videoStream => videoStream.Index == streamIndex).Index; streamIndex ??= source.PrimaryVideoStream?.Index
?? source.VideoStreams.FirstOrDefault()?.Index
?? 0;
return (FFMpegArguments return (FFMpegArguments
.FromFileInput(input, false, options => options .FromFileInput(input, false, options => options