diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 643028cf5..2ebedfcd6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,9 +4,8 @@ on: push: branches: - main - - develop jobs: - build: + build_and_test: runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -32,3 +31,81 @@ jobs: - name: Test run: dotnet test --no-restore --verbosity normal + build_and_push: + name: Build & Publish to Docker Hub + needs: build_and_test + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Extract Git Tag + shell: bash + run: | + tag=$(git describe --tags --abbrev=0) + tag2="${tag:1}" + short=$(git rev-parse --short HEAD) + final="${tag2/prealpha/$short}" + echo "GIT_TAG=${final}" >> $GITHUB_ENV + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Cache Docker layers + uses: actions/cache@v2.1.4 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Build and push base + uses: docker/build-push-action@v2 + with: + context: . + file: ./docker/Dockerfile + push: true + build-args: | + INFO_VERSION=${{ env.GIT_TAG }}-docker + tags: | + jasongdove/ersatztv:develop + jasongdove/ersatztv:${{ github.sha }}-develop + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache,mode=max + + - name: Build and push nvidia + uses: docker/build-push-action@v2 + with: + 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 }}-develop-nvidia + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache,mode=max + + - name: Build and push vaapi + uses: docker/build-push-action@v2 + with: + 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 }}-develop-vaapi + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache,mode=max diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 358ab1a22..128f57594 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -67,3 +67,80 @@ jobs: ErsatzTV*.tar.gz env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + build_and_push: + name: Build & Publish to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Extract Git Tag + shell: bash + run: | + tag=$(git describe --tags --abbrev=0) + echo "GIT_TAG=${tag:1}" >> $GITHUB_ENV + echo "DOCKER_TAG=${tag/-prealpha/}" >> $GITHUB_ENV + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Cache Docker layers + uses: actions/cache@v2.1.4 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Build and push base + uses: docker/build-push-action@v2 + with: + context: . + file: ./docker/Dockerfile + push: true + build-args: | + INFO_VERSION=${{ env.GIT_TAG }}-docker + tags: | + jasongdove/ersatztv:latest + jasongdove/ersatztv:${{ env.DOCKER_TAG }} + jasongdove/ersatztv:${{ github.sha }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache,mode=max + + - name: Build and push nvidia + uses: docker/build-push-action@v2 + with: + 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 + jasongdove/ersatztv:${{ github.sha }}-nvidia + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache,mode=max + + - name: Build and push vaapi + uses: docker/build-push-action@v2 + with: + 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 + jasongdove/ersatztv:${{ github.sha }}-vaapi + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache,mode=max diff --git a/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs b/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs index 218fb4817..bf22032e7 100644 --- a/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs +++ b/ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs @@ -10,6 +10,7 @@ using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.Repositories; using LanguageExt; using Microsoft.Extensions.Logging; +using static LanguageExt.Prelude; namespace ErsatzTV.Application.Streaming.Queries { @@ -68,15 +69,18 @@ namespace ErsatzTV.Application.Streaming.Queries playoutItem.StartOffset, now); }, - async () => + () => { if (channel.FFmpegProfile.Transcode) { - return _ffmpegProcessService.ForOfflineImage(ffmpegPath, channel); + return Right(_ffmpegProcessService.ForOfflineImage(ffmpegPath, channel)) + .AsTask(); } - return BaseError.New( - $"Unable to locate playout item for channel {channel.Number}; offline image is unavailable because transcoding is disabled in ffmpeg profile '{channel.FFmpegProfile.Name}'"); + var message = + $"Unable to locate playout item for channel {channel.Number}; offline image is unavailable because transcoding is disabled in ffmpeg profile '{channel.FFmpegProfile.Name}'"; + + return Left(BaseError.New(message)).AsTask(); }); } diff --git a/README.md b/README.md index 1532e8573..d871ba548 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Want to join the community or have a question? Join us on [Discord](https://disc - Channel-specific streaming mode (MPEG-TS or HLS) and transcoding settings - Collection-based scheduling, with collections containing television shows, seasons, episodes and movies - Powerful scheduling options such as chronological collection playback throughout the day or over multiple days +- [Hardware-accelerated transcoding](#Hardware Transcoding) options (QSV, NVENC, VAAPI) ## In Development @@ -53,6 +54,24 @@ docker run -d \ After running ErsatzTV for the first time, configure it by visiting the web UI at http://[address]:8409. +### Software Transcoding + +The following docker tags are available with software transcoding: + +* `develop` - merges to `main` branch +* `latest` - latest release + +### Hardware Transcoding + +The following docker tags are available with hardware-accelerated transcoding: + +* `develop-nvidia` - merges to `main` branch +* `develop-vaapi` - merges to `main` branch +* `latest-nvidia` - latest release +* `latest-vaapi` - latest release + +QSV transcoding has not been tested in docker. + ## Development See [development documentation](docs/development.md).