Browse Source

ffmpeg tweaks (#121)

* save reports from ffmpeg concat process

* let ffmpeg determine thread count by default

* disable stdin for ffmpeg processes
pull/122/head
Jason Dove 5 years ago committed by GitHub
parent
commit
90f775aab4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ErsatzTV.Application/FFmpegProfiles/Commands/CreateFFmpegProfileHandler.cs
  2. 2
      ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegProfileHandler.cs
  3. 28
      ErsatzTV.Application/Streaming/Queries/GetConcatProcessByChannelNumberHandler.cs
  4. 2
      ErsatzTV.CommandLine/Commands/FFmpegProfileCommand.cs
  5. 2
      ErsatzTV.Core/Domain/FFmpegProfile.cs
  6. 10
      ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs
  7. 4
      ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs
  8. 1829
      ErsatzTV.Infrastructure/Migrations/20210331010449_Update_FFmpegProfile_ThreadCount.Designer.cs
  9. 14
      ErsatzTV.Infrastructure/Migrations/20210331010449_Update_FFmpegProfile_ThreadCount.cs
  10. 3
      ErsatzTV/Controllers/IptvController.cs
  11. 2
      ErsatzTV/Validators/FFmpegProfileEditViewModelValidator.cs

2
ErsatzTV.Application/FFmpegProfiles/Commands/CreateFFmpegProfileHandler.cs

@ -63,7 +63,7 @@ namespace ErsatzTV.Application.FFmpegProfiles.Commands @@ -63,7 +63,7 @@ namespace ErsatzTV.Application.FFmpegProfiles.Commands
.Bind(_ => createFFmpegProfile.NotLongerThan(50)(x => x.Name));
private Validation<BaseError, int> ValidateThreadCount(CreateFFmpegProfile createFFmpegProfile) =>
createFFmpegProfile.AtLeast(1)(p => p.ThreadCount);
createFFmpegProfile.AtLeast(0)(p => p.ThreadCount);
private async Task<Validation<BaseError, int>> ResolutionMustExist(CreateFFmpegProfile createFFmpegProfile) =>
(await _resolutionRepository.Get(createFFmpegProfile.ResolutionId))

2
ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegProfileHandler.cs

@ -69,7 +69,7 @@ namespace ErsatzTV.Application.FFmpegProfiles.Commands @@ -69,7 +69,7 @@ namespace ErsatzTV.Application.FFmpegProfiles.Commands
.Bind(_ => updateFFmpegProfile.NotLongerThan(50)(x => x.Name));
private Validation<BaseError, int> ValidateThreadCount(UpdateFFmpegProfile updateFFmpegProfile) =>
updateFFmpegProfile.AtLeast(1)(p => p.ThreadCount);
updateFFmpegProfile.AtLeast(0)(p => p.ThreadCount);
private async Task<Validation<BaseError, int>> ResolutionMustExist(UpdateFFmpegProfile updateFFmpegProfile) =>
(await _resolutionRepository.Get(updateFFmpegProfile.ResolutionId))

28
ErsatzTV.Application/Streaming/Queries/GetConcatProcessByChannelNumberHandler.cs

@ -5,30 +5,38 @@ using ErsatzTV.Core.Domain; @@ -5,30 +5,38 @@ using ErsatzTV.Core.Domain;
using ErsatzTV.Core.FFmpeg;
using ErsatzTV.Core.Interfaces.Repositories;
using LanguageExt;
using static LanguageExt.Prelude;
namespace ErsatzTV.Application.Streaming.Queries
{
public class GetConcatProcessByChannelNumberHandler : FFmpegProcessHandler<GetConcatProcessByChannelNumber>
{
private readonly IConfigElementRepository _configElementRepository;
private readonly FFmpegProcessService _ffmpegProcessService;
public GetConcatProcessByChannelNumberHandler(
IChannelRepository channelRepository,
IConfigElementRepository configElementRepository,
FFmpegProcessService ffmpegProcessService)
: base(channelRepository, configElementRepository) =>
: base(channelRepository, configElementRepository)
{
_configElementRepository = configElementRepository;
_ffmpegProcessService = ffmpegProcessService;
}
protected override Task<Either<BaseError, Process>> GetProcess(
protected override async Task<Either<BaseError, Process>> GetProcess(
GetConcatProcessByChannelNumber request,
Channel channel,
string ffmpegPath) =>
Right<BaseError, Process>(
_ffmpegProcessService.ConcatChannel(
ffmpegPath,
channel,
request.Scheme,
request.Host)).AsTask();
string ffmpegPath)
{
bool saveReports = await _configElementRepository.GetValue<bool>(ConfigElementKey.FFmpegSaveReports)
.Map(result => result.IfNone(false));
return _ffmpegProcessService.ConcatChannel(
ffmpegPath,
saveReports,
channel,
request.Scheme,
request.Host);
}
}
}

2
ErsatzTV.CommandLine/Commands/FFmpegProfileCommand.cs

@ -28,7 +28,7 @@ namespace ErsatzTV.CommandLine.Commands @@ -28,7 +28,7 @@ namespace ErsatzTV.CommandLine.Commands
public string Name { get; set; }
[CommandOption("thread-count", Description = "The number of threads")]
public int ThreadCount { get; set; } = 4;
public int ThreadCount { get; set; } = 0;
[CommandOption("transcode", Description = "Whether to transcode all media")]
public bool Transcode { get; set; } = true;

2
ErsatzTV.Core/Domain/FFmpegProfile.cs

@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
new()
{
Name = name,
ThreadCount = 4,
ThreadCount = 0,
Transcode = true,
ResolutionId = resolution.Id,
Resolution = resolution,

10
ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs

@ -42,6 +42,7 @@ namespace ErsatzTV.Core.FFmpeg @@ -42,6 +42,7 @@ namespace ErsatzTV.Core.FFmpeg
private readonly string _ffmpegPath;
private readonly bool _saveReports;
private FFmpegComplexFilterBuilder _complexFilterBuilder = new();
private bool _isConcat;
public FFmpegProcessBuilder(string ffmpegPath, bool saveReports)
{
@ -186,6 +187,8 @@ namespace ErsatzTV.Core.FFmpeg @@ -186,6 +187,8 @@ namespace ErsatzTV.Core.FFmpeg
public FFmpegProcessBuilder WithConcat(string concatPlaylist)
{
_isConcat = true;
var arguments = new List<string>
{
"-f", "concat",
@ -193,8 +196,6 @@ namespace ErsatzTV.Core.FFmpeg @@ -193,8 +196,6 @@ namespace ErsatzTV.Core.FFmpeg
"-protocol_whitelist", "file,http,tcp,https,tcp,tls",
"-probesize", "32",
"-i", concatPlaylist,
"-map", "0:v",
"-map", "0:a",
"-c", "copy",
"-muxdelay", "0",
"-muxpreload", "0"
@ -373,10 +374,13 @@ namespace ErsatzTV.Core.FFmpeg @@ -373,10 +374,13 @@ namespace ErsatzTV.Core.FFmpeg
if (_saveReports)
{
string fileName = Path.Combine(FileSystemLayout.FFmpegReportsFolder, "%p-%t.log");
string fileName = _isConcat
? Path.Combine(FileSystemLayout.FFmpegReportsFolder, "ffmpeg-%t-concat.log")
: Path.Combine(FileSystemLayout.FFmpegReportsFolder, "ffmpeg-%t-transcode.log");
startInfo.EnvironmentVariables.Add("FFREPORT", $"file={fileName}:level=32");
}
startInfo.ArgumentList.Add("-nostdin");
foreach (string argument in _arguments)
{
startInfo.ArgumentList.Add(argument);

4
ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs

@ -124,11 +124,11 @@ namespace ErsatzTV.Core.FFmpeg @@ -124,11 +124,11 @@ namespace ErsatzTV.Core.FFmpeg
return builder.WithPipe().Build();
}
public Process ConcatChannel(string ffmpegPath, Channel channel, string scheme, string host)
public Process ConcatChannel(string ffmpegPath, bool saveReports, Channel channel, string scheme, string host)
{
FFmpegPlaybackSettings playbackSettings = _playbackSettingsCalculator.ConcatSettings;
return new FFmpegProcessBuilder(ffmpegPath, false)
return new FFmpegProcessBuilder(ffmpegPath, saveReports)
.WithThreads(1)
.WithQuiet()
.WithFormatFlags(playbackSettings.FormatFlags)

1829
ErsatzTV.Infrastructure/Migrations/20210331010449_Update_FFmpegProfile_ThreadCount.Designer.cs generated

File diff suppressed because it is too large Load Diff

14
ErsatzTV.Infrastructure/Migrations/20210331010449_Update_FFmpegProfile_ThreadCount.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace ErsatzTV.Infrastructure.Migrations
{
public partial class Update_FFmpegProfile_ThreadCount : Migration
{
protected override void Up(MigrationBuilder migrationBuilder) =>
migrationBuilder.Sql(@"UPDATE FFmpegProfile SET ThreadCount = 0 WHERE ThreadCount = 4");
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

3
ErsatzTV/Controllers/IptvController.cs

@ -44,6 +44,9 @@ namespace ErsatzTV.Controllers @@ -44,6 +44,9 @@ namespace ErsatzTV.Controllers
process =>
{
_logger.LogInformation("Starting ts stream for channel {ChannelNumber}", channelNumber);
// _logger.LogDebug(
// "ffmpeg concat arguments {FFmpegArguments}",
// string.Join(" ", process.StartInfo.ArgumentList));
process.Start();
return new FileStreamResult(process.StandardOutput.BaseStream, "video/mp2t");
},

2
ErsatzTV/Validators/FFmpegProfileEditViewModelValidator.cs

@ -14,7 +14,7 @@ namespace ErsatzTV.Validators @@ -14,7 +14,7 @@ namespace ErsatzTV.Validators
public FFmpegProfileEditViewModelValidator()
{
RuleFor(x => x.Name).NotEmpty();
RuleFor(x => x.ThreadCount).GreaterThan(0);
RuleFor(x => x.ThreadCount).GreaterThanOrEqualTo(0);
When(
x => x.Transcode,

Loading…
Cancel
Save