Hori Blog

フリーランスでバックエンドエンジニアとして活動している Ryota Hori のブログです。
最近はテック系記事より雑記ブログ気味。

eyecatch image of デジタル時計を載せた生放送を FFmpeg だけで実現する

デジタル時計を載せた生放送を FFmpeg だけで実現する

生放送の遅延確認で現在時刻を載せた配信が欲しかったので作成。ついでに Docker Image 化もしてみました。

経緯

担当している某生放送サービスにて、遅延の確認や開発のために流しっぱなしの時刻つき配信が欲しかったので整備してみました。

OBS に時計を表示させれば簡単だったのですが、パブリックドメインで軽量な時計ツールが意外と無かったのと、実 PC での配信だとスケールしづらい上に何かとめんどくさいので Docker 化して自動配信にしたかったのが動機です。

最終的にはこんな感じで動画上に時計を表示させることに成功。

result

時計部分は FFmpeg のフィルタで合成しているので、見た目やフォントは好きなようにカスタマイズできます。

構成

file-list
Dockerfile
NotoSans-Bold.ttf
src.mp4
start.sh*

Font と MP4 はライセンス的に問題ないものを拝借。

スクリプト

start.sh

Dockerfile の ENTRYPOINT に直接コマンドを書くとややこしくなるのと、スクリプトを直接叩いてデバッグしたかったので実行コマンドを別スクリプトにしました。

start.sh
#!/bin/bash

ffmpeg -re -stream_loop -1 -i 'src.mp4' -vf "drawtext=fontfile=./NotoSans-Bold.ttf: text='%{localtime\:%F%n%n%T}': fontcolor=black@0.8:fontsize=64: x=32: y=32" -vcodec libx264 -x264-params keyint=30 -acodec aac -f flv "${TARGET_RTMP_URL}"

FFmpeg での配信コマンドについては以下の記事でも紹介してあります。

テスト用の自動配信環境を Docker と FFmpeg で構築してみる | CyberAgent Developers Blog | サイバーエージェント デベロッパーズブログ

ざっくりオプションの説明をすると、

  • -re
    • 入力動画のフレームレート速度でファイルを読み込むオプション
    • つけない場合はエンコードで処理できるスピードをそのまま出力スピードに使ってしまうので、たとえば 2 倍速でエンコードできる場合、配信が 2 倍速の動画になってしまう
  • -stream_loop 1
    • 入力ソースを無限ループさせるオプション
  • -i 'src.mp4'
    • 入力ソースの指定
  • -vf
    • ビデオフィルタ
    • 複数のフィルタを : 区切りで指定できる
  • drawtext=fontfile=./NotoSans-Bold.ttf
    • フォントファイルの指定
  • text='%{localtime\:%F%n%n%T}'
    • 今回の肝になる時計部分。
    • strtime のフォーマットで指定できる。
    • %F : ハイフン区切りの年月日
    • %n : 改行
    • %T : : 区切りの時分秒
  • fontcolor=black@0.8
    • 字の色
    • @0.8 はアルファ値(透過)。 1 が透過なし。 0 が透明。
  • fontsize=64
    • フォントサイズ
  • x=32
    • 表示位置(横)
  • y=32
    • 表示位置(縦)
  • -vcodec libx264 -x264-params keyint=30
    • ビデオコーデックの指定
    • 今回は配信サービスの都合上、 H264Keyframe Interval30 にした。
  • -acodec aac
    • 音声コーデックを AAC にした
  • -f flv
    • 出力フォーマットの指定
    • 今回は RTMP での配信をするため flv 指定
  • "${TARGET_RTMP_URL}"
    • 出力先の指定
    • 今回は変数にしたので、配信サービスの RTMP 出力先 URL を指定する
    • rtmp://hogehoge.com/hogehoge:1935 みたいな
    • Docker 化した場合は -e オプションで -e 'TARGET_RTMP_URL=rtmp://hogehoge.com/hogehoge:1935' で指定できる

Dockerfile

Dockerfile
FROM horiryota/ffmpeg

COPY src.mp4 ./
COPY start.sh ./
COPY NotoSans-Bold.ttf ./

ENTRYPOINT ["/bin/sh", "./start.sh"]

Dockerfile は COPY して start.sh を叩くだけです。

ちなみに FFmpeg の Docker Image は jrottenberg/ffmpeg をお借りしようと思いましたが、時計を表示するための drawtext フィルタを使うのに必要なビルドオプション --enable-libfreetype が設定されていなかったので自分で用意。

FFmpeg の Dockerfile は以下。

Dockerfile
FROM gliderlabs/alpine:3.4

ENV TZ="JST-9"

ENV FFMPEG_VERSION=3.2.4

RUN \
      apk update && \

      apk add --no-cache \
      freetype-dev \
      openssl-dev \
      rtmpdump-dev \
      x264-dev \
      yasm-dev \
      zlib-dev \
      && \

      apk add --no-cache --virtual=build-dependencies \
      build-base \
      curl \
      nasm \
      tar \
      bzip2 \
      && \

      DIR=$(mktemp -d) && cd ${DIR} && \

      wget http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz -O - | tar zxvf - -C . && \
      cd ffmpeg-${FFMPEG_VERSION} && \
      ./configure \

      --enable-gpl \
      --enable-version3 \
      --enable-nonfree \

      --enable-small \

      --disable-ffplay \
      --disable-ffserver \

      --disable-doc \
      --disable-htmlpages \
      --disable-manpages \
      --disable-podpages \
      --disable-txtpages \

      --enable-libx264 \
      --enable-postproc \
      --enable-avresample \
      --enable-libfreetype \
      --enable-openssl \
      --disable-debug \
      && \

      make && \
      make install && \
      make distclean && \

      rm -rf ${DIR} && \
      apk del build-dependencies && \
      rm -rf /var/cache/apk/*

使い方

Doker Image なので以下のようなコマンドで配信できるはず。

docker run -e 'TARGET_RTMP_URL=rtmp://hogehoge.com/hogehoge:1935' horiryota/auto-broadcast

以上

とりあえず配信しっぱなしにはできたので、 CPU などのリソース表示や fps 、 bitrate などの配信状態表示にも挑戦してみたいところ。

FFmpeg はオプションが多くて全然把握しきれないので、覚えたものからメモっていきたい。