Browse Source

subtitle fixes (#750)

* fix crash with missing metadata

* fix subtitles in docker

* fix software overlay bug
pull/751/head
Jason Dove 4 years ago committed by GitHub
parent
commit
097b8c3d1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 8
      ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs
  3. 46
      ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs
  4. 4
      ErsatzTV.FFmpeg/Filter/ComplexFilter.cs
  5. 2
      ErsatzTV.Infrastructure/Data/DbInitializer.cs
  6. 2
      ErsatzTV.Infrastructure/Health/Checks/FFmpegVersionHealthCheck.cs
  7. 4
      docker/Dockerfile
  8. 2
      docker/nvidia/Dockerfile
  9. 4
      docker/nvidia/ffmpeg.Dockerfile
  10. 2
      docker/vaapi/Dockerfile
  11. 13
      docker/vaapi/ffmpeg.Dockerfile

1
CHANGELOG.md

@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased] ## [Unreleased]
### Fixed ### Fixed
- Fix unlocking libraries when scanning fails for any reason - Fix unlocking libraries when scanning fails for any reason
- Fix software overlay of actual size watermark
### Added ### Added
- Add support for burning in embedded text subtitles - Add support for burning in embedded text subtitles

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

@ -240,16 +240,16 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
{ {
List<Subtitle> allSubtitles = playoutItemWithPath.PlayoutItem.MediaItem switch List<Subtitle> allSubtitles = playoutItemWithPath.PlayoutItem.MediaItem switch
{ {
Episode episode => episode.EpisodeMetadata.HeadOrNone() Episode episode => Optional(episode.EpisodeMetadata).Flatten().HeadOrNone()
.Map(mm => mm.Subtitles) .Map(mm => mm.Subtitles)
.IfNone(new List<Subtitle>()), .IfNone(new List<Subtitle>()),
Movie movie => movie.MovieMetadata.HeadOrNone() Movie movie => Optional(movie.MovieMetadata).Flatten().HeadOrNone()
.Map(mm => mm.Subtitles) .Map(mm => mm.Subtitles)
.IfNone(new List<Subtitle>()), .IfNone(new List<Subtitle>()),
MusicVideo musicVideo => musicVideo.MusicVideoMetadata.HeadOrNone() MusicVideo musicVideo => Optional(musicVideo.MusicVideoMetadata).Flatten().HeadOrNone()
.Map(mm => mm.Subtitles) .Map(mm => mm.Subtitles)
.IfNone(new List<Subtitle>()), .IfNone(new List<Subtitle>()),
OtherVideo otherVideo => otherVideo.OtherVideoMetadata.HeadOrNone() OtherVideo otherVideo => Optional(otherVideo.OtherVideoMetadata).Flatten().HeadOrNone()
.Map(mm => mm.Subtitles) .Map(mm => mm.Subtitles)
.IfNone(new List<Subtitle>()), .IfNone(new List<Subtitle>()),
_ => new List<Subtitle>() _ => new List<Subtitle>()

46
ErsatzTV.Core.Tests/FFmpeg/TranscodingTests.cs

@ -10,6 +10,7 @@ using ErsatzTV.Core.Interfaces.FFmpeg;
using ErsatzTV.Core.Interfaces.Images; using ErsatzTV.Core.Interfaces.Images;
using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Metadata; using ErsatzTV.Core.Metadata;
using ErsatzTV.FFmpeg.State;
using FluentAssertions; using FluentAssertions;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -58,11 +59,13 @@ public class TranscodingTests
public enum Watermark public enum Watermark
{ {
None, None,
PermanentOpaque, PermanentOpaqueScaled,
PermanentTransparent, PermanentOpaqueActualSize,
PermanentTransparentScaled,
PermanentTransparentActualSize,
IntermittentOpaque, IntermittentOpaque,
IntermittentTransparent IntermittentTransparent
// TODO: animated vs static // TODO: animated vs static
} }
@ -78,8 +81,10 @@ public class TranscodingTests
public static Watermark[] Watermarks = public static Watermark[] Watermarks =
{ {
Watermark.None, Watermark.None,
Watermark.PermanentOpaque, Watermark.PermanentOpaqueScaled,
Watermark.PermanentTransparent Watermark.PermanentOpaqueActualSize,
Watermark.PermanentTransparentScaled,
Watermark.PermanentTransparentActualSize
}; };
public static Subtitle[] Subtitles = public static Subtitle[] Subtitles =
@ -184,8 +189,7 @@ public class TranscodingTests
[ValueSource(typeof(TestData), nameof(TestData.VideoFormats))] [ValueSource(typeof(TestData), nameof(TestData.VideoFormats))]
FFmpegProfileVideoFormat profileVideoFormat, FFmpegProfileVideoFormat profileVideoFormat,
// [ValueSource(typeof(TestData), nameof(TestData.NoAcceleration))] HardwareAccelerationKind profileAcceleration) // [ValueSource(typeof(TestData), nameof(TestData.NoAcceleration))] HardwareAccelerationKind profileAcceleration)
[ValueSource(typeof(TestData), nameof(TestData.NvidiaAcceleration))] [ValueSource(typeof(TestData), nameof(TestData.NvidiaAcceleration))] HardwareAccelerationKind profileAcceleration)
HardwareAccelerationKind profileAcceleration)
// [ValueSource(typeof(TestData), nameof(TestData.VaapiAcceleration))] HardwareAccelerationKind profileAcceleration) // [ValueSource(typeof(TestData), nameof(TestData.VaapiAcceleration))] HardwareAccelerationKind profileAcceleration)
// [ValueSource(typeof(TestData), nameof(TestData.QsvAcceleration))] HardwareAccelerationKind profileAcceleration) // [ValueSource(typeof(TestData), nameof(TestData.QsvAcceleration))] HardwareAccelerationKind profileAcceleration)
// [ValueSource(typeof(TestData), nameof(TestData.VideoToolboxAcceleration))] HardwareAccelerationKind profileAcceleration) // [ValueSource(typeof(TestData), nameof(TestData.VideoToolboxAcceleration))] HardwareAccelerationKind profileAcceleration)
@ -394,20 +398,40 @@ public class TranscodingTests
Opacity = 80 Opacity = 80
}; };
break; break;
case Watermark.PermanentOpaque: case Watermark.PermanentOpaqueScaled:
channelWatermark = new ChannelWatermark channelWatermark = new ChannelWatermark
{ {
ImageSource = ChannelWatermarkImageSource.Custom, ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent, Mode = ChannelWatermarkMode.Permanent,
Opacity = 100 Opacity = 100,
Size = WatermarkSize.Scaled
}; };
break; break;
case Watermark.PermanentTransparent: case Watermark.PermanentOpaqueActualSize:
channelWatermark = new ChannelWatermark channelWatermark = new ChannelWatermark
{ {
ImageSource = ChannelWatermarkImageSource.Custom, ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent, Mode = ChannelWatermarkMode.Permanent,
Opacity = 80 Opacity = 100,
Size = WatermarkSize.ActualSize
};
break;
case Watermark.PermanentTransparentScaled:
channelWatermark = new ChannelWatermark
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent,
Opacity = 80,
Size = WatermarkSize.Scaled
};
break;
case Watermark.PermanentTransparentActualSize:
channelWatermark = new ChannelWatermark
{
ImageSource = ChannelWatermarkImageSource.Custom,
Mode = ChannelWatermarkMode.Permanent,
Opacity = 80,
Size = WatermarkSize.ActualSize
}; };
break; break;
} }

