From f9427cac99d78cfbff318e8f1c7ada7daa59540d Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Tue, 25 May 2021 05:13:51 -0500 Subject: [PATCH] use multiple docker tags again (#209) * Revert "disable framerate normalization (#208)" This reverts commit 141a34933d6c06dd494b4192319114c0137eceb9. * Revert "use linuxserver base docker image (#207)" This reverts commit 0962a1429a466973a2eef6a20ba45a235de95f29. * fix playback that only uses fps filter * nvidia needs privileged --- .github/workflows/ci.yml | 42 ++++++++++++-- .github/workflows/release.yml | 40 ++++++++++++- .../FFmpegPlaybackSettingsCalculatorTests.cs | 57 +++++++++---------- .../FFmpegPlaybackSettingsCalculator.cs | 6 +- ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs | 2 +- ErsatzTV/Pages/FFmpegEditor.razor | 6 +- docker/Dockerfile | 5 +- docker/docker-compose.nvidia.yml | 8 ++- docker/docker-compose.vaapi.yml | 2 + docker/nvidia/Dockerfile | 40 +++++++++++++ docker/vaapi/Dockerfile | 40 +++++++++++++ 11 files changed, 201 insertions(+), 47 deletions(-) create mode 100644 docker/nvidia/Dockerfile create mode 100644 docker/vaapi/Dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9bf82111b..2eebe9c55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,9 +52,17 @@ jobs: final="${tag2/prealpha/$short}" echo "GIT_TAG=${final}" >> $GITHUB_ENV - - name: Set up Docker Buildx + - name: Set up Docker Buildx Base uses: docker/setup-buildx-action@v1 - id: builder + id: builder-base + + - name: Set up Docker Buildx NVIDIA + uses: docker/setup-buildx-action@v1 + id: builder-nvidia + + - name: Set up Docker Buildx VAAPI + uses: docker/setup-buildx-action@v1 + id: builder-vaapi - name: Login to DockerHub uses: docker/login-action@v1 @@ -62,10 +70,10 @@ jobs: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - name: Build and push + - name: Build and push base uses: docker/build-push-action@v2 with: - builder: ${{ steps.builder.outputs.name }} + builder: ${{ steps.builder-base.outputs.name }} context: . file: ./docker/Dockerfile push: true @@ -74,3 +82,29 @@ jobs: tags: | jasongdove/ersatztv:develop jasongdove/ersatztv:${{ github.sha }} + + - name: Build and push nvidia + uses: docker/build-push-action@v2 + with: + builder: ${{ steps.builder-nvidia.outputs.name }} + context: . + file: ./docker/nvidia/Dockerfile + push: true + build-args: | + INFO_VERSION=${{ env.GIT_TAG }}-docker-nvidia + tags: | + jasongdove/ersatztv:develop-nvidia + jasongdove/ersatztv:${{ github.sha }}-nvidia + + - name: Build and push vaapi + uses: docker/build-push-action@v2 + with: + builder: ${{ steps.builder-vaapi.outputs.name }} + context: . + file: ./docker/vaapi/Dockerfile + push: true + build-args: | + INFO_VERSION=${{ env.GIT_TAG }}-docker-vaapi + tags: | + jasongdove/ersatztv:develop-vaapi + jasongdove/ersatztv:${{ github.sha }}-vaapi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aad0e85ce..816ceef41 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -83,9 +83,17 @@ jobs: echo "GIT_TAG=${tag:1}" >> $GITHUB_ENV echo "DOCKER_TAG=${tag/-prealpha/}" >> $GITHUB_ENV - - name: Set up Docker Buildx + - name: Set up Docker Buildx Base uses: docker/setup-buildx-action@v1 - id: builder + id: builder-base + + - name: Set up Docker Buildx NVIDIA + uses: docker/setup-buildx-action@v1 + id: builder-nvidia + + - name: Set up Docker Buildx VAAPI + uses: docker/setup-buildx-action@v1 + id: builder-vaapi - name: Login to DockerHub uses: docker/login-action@v1 @@ -96,7 +104,7 @@ jobs: - name: Build and push base uses: docker/build-push-action@v2 with: - builder: ${{ steps.builder.outputs.name }} + builder: ${{ steps.builder-base.outputs.name }} context: . file: ./docker/Dockerfile push: true @@ -105,3 +113,29 @@ jobs: tags: | jasongdove/ersatztv:latest jasongdove/ersatztv:${{ env.DOCKER_TAG }} + + - name: Build and push nvidia + uses: docker/build-push-action@v2 + with: + builder: ${{ steps.builder-nvidia.outputs.name }} + context: . + file: ./docker/nvidia/Dockerfile + push: true + build-args: | + INFO_VERSION=${{ env.GIT_TAG }}-docker-nvidia + tags: | + jasongdove/ersatztv:latest-nvidia + jasongdove/ersatztv:${{ env.DOCKER_TAG }}-nvidia + + - name: Build and push vaapi + uses: docker/build-push-action@v2 + with: + builder: ${{ steps.builder-vaapi.outputs.name }} + context: . + file: ./docker/vaapi/Dockerfile + push: true + build-args: | + INFO_VERSION=${{ env.GIT_TAG }}-docker-vaapi + tags: | + jasongdove/ersatztv:latest-vaapi + jasongdove/ersatztv:${{ env.DOCKER_TAG }}-vaapi diff --git a/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs b/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs index f5dfcfa31..2ae148cc2 100644 --- a/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs +++ b/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs @@ -467,35 +467,34 @@ namespace ErsatzTV.Core.Tests.FFmpeg actual.VideoCodec.Should().Be("copy"); } - // disabled while frame rate normalization is unused - // [Test] - // public void ShouldNot_SetCopyVideoCodec_When_ContentIsCorrectSize_And_CorrectCodec_And_Framerate_ForTransportStream() - // { - // var ffmpegProfile = new FFmpegProfile - // { - // NormalizeVideo = true, - // Resolution = new Resolution { Width = 1920, Height = 1080 }, - // VideoCodec = "libx264", - // FrameRate = "24" - // }; - // - // // not anamorphic - // var version = new MediaVersion - // { Width = 1920, Height = 1080, SampleAspectRatio = "1:1" }; - // - // FFmpegPlaybackSettings actual = _calculator.CalculateSettings( - // StreamingMode.TransportStream, - // ffmpegProfile, - // version, - // new MediaStream { Codec = "libx264" }, - // new MediaStream(), - // DateTimeOffset.Now, - // DateTimeOffset.Now); - // - // actual.ScaledSize.IsNone.Should().BeTrue(); - // actual.PadToDesiredResolution.Should().BeFalse(); - // actual.VideoCodec.Should().NotBe("copy"); - // } + [Test] + public void Should_SetCorrectVideoCodec_When_ContentIsCorrectSize_And_CorrectCodec_And_Framerate_ForTransportStream() + { + var ffmpegProfile = new FFmpegProfile + { + NormalizeVideo = true, + Resolution = new Resolution { Width = 1920, Height = 1080 }, + VideoCodec = "libx264", + FrameRate = "24" + }; + + // not anamorphic + var version = new MediaVersion + { Width = 1920, Height = 1080, SampleAspectRatio = "1:1" }; + + FFmpegPlaybackSettings actual = _calculator.CalculateSettings( + StreamingMode.TransportStream, + ffmpegProfile, + version, + new MediaStream { Codec = "libx264" }, + new MediaStream(), + DateTimeOffset.Now, + DateTimeOffset.Now); + + actual.ScaledSize.IsNone.Should().BeTrue(); + actual.PadToDesiredResolution.Should().BeFalse(); + actual.VideoCodec.Should().Be("libx264"); + } [Test] public void diff --git a/ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs b/ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs index 6e5809462..af3846efc 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs @@ -91,9 +91,9 @@ namespace ErsatzTV.Core.FFmpeg if (ffmpegProfile.NormalizeVideo) { - // result.FrameRate = string.IsNullOrWhiteSpace(ffmpegProfile.FrameRate) - // ? None - // : Some(ffmpegProfile.FrameRate); + result.FrameRate = string.IsNullOrWhiteSpace(ffmpegProfile.FrameRate) + ? None + : Some(ffmpegProfile.FrameRate); result.VideoTrackTimeScale = 90000; } diff --git a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs index 0b6be7564..bcf46c71a 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs @@ -49,7 +49,7 @@ namespace ErsatzTV.Core.FFmpeg .WithRealtimeOutput(playbackSettings.RealtimeOutput) .WithSeek(playbackSettings.StreamSeek) .WithInputCodec(path, playbackSettings.HardwareAcceleration, videoStream.Codec) - // .WithFrameRate(playbackSettings.FrameRate) + .WithFrameRate(playbackSettings.FrameRate) .WithVideoTrackTimeScale(playbackSettings.VideoTrackTimeScale) .WithAlignedAudio(playbackSettings.AudioDuration) .WithNormalizeLoudness(playbackSettings.NormalizeLoudness); diff --git a/ErsatzTV/Pages/FFmpegEditor.razor b/ErsatzTV/Pages/FFmpegEditor.razor index b19b6e338..5eda50046 100644 --- a/ErsatzTV/Pages/FFmpegEditor.razor +++ b/ErsatzTV/Pages/FFmpegEditor.razor @@ -58,9 +58,9 @@ } - @* *@ - @* *@ - @* *@ + + + diff --git a/docker/Dockerfile b/docker/Dockerfile index 7d00f293a..a7e9fe1bf 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,6 @@ FROM mcr.microsoft.com/dotnet/aspnet:5.0-focal-amd64 AS dotnet-runtime -FROM linuxserver/ffmpeg:amd64-latest AS runtime-base +FROM jrottenberg/ffmpeg:4.3-ubuntu2004 AS runtime-base COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev tzdata @@ -37,5 +37,4 @@ FROM runtime-base WORKDIR /app EXPOSE 8409 COPY --from=build /app ./ -RUN usermod -a -G root abc -ENTRYPOINT ["/app/ErsatzTV"] +ENTRYPOINT ["./ErsatzTV"] diff --git a/docker/docker-compose.nvidia.yml b/docker/docker-compose.nvidia.yml index d68e23d74..68db314d0 100644 --- a/docker/docker-compose.nvidia.yml +++ b/docker/docker-compose.nvidia.yml @@ -3,8 +3,14 @@ services: ersatztv: privileged: true + build: + context: .. + dockerfile: docker/nvidia/Dockerfile + environment: + NVIDIA_VISIBLE_DEVICES: all + NVIDIA_DRIVER_CAPABILITIES: compute,utility,video deploy: resources: reservations: devices: - - capabilities: [ gpu ] + - capabilities: [ gpu ] diff --git a/docker/docker-compose.vaapi.yml b/docker/docker-compose.vaapi.yml index 59a313091..a00c42a51 100644 --- a/docker/docker-compose.vaapi.yml +++ b/docker/docker-compose.vaapi.yml @@ -2,5 +2,7 @@ services: ersatztv: + build: + dockerfile: docker/vaapi/Dockerfile devices: - /dev/dri/renderD128:/dev/dri/renderD128 diff --git a/docker/nvidia/Dockerfile b/docker/nvidia/Dockerfile new file mode 100644 index 000000000..e7625f9b5 --- /dev/null +++ b/docker/nvidia/Dockerfile @@ -0,0 +1,40 @@ +FROM mcr.microsoft.com/dotnet/aspnet:5.0-focal-amd64 AS dotnet-runtime + +FROM jrottenberg/ffmpeg:4.3-nvidia1804 AS runtime-base +COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet +RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev tzdata + +# https://hub.docker.com/_/microsoft-dotnet +FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build +RUN apt-get update && apt-get install -y ca-certificates +WORKDIR /source + +# copy csproj and restore as distinct layers +COPY *.sln . +COPY ErsatzTV/*.csproj ./ErsatzTV/ +COPY generated/ErsatzTV.Api.Sdk/src/ErsatzTV.Api.Sdk/*.csproj ./generated/ErsatzTV.Api.Sdk/src/ErsatzTV.Api.Sdk/ +COPY ErsatzTV.Application/*.csproj ./ErsatzTV.Application/ +COPY ErsatzTV.CommandLine/*.csproj ./ErsatzTV.CommandLine/ +COPY ErsatzTV.Core/*.csproj ./ErsatzTV.Core/ +COPY ErsatzTV.Core.Tests/*.csproj ./ErsatzTV.Core.Tests/ +COPY ErsatzTV.Infrastructure/*.csproj ./ErsatzTV.Infrastructure/ +RUN dotnet restore -r linux-x64 + +# copy everything else and build app +COPY ErsatzTV/. ./ErsatzTV/ +COPY generated/ErsatzTV.Api.Sdk/src/ErsatzTV.Api.Sdk/. ./generated/ErsatzTV.Api.Sdk/src/ErsatzTV.Api.Sdk/ +COPY ErsatzTV.Application/. ./ErsatzTV.Application/ +COPY ErsatzTV.CommandLine/. ./ErsatzTV.CommandLine/ +COPY ErsatzTV.Core/. ./ErsatzTV.Core/ +COPY ErsatzTV.Core.Tests/. ./ErsatzTV.Core.Tests/ +COPY ErsatzTV.Infrastructure/. ./ErsatzTV.Infrastructure/ +WORKDIR /source/ErsatzTV +ARG INFO_VERSION="unknown" +RUN dotnet publish -c release -o /app -r linux-x64 --self-contained false --no-restore /p:InformationalVersion=${INFO_VERSION} + +# final stage/image +FROM runtime-base +WORKDIR /app +EXPOSE 8409 +COPY --from=build /app ./ +ENTRYPOINT ["./ErsatzTV"] diff --git a/docker/vaapi/Dockerfile b/docker/vaapi/Dockerfile new file mode 100644 index 000000000..7dee22662 --- /dev/null +++ b/docker/vaapi/Dockerfile @@ -0,0 +1,40 @@ +FROM mcr.microsoft.com/dotnet/aspnet:5.0-focal-amd64 AS dotnet-runtime + +FROM jrottenberg/ffmpeg:4.3-vaapi2004 AS runtime-base +COPY --from=dotnet-runtime /usr/share/dotnet /usr/share/dotnet +RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y libicu-dev tzdata + +# https://hub.docker.com/_/microsoft-dotnet +FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build +RUN apt-get update && apt-get install -y ca-certificates +WORKDIR /source + +# copy csproj and restore as distinct layers +COPY *.sln . +COPY ErsatzTV/*.csproj ./ErsatzTV/ +COPY generated/ErsatzTV.Api.Sdk/src/ErsatzTV.Api.Sdk/*.csproj ./generated/ErsatzTV.Api.Sdk/src/ErsatzTV.Api.Sdk/ +COPY ErsatzTV.Application/*.csproj ./ErsatzTV.Application/ +COPY ErsatzTV.CommandLine/*.csproj ./ErsatzTV.CommandLine/ +COPY ErsatzTV.Core/*.csproj ./ErsatzTV.Core/ +COPY ErsatzTV.Core.Tests/*.csproj ./ErsatzTV.Core.Tests/ +COPY ErsatzTV.Infrastructure/*.csproj ./ErsatzTV.Infrastructure/ +RUN dotnet restore -r linux-x64 + +# copy everything else and build app +COPY ErsatzTV/. ./ErsatzTV/ +COPY generated/ErsatzTV.Api.Sdk/src/ErsatzTV.Api.Sdk/. ./generated/ErsatzTV.Api.Sdk/src/ErsatzTV.Api.Sdk/ +COPY ErsatzTV.Application/. ./ErsatzTV.Application/ +COPY ErsatzTV.CommandLine/. ./ErsatzTV.CommandLine/ +COPY ErsatzTV.Core/. ./ErsatzTV.Core/ +COPY ErsatzTV.Core.Tests/. ./ErsatzTV.Core.Tests/ +COPY ErsatzTV.Infrastructure/. ./ErsatzTV.Infrastructure/ +WORKDIR /source/ErsatzTV +ARG INFO_VERSION="unknown" +RUN dotnet publish -c release -o /app -r linux-x64 --self-contained false --no-restore /p:InformationalVersion=${INFO_VERSION} + +# final stage/image +FROM runtime-base +WORKDIR /app +EXPOSE 8409 +COPY --from=build /app ./ +ENTRYPOINT ["./ErsatzTV"]