Browse Source

add watermark opacity (#259)

pull/260/head
Jason Dove 4 years ago committed by GitHub
parent
commit
679feb6d21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      CHANGELOG.md
  2. 3
      ErsatzTV.Application/Channels/ChannelViewModel.cs
  3. 3
      ErsatzTV.Application/Channels/Commands/CreateChannel.cs
  4. 3
      ErsatzTV.Application/Channels/Commands/CreateChannelHandler.cs
  5. 3
      ErsatzTV.Application/Channels/Commands/UpdateChannel.cs
  6. 4
      ErsatzTV.Application/Channels/Commands/UpdateChannelHandler.cs
  7. 3
      ErsatzTV.Application/Channels/Mapper.cs
  8. 1
      ErsatzTV.Core/Domain/ChannelWatermark.cs
  9. 23
      ErsatzTV.Core/FFmpeg/FFmpegComplexFilterBuilder.cs
  10. 2942
      ErsatzTV.Infrastructure/Migrations/20210614013016_Add_ChannelWatermarkOpacity.Designer.cs
  11. 24
      ErsatzTV.Infrastructure/Migrations/20210614013016_Add_ChannelWatermarkOpacity.cs
  12. 3
      ErsatzTV.Infrastructure/Migrations/TvContextModelSnapshot.cs
  13. 13
      ErsatzTV/Pages/ChannelEditor.razor
  14. 5
      ErsatzTV/Validators/ChannelEditViewModelValidator.cs
  15. 7
      ErsatzTV/ViewModels/ChannelEditViewModel.cs

3
CHANGELOG.md

@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Added
- Add watermark opacity setting to allow blending with content
### Changed
- Remove unused API and SDK project; may reintroduce in the future but for now they have fallen out of date

3
ErsatzTV.Application/Channels/ChannelViewModel.cs

@ -17,5 +17,6 @@ namespace ErsatzTV.Application.Channels @@ -17,5 +17,6 @@ namespace ErsatzTV.Application.Channels
int WatermarkHorizontalMargin,
int WatermarkVerticalMargin,
int WatermarkFrequencyMinutes,
int WatermarkDurationSeconds);
int WatermarkDurationSeconds,
int WatermarkOpacity);
}

3
ErsatzTV.Application/Channels/Commands/CreateChannel.cs

@ -20,5 +20,6 @@ namespace ErsatzTV.Application.Channels.Commands @@ -20,5 +20,6 @@ namespace ErsatzTV.Application.Channels.Commands
int WatermarkHorizontalMargin,
int WatermarkVerticalMargin,
int WatermarkFrequencyMinutes,
int WatermarkDurationSeconds) : IRequest<Either<BaseError, CreateChannelResult>>;
int WatermarkDurationSeconds,
int WatermarkOpacity) : IRequest<Either<BaseError, CreateChannelResult>>;
}

3
ErsatzTV.Application/Channels/Commands/CreateChannelHandler.cs

@ -79,7 +79,8 @@ namespace ErsatzTV.Application.Channels.Commands @@ -79,7 +79,8 @@ namespace ErsatzTV.Application.Channels.Commands
HorizontalMarginPercent = request.WatermarkHorizontalMargin,
VerticalMarginPercent = request.WatermarkVerticalMargin,
FrequencyMinutes = request.WatermarkFrequencyMinutes,
DurationSeconds = request.WatermarkDurationSeconds
DurationSeconds = request.WatermarkDurationSeconds,
Opacity = request.WatermarkOpacity
};
}

3
ErsatzTV.Application/Channels/Commands/UpdateChannel.cs

@ -21,5 +21,6 @@ namespace ErsatzTV.Application.Channels.Commands @@ -21,5 +21,6 @@ namespace ErsatzTV.Application.Channels.Commands
int WatermarkHorizontalMargin,
int WatermarkVerticalMargin,
int WatermarkFrequencyMinutes,
int WatermarkDurationSeconds) : IRequest<Either<BaseError, ChannelViewModel>>;
int WatermarkDurationSeconds,
int WatermarkOpacity) : IRequest<Either<BaseError, ChannelViewModel>>;
}

4
ErsatzTV.Application/Channels/Commands/UpdateChannelHandler.cs