4
ErsatzTV.FFmpeg/Filter/ComplexFilter.cs

@ -142,6 +142,10 @@ public class ComplexFilter : IPipelineStep
watermarkLabel = "[wm]"; watermarkLabel = "[wm]";
watermarkFilterComplex += watermarkLabel; watermarkFilterComplex += watermarkLabel;
} }
else
{
watermarkLabel = $"[{watermarkLabel}]";
}
IPipelineFilterStep overlayFilter = AvailableWatermarkOverlayFilters.ForAcceleration( IPipelineFilterStep overlayFilter = AvailableWatermarkOverlayFilters.ForAcceleration(
_ffmpegState.HardwareAccelerationMode, _ffmpegState.HardwareAccelerationMode,

2
ErsatzTV.Infrastructure/Data/DbInitializer.cs

@ -84,7 +84,7 @@ public static class DbInitializer
Number = "1", Number = "1",
Name = "ErsatzTV", Name = "ErsatzTV",
FFmpegProfile = defaultProfile, FFmpegProfile = defaultProfile,
StreamingMode = StreamingMode.TransportStream StreamingMode = StreamingMode.TransportStreamHybrid
}; };
await context.Channels.AddAsync(defaultChannel, cancellationToken); await context.Channels.AddAsync(defaultChannel, cancellationToken);
await context.SaveChangesAsync(cancellationToken); await context.SaveChangesAsync(cancellationToken);

2
ErsatzTV.Infrastructure/Health/Checks/FFmpegVersionHealthCheck.cs

