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"]