@ -77,6 +77,7 @@ namespace ErsatzTV.Application.Channels.Commands @@ -77,6 +77,7 @@ namespace ErsatzTV.Application.Channels.Commands
c.Watermark.VerticalMarginPercent = update.WatermarkVerticalMargin;
c.Watermark.FrequencyMinutes = update.WatermarkFrequencyMinutes;
c.Watermark.DurationSeconds = update.WatermarkDurationSeconds;
c.Watermark.Opacity = update.WatermarkOpacity;
}
else
{
@ -89,7 +90,8 @@ namespace ErsatzTV.Application.Channels.Commands @@ -89,7 +90,8 @@ namespace ErsatzTV.Application.Channels.Commands
HorizontalMarginPercent = update.WatermarkHorizontalMargin,
VerticalMarginPercent = update.WatermarkVerticalMargin,
FrequencyMinutes = update.WatermarkFrequencyMinutes,
DurationSeconds = update.WatermarkDurationSeconds
DurationSeconds = update.WatermarkDurationSeconds,
Opacity = update.WatermarkOpacity
};
}
}

3
ErsatzTV.Application/Channels/Mapper.cs

@ -22,7 +22,8 @@ namespace ErsatzTV.Application.Channels @@ -22,7 +22,8 @@ namespace ErsatzTV.Application.Channels
channel.Watermark?.HorizontalMarginPercent ?? 5,
channel.Watermark?.VerticalMarginPercent ?? 5,
channel.Watermark?.FrequencyMinutes ?? 15,
channel.Watermark?.DurationSeconds ?? 15);
channel.Watermark?.DurationSeconds ?? 15,
channel.Watermark?.Opacity ?? 100);
private static string GetLogo(Channel channel) =>
Optional(channel.Artwork.FirstOrDefault(a => a.ArtworkKind == ArtworkKind.Logo))

1
ErsatzTV.Core/Domain/ChannelWatermark.cs

@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
public int VerticalMarginPercent { get; set; }
public int FrequencyMinutes { get; set; }
public int DurationSeconds { get; set; }
public int Opacity { get; set; }
}
public enum ChannelWatermarkLocation

23
ErsatzTV.Core/FFmpeg/FFmpegComplexFilterBuilder.cs

@ -88,7 +88,7 @@ namespace ErsatzTV.Core.FFmpeg @@ -88,7 +88,7 @@ namespace ErsatzTV.Core.FFmpeg
var audioFilterQueue = new List<string>();
var videoFilterQueue = new List<string>();
string watermarkScale = string.Empty;
string watermarkPreprocess = string.Empty;
string watermarkOverlay = string.Empty;
if (_normalizeLoudness)
@ -180,7 +180,20 @@ namespace ErsatzTV.Core.FFmpeg @@ -180,7 +180,20 @@ namespace ErsatzTV.Core.FFmpeg
if (watermark.Size == ChannelWatermarkSize.Scaled)
{
double width = Math.Round(watermark.WidthPercent / 100.0 * _resolution.Width);
watermarkScale = $"scale={width}:-1";
watermarkPreprocess = $"scale={width}:-1";
}
if (watermark.Opacity != 100)
{
const string FORMATS = "yuva420p|yuva444p|yuva422p|rgba|abgr|bgra|gbrap|ya8";
string join = string.Empty;
double opacity = watermark.Opacity / 100.0;
if (!string.IsNullOrWhiteSpace(watermarkPreprocess))
{
join = ",";
}
watermarkPreprocess = $"format={FORMATS},colorchannelmixer=aa={opacity:F2}{join}{watermarkPreprocess}";
}
watermarkOverlay = $"overlay={position}{enable}";
@ -224,10 +237,10 @@ namespace ErsatzTV.Core.FFmpeg @@ -224,10 +237,10 @@ namespace ErsatzTV.Core.FFmpeg
{
complexFilter.Append("[vt]");
var watermarkLabel = "[1:v]";
if (!string.IsNullOrWhiteSpace(watermarkScale))
if (!string.IsNullOrWhiteSpace(watermarkPreprocess))
{
complexFilter.Append($";{watermarkLabel}{watermarkScale}[wms]");
watermarkLabel = "[wms]";
complexFilter.Append($";{watermarkLabel}{watermarkPreprocess}[wmp]");
watermarkLabel = "[wmp]";
}
complexFilter.Append($";[vt]{watermarkLabel}{watermarkOverlay}");

2942
ErsatzTV.Infrastructure/Migrations/20210614013016_Add_ChannelWatermarkOpacity.Designer.cs generated

File diff suppressed because it is too large Load Diff

24
ErsatzTV.Infrastructure/Migrations/20210614013016_Add_ChannelWatermarkOpacity.cs

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace ErsatzTV.Infrastructure.Migrations
{
public partial class Add_ChannelWatermarkOpacity : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Opacity",
table: "ChannelWatermark",
type: "INTEGER",
nullable: false,
defaultValue: 100);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Opacity",
table: "ChannelWatermark");
}
}
}

