NVEncを利用したEPGStationのハードウェアエンコード環境


これまでの録画環境と変更点

以前はIntel の内蔵GPU(iGPU)のVAAPIを利用していたのですが、GPUの追加(RTX2060)に伴いNVEncを利用したエンコード設定に変更しました。設定にあたってはEPGStationのDockerイメージ内にffmpegをインストールするのが一般的ですが、手順やビルドが非常に煩雑なため、NVEncが付属したffmpegコマンドが実行できるDockerイメージを作り、EPGStationからDockerコマンドで実行するような方針で構成してみました。
5ヶ月経過現在、エンコード時400FPS・GPU使用率15%・CPU使用率1%くらいの運用で安定しています。

ミドルウェア
OS ubuntu20.04
docker 19.03.8
docker-compose 1.26.0
nvidia-docker 2.5.0
NVIDIA-SMI 460.73.01 / Driver Version: 460.73.01 / CUDA Version: 11.2

ハードウェア
M/B PRIME H310M-E R2.0
GPU RTX2060
CPU i7-9700F

設定にあたっての前提
Dockerコマンド、docker-composeコマンド、nvidia-dockerコマンドが利用できること、Docker-mirakurun-EPGStationを利用していること

2021/10/16 追記 最近、旧手順でビルドしなおしたところ、以下のようなエラーが出て困ったため、より簡単な手順を追記しました。古い手順は自身でビルドしたい方向けに記事の最後におまけとして残していますので必要に応じて参考にしてください。 > Driver does not support the required nvenc API version. Required: 11.1 Found: 11.0

設定方法

epgstationサービス内からDockerコマンドが扱えるように、docker-compose.ymlファイルに以下1行を追記します。#追加のコメント箇所が追加した行です。

docker-compose.yml
    epgstation:
        build: epgstation
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - ./epgstation/config:/app/config
            - ./epgstation/data:/app/data
            - ./epgstation/thumbnail:/app/thumbnail
            - ./epgstation/logs:/app/logs
            - ./recorded:/app/recorded
            - /var/run/docker.sock:/var/run/docker.sock # 追加
        environment:
            TZ: "Asia/Tokyo"
        depends_on:
            - mirakurun
            - mysql
        ports:
            - "8888:8888"
            - "8889:8889"
        restart: always
        privileged: true # 追加

エンコードスクリプトを追加します。以下のファイルをepgstation/configのディレクトリに作成します。スクリプト中、<ホスト側録画ディレクトリ>と書いてある箇所にはコンテナ内/app/recordedのホスト側ディレクトリの絶対パスを指定してください。上のdocker-compose.ymlの設定だと、<docker-compose.ymlの絶対ディレクトリ>/recorded になるでしょう。

epgstation/config/enc_nvenc.sh
#!/bin/bash

img=jrottenberg/ffmpeg:4.3-nvidia1804
ffmpeg_cmd="docker run --rm --gpus all -u`id -u`:`id -g` -v <ホスト側録画ディレクトリ>:/app/recorded $img"
$ffmpeg_cmd -c:v mpeg2_cuvid -deint adaptive -drop_second_field 1 -i "$INPUT" -c:v h264_nvenc -vb 3M -rc vbr_hq -c:a aac -b:a 192k -r:a 48000 -ac 2 "$OUTPUT"

最後にエンコードオプションを追加します。#追加コメントは誤動作の原因になるので消しておいてください。

epgstation/config/config.yml
# 省略
encode:
    - name: H.264
      cmd: '%NODE% %ROOT%/config/enc.js'
      suffix: .mp4
      rate: 4.0
    - name: H264/nvenc                            # 追加
      cmd: /bin/bash %ROOT%/config/enc_nvenc.sh   # 追加
      suffix: .mp4                                # 追加

動作確認

EPGStationを開き、オプションが表示されていればエンコードしてみましょう。多分問題なく動作すると思います。

参考

おまけ(自分でビルドする場合)

本手順は非推奨です

nvcc付属のffmpegのDockerfileを提供してくれている方がいるのでまずは雛形としてダウンロードします。Docker-mirakurun-EPGStationのdocker-compose.ymlと同じディレクトリで以下のコマンドを実行しリポジトリをクローンしてきます。

git clone https://github.com/myoshimi/ffmpeg-nvenc.git

epgstationサービス内からDockerコマンドが扱えるように、docker-compose.ymlファイルを以下のように修正します。#追加のコメント箇所が追加した行です。

docker-compose.yml
    ffmpeg-nvenc:              # 追加
         build: ffmpeg-nvenc   # 追加
         image: ffmpeg-nvenc   # 追加
    epgstation:
        build: epgstation
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - ./epgstation/config:/app/config
            - ./epgstation/data:/app/data
            - ./epgstation/thumbnail:/app/thumbnail
            - ./epgstation/logs:/app/logs
            - ./recorded:/app/recorded
            - /var/run/docker.sock:/var/run/docker.sock # 追加
        environment:
            TZ: "Asia/Tokyo"
        depends_on:
            - mirakurun
            - mysql
        ports:
            - "8888:8888"
            - "8889:8889"
        restart: always
        privileged: true # 追加

エンコードスクリプトを追加します。以下のファイルをepgstation/configのディレクトリに作成します。スクリプト中、<ホスト側録画ディレクトリ>と書いてある箇所にはコンテナ内/app/recordedのホスト側ディレクトリの絶対パスを指定してください。上のdocker-compose.ymlの設定だと、<docker-compose.ymlの絶対ディレクトリ>/recorded になるでしょう。

epgstation/config/enc_nvenc.sh
#!/bin/bash

img=ffmpeg-nvenc
ffmpeg_cmd="docker run --rm --gpus all -u`id -u`:`id -g` -v <ホスト側録画ディレクトリ>:/app/recorded $img"
$ffmpeg_cmd -c:v mpeg2_cuvid -deint adaptive -drop_second_field 1 -i "$INPUT" -c:v h264_nvenc -vb 3M -rc vbr_hq -c:a aac -b:a 192k -r:a 48000 -ac 2 "$OUTPUT"

最後にエンコードオプションを追加します。#追加コメントは誤動作の原因になるので消しておいてください。

epgstation/config/config.yml
# 省略
encode:
    - name: H.264
      cmd: '%NODE% %ROOT%/config/enc.js'
      suffix: .mp4
      rate: 4.0
    - name: H264/nvenc                            # 追加
      cmd: /bin/bash %ROOT%/config/enc_nvenc.sh   # 追加
      suffix: .mp4                                # 追加

コンテナを再起動しておきます。この時にffmpeg-nvencのビルドが走るはずです。

docker-compose down
docker-compose up -d