Browse Source

use subtitles instead of drawtext for songs (#510)

pull/512/head
Jason Dove 5 years ago committed by GitHub
parent
commit
919325033d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs
  2. 41
      ErsatzTV.Core/FFmpeg/FFmpegComplexFilterBuilder.cs
  3. 8
      ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs
  4. 4
      ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs
  5. 2
      ErsatzTV.Core/FFmpeg/TempFileCategory.cs
  6. 2
      ErsatzTV.Core/Interfaces/FFmpeg/IFFmpegProcessService.cs

11
ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs

@ -142,7 +142,7 @@ namespace ErsatzTV.Application.Streaming.Queries
if (playoutItemWithPath.PlayoutItem.MediaItem is Song song) if (playoutItemWithPath.PlayoutItem.MediaItem is Song song)
{ {
Option<string> drawtextFile = None; Option<string> subtitleFile = None;
videoVersion = new FallbackMediaVersion videoVersion = new FallbackMediaVersion
{ {
@ -175,10 +175,13 @@ namespace ErsatzTV.Application.Streaming.Queries
// use thumbnail (cover art) if present // use thumbnail (cover art) if present
foreach (SongMetadata metadata in song.SongMetadata) foreach (SongMetadata metadata in song.SongMetadata)
{ {
string fileName = _tempFilePool.GetNextTempFile(TempFileCategory.DrawText); string fileName = _tempFilePool.GetNextTempFile(TempFileCategory.Subtitle);
drawtextFile = fileName; subtitleFile = fileName;
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine("1");
sb.AppendLine("00:00:00,000 --> 99:99:99,999");
if (!string.IsNullOrWhiteSpace(metadata.Artist)) if (!string.IsNullOrWhiteSpace(metadata.Artist))
{ {
sb.AppendLine(metadata.Artist); sb.AppendLine(metadata.Artist);
@ -231,7 +234,7 @@ namespace ErsatzTV.Application.Streaming.Queries
Either<BaseError, string> maybeSongImage = await _ffmpegProcessService.GenerateSongImage( Either<BaseError, string> maybeSongImage = await _ffmpegProcessService.GenerateSongImage(
ffmpegPath, ffmpegPath,
drawtextFile, subtitleFile,
channel, channel,
maybeGlobalWatermark, maybeGlobalWatermark,
videoVersion, videoVersion,

41
ErsatzTV.Core/FFmpeg/FFmpegComplexFilterBuilder.cs

@ -28,7 +28,7 @@ namespace ErsatzTV.Core.FFmpeg
private Option<int> _watermarkIndex; private Option<int> _watermarkIndex;
private string _pixelFormat; private string _pixelFormat;
private string _videoEncoder; private string _videoEncoder;
private Option<string> _drawtext; private Option<string> _subtitle;
public FFmpegComplexFilterBuilder WithHardwareAcceleration(HardwareAccelerationKind hardwareAccelerationKind) public FFmpegComplexFilterBuilder WithHardwareAcceleration(HardwareAccelerationKind hardwareAccelerationKind)
{ {
@ -97,21 +97,21 @@ namespace ErsatzTV.Core.FFmpeg
return this; return this;
} }
public FFmpegComplexFilterBuilder WithDrawtextFile( public FFmpegComplexFilterBuilder WithSubtitleFile(
MediaVersion videoVersion, MediaVersion videoVersion,
Option<string> drawtextFile) Option<string> subtitleFile)
{ {
foreach (string file in drawtextFile) foreach (string file in subtitleFile)
{ {
string effectiveFile = file; string effectiveFile = file;
if (videoVersion is FallbackMediaVersion or CoverArtMediaVersion) if (videoVersion is FallbackMediaVersion or CoverArtMediaVersion)
{ {
string fontPath = Path.Combine(FileSystemLayout.ResourcesCacheFolder, "OPTIKabel-Heavy.otf"); string fontsDir = FileSystemLayout.ResourcesCacheFolder;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
fontPath = fontPath fontsDir = fontsDir
.Replace(@"\", @"/\") .Replace(@"\", @"/\")
.Replace(@":/", @"\\:/"); .Replace(@":/", @"\\:/");
@ -120,27 +120,31 @@ namespace ErsatzTV.Core.FFmpeg
.Replace(@":/", @"\\:/"); .Replace(@":/", @"\\:/");
} }
var horizontalMarginPercent = 3; var leftMarginPercent = 3;
var rightMarginPercent = 3;
const int VERTICAL_MARGIN_PERCENT = 5; const int VERTICAL_MARGIN_PERCENT = 5;
foreach (ChannelWatermark watermark in _watermark) foreach (ChannelWatermark watermark in _watermark)
{ {
horizontalMarginPercent = watermark.HorizontalMarginPercent; leftMarginPercent = rightMarginPercent = watermark.HorizontalMarginPercent;
switch (watermark.Location) switch (watermark.Location)
{ {
case ChannelWatermarkLocation.BottomLeft: case ChannelWatermarkLocation.BottomLeft:
horizontalMarginPercent += watermark.WidthPercent + watermark.HorizontalMarginPercent; leftMarginPercent += watermark.WidthPercent + watermark.HorizontalMarginPercent;
break;
case ChannelWatermarkLocation.BottomRight:
rightMarginPercent += watermark.WidthPercent + watermark.HorizontalMarginPercent;
break; break;
} }
} }
double horizontalMargin = Math.Round(horizontalMarginPercent / 100.0 * _resolution.Width); double leftMargin = Math.Round(leftMarginPercent / 100.0 * _resolution.Width);
double rightMargin = Math.Round(rightMarginPercent / 100.0 * _resolution.Width);
double verticalMargin = Math.Round(VERTICAL_MARGIN_PERCENT / 100.0 * _resolution.Height); double verticalMargin = Math.Round(VERTICAL_MARGIN_PERCENT / 100.0 * _resolution.Height);
double fontSize = Math.Round(_resolution.Height / 20.0);
var location = $"x={horizontalMargin}:y=H-text_h-{verticalMargin}";
_subtitle =
_drawtext = $"subtitles={effectiveFile}:fontsdir={fontsDir}:force_style='PlayResX={_resolution.Width},PlayResY={_resolution.Height},Fontname=OPTIKabel-Heavy,Fontsize={fontSize},PrimaryColour=&HFFFFFF,OutlineColour=&H555555,Alignment=0,MarginR={rightMargin},MarginL={leftMargin},MarginV={verticalMargin},Shadow=3'";
$"drawtext=fontfile={fontPath}:textfile={effectiveFile}:{location}:fontsize=(h/25):fontcolor=white:line_spacing=7";
} }
} }
@ -308,9 +312,6 @@ namespace ErsatzTV.Core.FFmpeg
$"palettegen=max_colors=8,crop=1:1:{next}:0,scale={_resolution.Width}:{_resolution.Height},setsar=1:1"; $"palettegen=max_colors=8,crop=1:1:{next}:0,scale={_resolution.Width}:{_resolution.Height},setsar=1:1";
} }
filter +=
"[b];[b]split[b1][b2];[b1]format=rgba,geq=r=0:g=0:b=0:a=70[fg];[b2][fg]overlay=format=auto";
videoFilterQueue.Add(filter); videoFilterQueue.Add(filter);
} }
@ -365,9 +366,9 @@ namespace ErsatzTV.Core.FFmpeg
_padToSize.IfSome(size => videoFilterQueue.Add($"pad={size.Width}:{size.Height}:(ow-iw)/2:(oh-ih)/2")); _padToSize.IfSome(size => videoFilterQueue.Add($"pad={size.Width}:{size.Height}:(ow-iw)/2:(oh-ih)/2"));
foreach (string drawtext in _drawtext) foreach (string subtitle in _subtitle)
{ {
videoFilterQueue.Add(drawtext); videoFilterQueue.Add(subtitle);
} }
string outputPixelFormat = null; string outputPixelFormat = null;

8
ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs

@ -221,13 +221,13 @@ namespace ErsatzTV.Core.FFmpeg
return this; return this;
} }
public FFmpegProcessBuilder WithDrawtextFile( public FFmpegProcessBuilder WithSubtitleFile(
MediaVersion videoVersion, MediaVersion videoVersion,
Option<string> drawtextFile) Option<string> subtitleFile)
{ {
_complexFilterBuilder = _complexFilterBuilder.WithDrawtextFile( _complexFilterBuilder = _complexFilterBuilder.WithSubtitleFile(
videoVersion, videoVersion,
drawtextFile); subtitleFile);
return this; return this;
} }

4
ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs

@ -238,7 +238,7 @@ namespace ErsatzTV.Core.FFmpeg
public async Task<Either<BaseError, string>> GenerateSongImage( public async Task<Either<BaseError, string>> GenerateSongImage(
string ffmpegPath, string ffmpegPath,
Option<string> drawtextFile, Option<string> subtitleFile,
Channel channel, Channel channel,
Option<ChannelWatermark> globalWatermark, Option<ChannelWatermark> globalWatermark,
MediaVersion videoVersion, MediaVersion videoVersion,
@ -273,7 +273,7 @@ namespace ErsatzTV.Core.FFmpeg
.WithFormatFlags(playbackSettings.FormatFlags) .WithFormatFlags(playbackSettings.FormatFlags)
.WithSongInput(videoPath, videoStream.Codec, videoStream.PixelFormat) .WithSongInput(videoPath, videoStream.Codec, videoStream.PixelFormat)
.WithWatermark(watermarkOptions, channel.FFmpegProfile.Resolution) .WithWatermark(watermarkOptions, channel.FFmpegProfile.Resolution)
.WithDrawtextFile(videoVersion, drawtextFile); .WithSubtitleFile(videoVersion, subtitleFile);
foreach (IDisplaySize scaledSize in scalePlaybackSettings.ScaledSize) foreach (IDisplaySize scaledSize in scalePlaybackSettings.ScaledSize)
{ {

2
ErsatzTV.Core/FFmpeg/TempFileCategory.cs

@ -2,7 +2,7 @@
{ {
public enum TempFileCategory public enum TempFileCategory
{ {
DrawText = 0, Subtitle = 0,
SongBackground = 1, SongBackground = 1,
CoverArt = 2 CoverArt = 2
} }

2
ErsatzTV.Core/Interfaces/FFmpeg/IFFmpegProcessService.cs

@ -42,7 +42,7 @@ namespace ErsatzTV.Core.Interfaces.FFmpeg
Task<Either<BaseError, string>> GenerateSongImage( Task<Either<BaseError, string>> GenerateSongImage(
string ffmpegPath, string ffmpegPath,
Option<string> drawtextFile, Option<string> subtitleFile,
Channel channel, Channel channel,
Option<ChannelWatermark> globalWatermark, Option<ChannelWatermark> globalWatermark,
MediaVersion videoVersion, MediaVersion videoVersion,

Loading…
Cancel
Save