3
ErsatzTV.Infrastructure/Migrations/TvContextModelSnapshot.cs

@ -240,6 +240,9 @@ namespace ErsatzTV.Infrastructure.Migrations @@ -240,6 +240,9 @@ namespace ErsatzTV.Infrastructure.Migrations
b.Property<int>("Mode")
.HasColumnType("INTEGER");
b.Property<int>("Opacity")
.HasColumnType("INTEGER");
b.Property<int>("Size")
.HasColumnType("INTEGER");

13
ErsatzTV/Pages/ChannelEditor.razor

@ -141,6 +141,17 @@ @@ -141,6 +141,17 @@
Immediate="true"/>
</MudItem>
</MudGrid>
<MudGrid Class="mt-3" Style="align-items: start" Justify="Justify.Center">
<MudItem xs="6">
<MudTextField Label="Opacity" @bind-Value="_model.WatermarkOpacity"
For="@(() => _model.WatermarkOpacity)"
Adornment="Adornment.End"
AdornmentText="%"
Disabled="@(_model.StreamingMode == StreamingMode.HttpLiveStreamingDirect || _model.WatermarkMode == ChannelWatermarkMode.None)"
Immediate="true"/>
</MudItem>
<MudItem xs="6" />
</MudGrid>
</MudCardContent>
<MudCardActions>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary">
@ -190,6 +201,7 @@ @@ -190,6 +201,7 @@
_model.WatermarkVerticalMargin = channelViewModel.WatermarkVerticalMargin;
_model.WatermarkFrequencyMinutes = channelViewModel.WatermarkFrequencyMinutes;
_model.WatermarkDurationSeconds = channelViewModel.WatermarkDurationSeconds;
_model.WatermarkOpacity = channelViewModel.WatermarkOpacity;
},
() => _navigationManager.NavigateTo("404"));
}
@ -213,6 +225,7 @@ @@ -213,6 +225,7 @@
_model.WatermarkVerticalMargin = 5;
_model.WatermarkFrequencyMinutes = 15;
_model.WatermarkDurationSeconds = 15;
_model.WatermarkOpacity = 100;
}
}

5
ErsatzTV/Validators/ChannelEditViewModelValidator.cs

@ -49,6 +49,11 @@ namespace ErsatzTV.Validators @@ -49,6 +49,11 @@ namespace ErsatzTV.Validators
.GreaterThan(0)
.LessThan(c => c.WatermarkFrequencyMinutes * 60)
.When(vm => vm.WatermarkMode != ChannelWatermarkMode.None);
RuleFor(x => x.WatermarkOpacity)
.GreaterThan(0)
.LessThanOrEqualTo(100)
.When(vm => vm.WatermarkMode != ChannelWatermarkMode.None);
}
}
}

7
ErsatzTV/ViewModels/ChannelEditViewModel.cs

@ -20,6 +20,7 @@ namespace ErsatzTV.ViewModels @@ -20,6 +20,7 @@ namespace ErsatzTV.ViewModels
public int WatermarkVerticalMargin { get; set; }
public int WatermarkFrequencyMinutes { get; set; }
public int WatermarkDurationSeconds { get; set; }
public int WatermarkOpacity { get; set; }
public UpdateChannel ToUpdate() =>
new(
@ -37,7 +38,8 @@ namespace ErsatzTV.ViewModels @@ -37,7 +38,8 @@ namespace ErsatzTV.ViewModels
WatermarkHorizontalMargin,
WatermarkVerticalMargin,
WatermarkFrequencyMinutes,
WatermarkDurationSeconds);
WatermarkDurationSeconds,
WatermarkOpacity);
public CreateChannel ToCreate() =>
new(
@ -54,6 +56,7 @@ namespace ErsatzTV.ViewModels @@ -54,6 +56,7 @@ namespace ErsatzTV.ViewModels
WatermarkHorizontalMargin,
WatermarkVerticalMargin,
WatermarkFrequencyMinutes,
WatermarkDurationSeconds);
WatermarkDurationSeconds,
WatermarkOpacity);
}
}

Loading…
Cancel
Save