@ -8,7 +8,7 @@ namespace ErsatzTV.Infrastructure.Health.Checks;
public class FFmpegVersionHealthCheck : BaseHealthCheck, IFFmpegVersionHealthCheck public class FFmpegVersionHealthCheck : BaseHealthCheck, IFFmpegVersionHealthCheck
{ {
private const string BundledVersion = "N-105324-g0f5fd44dc9"; private const string BundledVersion = "N-106635-g83e1a1de88";
private readonly IConfigElementRepository _configElementRepository; private readonly IConfigElementRepository _configElementRepository;
public FFmpegVersionHealthCheck(IConfigElementRepository configElementRepository) => public FFmpegVersionHealthCheck(IConfigElementRepository configElementRepository) =>

4
docker/Dockerfile

@ -2,7 +2,7 @@
FROM jasongdove/ffmpeg:5.0-ubuntu2004 AS runtime-base FROM jasongdove/ffmpeg:5.0-ubuntu2004 AS runtime-base
COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet
RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev tzdata RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev tzdata fontconfig fonts-dejavu
# https://hub.docker.com/_/microsoft-dotnet # https://hub.docker.com/_/microsoft-dotnet
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
@ -36,6 +36,8 @@ RUN dotnet publish ErsatzTV.csproj -c release -o /app -r linux-x64 --self-contai
# final stage/image # final stage/image
FROM runtime-base FROM runtime-base
ENV FONTCONFIG_PATH=/etc/fonts
RUN fc-cache update
WORKDIR /app WORKDIR /app
EXPOSE 8409 EXPOSE 8409
COPY --from=build /app ./ COPY --from=build /app ./

2
docker/nvidia/Dockerfile

@ -30,6 +30,8 @@ RUN dotnet publish ErsatzTV.csproj -c release -o /app -r linux-x64 --self-contai
# final stage/image # final stage/image
FROM jasongdove/ffmpeg:5.0-nvidia2004 AS runtime-base FROM jasongdove/ffmpeg:5.0-nvidia2004 AS runtime-base
ENV FONTCONFIG_PATH=/etc/fonts
RUN fc-cache update
WORKDIR /app WORKDIR /app
EXPOSE 8409 EXPOSE 8409
COPY --from=build /app ./ COPY --from=build /app ./

4
docker/nvidia/ffmpeg.Dockerfile

@ -3,5 +3,5 @@
FROM jasongdove/ffmpeg-base:5.0-nvidia2004 AS runtime-base FROM jasongdove/ffmpeg-base:5.0-nvidia2004 AS runtime-base
COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet
RUN apt-get update \ RUN apt-get update \
&& DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev tzdata \ && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev tzdata fontconfig fonts-dejavu \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*

2
docker/vaapi/Dockerfile

@ -30,6 +30,8 @@ RUN dotnet publish ErsatzTV.csproj -c release -o /app -r linux-x64 --self-contai
# final stage/image # final stage/image
FROM jasongdove/ffmpeg:5.0-vaapi2004 AS runtime-base FROM jasongdove/ffmpeg:5.0-vaapi2004 AS runtime-base
ENV FONTCONFIG_PATH=/etc/fonts
RUN fc-cache update
WORKDIR /app WORKDIR /app
EXPOSE 8409 EXPOSE 8409
COPY --from=build /app ./ COPY --from=build /app ./

13
docker/vaapi/ffmpeg.Dockerfile

@ -4,6 +4,8 @@ FROM jasongdove/ffmpeg-base:5.0-vaapi2004 AS runtime-base
COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet
RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev \ RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev \
tzdata \ tzdata \
fontconfig \
fonts-dejavu \
autoconf \ autoconf \
libtool \ libtool \
libdrm-dev \ libdrm-dev \
@ -14,21 +16,22 @@ RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu
wget \ wget \
mesa-va-drivers \ mesa-va-drivers \
&& mkdir /tmp/intel && cd /tmp/intel \ && mkdir /tmp/intel && cd /tmp/intel \
&& wget -O - https://github.com/intel/libva/archive/refs/tags/2.12.0.tar.gz | tar zxf - \ && wget -O - https://github.com/intel/libva/archive/refs/tags/2.14.0.tar.gz | tar zxf - \
&& cd libva-2.12.0 \ && cd libva-2.14.0 \
&& ./autogen.sh \ && ./autogen.sh \
&& ./configure \ && ./configure \
&& make -j$(nproc) \ && make -j$(nproc) \
&& make -j$(nproc) install \ && make -j$(nproc) install \
&& cd /tmp/intel \ && cd /tmp/intel \
&& wget -O - https://github.com/intel/gmmlib/archive/refs/tags/intel-gmmlib-21.3.1.tar.gz | tar zxf - \ && wget -O - https://github.com/intel/gmmlib/archive/refs/tags/intel-gmmlib-22.1.2.tar.gz | tar zxf - \
&& mv gmmlib-intel-gmmlib-21.3.1 gmmlib \ && mv gmmlib-intel-gmmlib-22.1.2 gmmlib \
&& cd gmmlib \ && cd gmmlib \
&& mkdir build && cd build \ && mkdir build && cd build \
&& cmake .. \ && cmake .. \
&& make -j$(nproc) \ && make -j$(nproc) \
&& make install \
&& cd /tmp/intel \ && cd /tmp/intel \
&& git clone --depth 1 --branch intel-media-21.2.3 https://github.com/intel/media-driver \ && git clone --depth 1 --branch intel-media-22.3 https://github.com/intel/media-driver \
&& mkdir build_media && cd build_media \ && mkdir build_media && cd build_media \
&& cmake ../media-driver \ && cmake ../media-driver \
&& make -j$(nproc) \ && make -j$(nproc) \

Loading…
Cancel
Save