Merge pull request #5697 from Bond-009/ffmpeg2
Simplify the way we choose our ffmpeg
This commit is contained in:
commit
b7e13f3a03
|
@ -1099,7 +1099,6 @@ namespace Emby.Server.Implementations
|
|||
ServerName = FriendlyName,
|
||||
LocalAddress = GetSmartApiUrl(source),
|
||||
SupportsLibraryMonitor = true,
|
||||
EncoderLocation = _mediaEncoder.EncoderLocation,
|
||||
SystemArchitecture = RuntimeInformation.OSArchitecture,
|
||||
PackageName = _startupOptions.PackageName
|
||||
};
|
||||
|
|
|
@ -10,7 +10,6 @@ using MediaBrowser.Model.Dlna;
|
|||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.System;
|
||||
|
||||
namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
|
@ -19,11 +18,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
/// </summary>
|
||||
public interface IMediaEncoder : ITranscoderSupport
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets location of the discovered FFmpeg tool.
|
||||
/// </summary>
|
||||
FFmpegLocation EncoderLocation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encoder path.
|
||||
/// </summary>
|
||||
|
|
|
@ -12,8 +12,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
{
|
||||
public class EncoderValidator
|
||||
{
|
||||
private const string DefaultEncoderPath = "ffmpeg";
|
||||
|
||||
private static readonly string[] _requiredDecoders = new[]
|
||||
{
|
||||
"h264",
|
||||
|
@ -106,7 +104,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
|
||||
private readonly string _encoderPath;
|
||||
|
||||
public EncoderValidator(ILogger logger, string encoderPath = DefaultEncoderPath)
|
||||
public EncoderValidator(ILogger logger, string encoderPath)
|
||||
{
|
||||
_logger = logger;
|
||||
_encoderPath = encoderPath;
|
||||
|
|
|
@ -23,7 +23,6 @@ using MediaBrowser.Model.Entities;
|
|||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.System;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
@ -69,7 +68,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
|
||||
private string _ffmpegPath = string.Empty;
|
||||
private string _ffprobePath;
|
||||
private int threads;
|
||||
private int _threads;
|
||||
|
||||
public MediaEncoder(
|
||||
ILogger<MediaEncoder> logger,
|
||||
|
@ -89,9 +88,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
/// <inheritdoc />
|
||||
public string EncoderPath => _ffmpegPath;
|
||||
|
||||
/// <inheritdoc />
|
||||
public FFmpegLocation EncoderLocation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Run at startup or if the user removes a Custom path from transcode page.
|
||||
/// Sets global variables FFmpegPath.
|
||||
|
@ -100,19 +96,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
public void SetFFmpegPath()
|
||||
{
|
||||
// 1) Custom path stored in config/encoding xml file under tag <EncoderAppPath> takes precedence
|
||||
if (!ValidatePath(_configurationManager.GetEncodingOptions().EncoderAppPath, FFmpegLocation.Custom))
|
||||
var ffmpegPath = _configurationManager.GetEncodingOptions().EncoderAppPath;
|
||||
if (string.IsNullOrEmpty(ffmpegPath))
|
||||
{
|
||||
// 2) Check if the --ffmpeg CLI switch has been given
|
||||
if (!ValidatePath(_startupOptionFFmpegPath, FFmpegLocation.SetByArgument))
|
||||
ffmpegPath = _startupOptionFFmpegPath;
|
||||
if (string.IsNullOrEmpty(ffmpegPath))
|
||||
{
|
||||
// 3) Search system $PATH environment variable for valid FFmpeg
|
||||
if (!ValidatePath(ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System))
|
||||
// 3) Check "ffmpeg"
|
||||
ffmpegPath = "ffmpeg";
|
||||
}
|
||||
}
|
||||
|
||||
if (!ValidatePath(ffmpegPath))
|
||||
{
|
||||
EncoderLocation = FFmpegLocation.NotFound;
|
||||
_ffmpegPath = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write the FFmpeg path to the config/encoding.xml file as <EncoderAppPathDisplay> so it appears in UI
|
||||
var config = _configurationManager.GetEncodingOptions();
|
||||
|
@ -131,10 +130,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
SetAvailableDecoders(validator.GetDecoders());
|
||||
SetAvailableEncoders(validator.GetEncoders());
|
||||
SetAvailableHwaccels(validator.GetHwaccels());
|
||||
threads = EncodingHelper.GetNumberOfThreads(null, _configurationManager.GetEncodingOptions(), null);
|
||||
_threads = EncodingHelper.GetNumberOfThreads(null, _configurationManager.GetEncodingOptions(), null);
|
||||
}
|
||||
|
||||
_logger.LogInformation("FFmpeg: {EncoderLocation}: {FfmpegPath}", EncoderLocation, _ffmpegPath ?? string.Empty);
|
||||
_logger.LogInformation("FFmpeg: {FfmpegPath}", _ffmpegPath ?? string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -153,15 +152,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
{
|
||||
throw new ArgumentException("Unexpected pathType value");
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(path))
|
||||
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
// User had cleared the custom path in UI
|
||||
newPath = string.Empty;
|
||||
}
|
||||
else if (File.Exists(path))
|
||||
{
|
||||
newPath = path;
|
||||
}
|
||||
else if (Directory.Exists(path))
|
||||
{
|
||||
// Given path is directory, so resolve down to filename
|
||||
|
@ -169,7 +165,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new ResourceNotFoundException();
|
||||
newPath = path;
|
||||
}
|
||||
|
||||
// Write the new ffmpeg path to the xml as <EncoderAppPath>
|
||||
|
@ -184,38 +180,27 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
|
||||
/// <summary>
|
||||
/// Validates the supplied FQPN to ensure it is a ffmpeg utility.
|
||||
/// If checks pass, global variable FFmpegPath and EncoderLocation are updated.
|
||||
/// If checks pass, global variable FFmpegPath is updated.
|
||||
/// </summary>
|
||||
/// <param name="path">FQPN to test.</param>
|
||||
/// <param name="location">Location (External, Custom, System) of tool.</param>
|
||||
/// <returns><c>true</c> if the version validation succeeded; otherwise, <c>false</c>.</returns>
|
||||
private bool ValidatePath(string path, FFmpegLocation location)
|
||||
private bool ValidatePath(string path)
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
rc = new EncoderValidator(_logger, path).ValidateVersion();
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rc = new EncoderValidator(_logger, path).ValidateVersion();
|
||||
if (!rc)
|
||||
{
|
||||
_logger.LogWarning("FFmpeg: {Location}: Failed version check: {Path}", location, path);
|
||||
_logger.LogWarning("FFmpeg: Failed version check: {Path}", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
_ffmpegPath = path;
|
||||
EncoderLocation = location;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("FFmpeg: {Location}: File not found: {Path}", location, path);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
private string GetEncoderPathFromDirectory(string path, string filename, bool recursive = false)
|
||||
{
|
||||
|
@ -235,34 +220,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search the system $PATH environment variable looking for given filename.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The filename.</param>
|
||||
/// <returns>The full path to the file.</returns>
|
||||
private string ExistsOnSystemPath(string fileName)
|
||||
{
|
||||
var inJellyfinPath = GetEncoderPathFromDirectory(AppContext.BaseDirectory, fileName, recursive: true);
|
||||
if (!string.IsNullOrEmpty(inJellyfinPath))
|
||||
{
|
||||
return inJellyfinPath;
|
||||
}
|
||||
|
||||
var values = Environment.GetEnvironmentVariable("PATH");
|
||||
|
||||
foreach (var path in values.Split(Path.PathSeparator))
|
||||
{
|
||||
var candidatePath = GetEncoderPathFromDirectory(path, fileName);
|
||||
|
||||
if (!string.IsNullOrEmpty(candidatePath))
|
||||
{
|
||||
return candidatePath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetAvailableEncoders(IEnumerable<string> list)
|
||||
{
|
||||
_encoders = list.ToList();
|
||||
|
@ -394,7 +351,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
var args = extractChapters
|
||||
? "{0} -i {1} -threads {2} -v warning -print_format json -show_streams -show_chapters -show_format"
|
||||
: "{0} -i {1} -threads {2} -v warning -print_format json -show_streams -show_format";
|
||||
args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath, threads).Trim();
|
||||
args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath, _threads).Trim();
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
|
@ -615,7 +572,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
}
|
||||
}
|
||||
|
||||
var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads);
|
||||
var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, _threads);
|
||||
|
||||
if (offset.HasValue)
|
||||
{
|
||||
|
@ -728,7 +685,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
Directory.CreateDirectory(targetDirectory);
|
||||
var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg");
|
||||
|
||||
var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, threads);
|
||||
var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, _threads);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(container))
|
||||
{
|
||||
|
|
|
@ -133,6 +133,7 @@ namespace MediaBrowser.Model.System
|
|||
[Obsolete("This should be handled by the package manager")]
|
||||
public bool HasUpdateAvailable { get; set; }
|
||||
|
||||
[Obsolete("This isn't set correctly anymore")]
|
||||
public FFmpegLocation EncoderLocation { get; set; }
|
||||
|
||||
public Architecture SystemArchitecture { get; set; }
|
||||
|
|
|
@ -9,12 +9,13 @@ namespace Jellyfin.MediaEncoding.Tests
|
|||
{
|
||||
public class EncoderValidatorTests
|
||||
{
|
||||
private readonly EncoderValidator _encoderValidator = new EncoderValidator(new NullLogger<EncoderValidatorTests>(), "ffmpeg");
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(GetFFmpegVersionTestData))]
|
||||
public void GetFFmpegVersionTest(string versionOutput, Version? version)
|
||||
{
|
||||
var val = new EncoderValidator(new NullLogger<EncoderValidatorTests>());
|
||||
Assert.Equal(version, val.GetFFmpegVersion(versionOutput));
|
||||
Assert.Equal(version, _encoderValidator.GetFFmpegVersion(versionOutput));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
@ -28,8 +29,7 @@ namespace Jellyfin.MediaEncoding.Tests
|
|||
[InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput, false)]
|
||||
public void ValidateVersionInternalTest(string versionOutput, bool valid)
|
||||
{
|
||||
var val = new EncoderValidator(new NullLogger<EncoderValidatorTests>());
|
||||
Assert.Equal(valid, val.ValidateVersionInternal(versionOutput));
|
||||
Assert.Equal(valid, _encoderValidator.ValidateVersionInternal(versionOutput));
|
||||
}
|
||||
|
||||
private class GetFFmpegVersionTestData : IEnumerable<object?[]>
|
||||
|
|
Loading…
Reference in New Issue
Block a user