FFmpegのビルド&インストール

# FFmpegのビルド

関連モジュールも含めてFFmpegをソースからビルドするのはなかなか困難ですが、AnsibleのPlaybookにまとまったのでここにあげておきます。

FFmpegのバージョンは**4.1**です。
FFmpegのコンパイルオプションは以下に対応しています。
--enable-libaom
--enable-libfdk_aac
--enable-libfreetype
--enable-libmp3lame
--enable-libopus
--enable-libvorbis
--enable-libvpx
--enable-libx264
--enable-libx265

# 対象OS
対象OSは**CentOS7**、**Ubuntu18**です。
PlaybookはどちらのOSに対しても共通して使用できます。

Vagrantの「centos/7」「ubuntu/bionic64」ボックスで検証済みです。

# Playbook
「vars/main.yml」に定義値を設定します。

```
#
# Basic configuration
#
# Compile directory
ffmpeg_version: "4.1"
ffmpeg_dir: "/usr/local/src/ffmpeg-{{ ffmpeg_version }}"
ffmpeg_src_dir: "{{ ffmpeg_dir }}/ffmpeg_sources"
ffmpeg_build_dir: "{{ ffmpeg_dir }}/ffmpeg_build"
ffmpeg_bin_dir: "{{ ffmpeg_build_dir }}/bin"

# Tool bin dir
tool_bin_dir: "/usr/local/bin"

# library version
freetype_version: "2.9.1"
nasm_version: "2.14rc16"
yasm_version: "1.3.0"
libmp3lame_version: "3.100"
libogg_version: "1.3.3"
libvorbis_version: "1.3.6"

```

Playbookです。

```
---
- name: Compile FFMpeg from sources
  include_vars: "vars/main.yml"
  
- name: Install base library for CentOS by yum
  yum:
    name:
      - git
      - wget
      - autoconf
      - automake
      - gcc
      - gcc-c++
      - libtool
      - make
      - cmake3
      - mercurial
      - pkgconfig
      - zlib-devel
  when: ansible_os_family == 'RedHat'
- name: Install base library for Ubuntu by apt
  apt:
    name:
      - git
      - wget
      - autoconf
      - automake
      - build-essential
      - libtool
      - cmake
      - mercurial
      - pkg-config
      - zlib1g-dev
  when: ansible_os_family == 'Debian'
  
- name: Make cmake symbolic link
  file:
    src: /usr/bin/cmake3
    dest: /usr/bin/cmake
    state: link
  when: ansible_os_family == 'RedHat'

- name: Create FFmpeg directory
  file: path="{{ item }}" state=directory owner=root group=root mode=0755
  with_items:
    - "{{ ffmpeg_src_dir }}"
    - "{{ ffmpeg_build_dir }}"
    - "{{ ffmpeg_bin_dir }}"

### TOOL INSTALL ###
- name: Download and Extract NASM gzip archive
  unarchive:
    src: "https://www.nasm.us/pub/nasm/releasebuilds/{{ nasm_version }}/nasm-{{ nasm_version }}.tar.gz"
    dest: "{{ ffmpeg_src_dir }}"
    remote_src: yes
- name: Compile NASM
  shell: >-
    ./configure --prefix="{{ ffmpeg_build_dir }}" --bindir="{{ tool_bin_dir }}" &&
    make
    chdir="{{ ffmpeg_src_dir }}/nasm-{{ nasm_version }}"
- name: Install NASM
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/nasm-{{ nasm_version }}"

- name: Download and Extract Yasm gzip archive
  unarchive:
    src: "https://www.tortall.net/projects/yasm/releases/yasm-{{ yasm_version }}.tar.gz"
    dest: "{{ ffmpeg_src_dir }}"
    remote_src: yes
- name: Compile Yasm
  shell: >-
    ./configure --prefix="{{ ffmpeg_build_dir }}" --bindir="{{ tool_bin_dir }}" &&
    make
    chdir="{{ ffmpeg_src_dir }}/yasm-{{ yasm_version }}"
- name: Install Yasm
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/yasm-{{ yasm_version }}"
    
### BASE LIBRARY BUILD ###
- name: Download and Extract Freetype archive
  unarchive:
    src: "http://jaist.dl.sourceforge.net/sourceforge/freetype/freetype-{{ freetype_version }}.tar.gz"
    dest: "{{ ffmpeg_src_dir }}"
    remote_src: yes
- name: Compile Freetype
  shell: >-
    ./configure --prefix="{{ ffmpeg_build_dir }}" --disable-shared &&
    make
    chdir="{{ ffmpeg_src_dir }}/freetype-{{ freetype_version }}"
- name: Install Freetype
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/freetype-{{ freetype_version }}"

### LIBRARY INSTALL ###
- name: Download and Extract libx264 archive
  git:
    repo: "git://git.videolan.org/x264"
    dest: "{{ ffmpeg_src_dir }}/x264"
- name: Compile libx264 for CentOS
  shell: >-
    PKG_CONFIG_PATH="{{ ffmpeg_build_dir }}/lib/pkgconfig" &&
    ./configure --prefix="{{ ffmpeg_build_dir }}" --bindir="{{ ffmpeg_bin_dir }}" --enable-static &&
    make
    chdir="{{ ffmpeg_src_dir }}/x264"
  # compiling libx264 needs NASM command
  environment:
    PATH: "{{ tool_bin_dir }}:{{ ansible_env.PATH }}"
  when: ansible_os_family == 'RedHat'
- name: Compile libx264 for Ubuntu
  shell: >-
    PKG_CONFIG_PATH="{{ ffmpeg_build_dir }}/lib/pkgconfig" &&
    ./configure --prefix="{{ ffmpeg_build_dir }}" --bindir="{{ ffmpeg_bin_dir }}" --enable-static --enable-pic &&
    make
    chdir="{{ ffmpeg_src_dir }}/x264"
  # compiling libx264 needs NASM command
  environment:
    PATH: "{{ tool_bin_dir }}:{{ ansible_env.PATH }}"
  when: ansible_os_family == 'Debian'
- name: Install libx264
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/x264"

- name: Download and Extract libx265 archive
  hg:
    repo: "https://bitbucket.org/multicoreware/x265"
    dest: "{{ ffmpeg_src_dir }}/x265"
- name: Compile libx265
  shell: >-
    cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="{{ ffmpeg_build_dir }}" -DENABLE_SHARED=off ../../source &&
    make
    chdir="{{ ffmpeg_src_dir }}/x265/build/linux"
- name: Install libx265
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/x265/build/linux"

- name: Download and Extract libfdk_aac archive
  git:
    repo: "git://git.code.sf.net/p/opencore-amr/fdk-aac"
    dest: "{{ ffmpeg_src_dir }}/fdk-aac"
- name: Compile libfdk_aac
  shell: >-
    autoreconf -fiv &&
    ./configure --prefix="{{ ffmpeg_build_dir }}" --disable-shared &&
    make
    chdir="{{ ffmpeg_src_dir }}/fdk-aac"
- name: Install libfdk_aac
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/fdk-aac"

- name: Download and Extract libmp3lame archive
  unarchive:
    src: "http://downloads.sourceforge.net/project/lame/lame/{{ libmp3lame_version }}/lame-{{ libmp3lame_version }}.tar.gz"
    dest: "{{ ffmpeg_src_dir }}"
    remote_src: yes
- name: Compile libmp3lame
  shell: >-
    ./configure --prefix="{{ ffmpeg_build_dir }}" --bindir="{{ ffmpeg_bin_dir }}" --disable-shared --enable-nasm &&
    make
    chdir="{{ ffmpeg_src_dir }}/lame-{{ libmp3lame_version }}"
- name: Install libmp3lame
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/lame-{{ libmp3lame_version }}"

- name: Download and Extract libopus archive
  git:
    repo: "http://git.opus-codec.org/opus.git"
    dest: "{{ ffmpeg_src_dir }}/opus"
- name: Compile libopus
  shell: >-
    autoreconf -fiv &&
    ./configure --prefix="{{ ffmpeg_build_dir }}" --disable-shared &&
    make
    chdir="{{ ffmpeg_src_dir }}/opus"
- name: Install libopus
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/opus"
    
- name: Download and Extract libogg archive
  unarchive:
    src: "https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-{{ libogg_version }}.tar.gz"
    dest: "{{ ffmpeg_src_dir }}"
    remote_src: yes
- name: Compile libogg
  shell: >-
    ./configure --prefix="{{ ffmpeg_build_dir }}" --disable-shared &&
    make
    chdir="{{ ffmpeg_src_dir }}/libogg-{{ libogg_version }}"
- name: Install libogg
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/libogg-{{ libogg_version }}"

- name: Download and Extract libvorbis archive
  unarchive:
    src: "https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-{{ libvorbis_version }}.tar.gz"
    dest: "{{ ffmpeg_src_dir }}"
    remote_src: yes
- name: Compile libvorbis
  shell: >-
    LDFLAGS="-L{{ ffmpeg_build_dir }}/lib" &&
    CPPFLAGS="-I{{ ffmpeg_build_dir }}/include" &&
    ./configure --prefix="{{ ffmpeg_build_dir }}" --with-ogg="{{ ffmpeg_build_dir }}" --disable-shared &&
    make
    chdir="{{ ffmpeg_src_dir }}/libvorbis-{{ libvorbis_version }}"
- name: Install libvorbis
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/libvorbis-{{ libvorbis_version }}"

- name: Download and Extract libvpx archive
  git:
    repo: "https://chromium.googlesource.com/webm/libvpx.git"
    dest: "{{ ffmpeg_src_dir }}/libvpx"
- name: Compile libvpx
  shell: >-
    ./configure --prefix="{{ ffmpeg_build_dir }}" &&
    make
    chdir="{{ ffmpeg_src_dir }}/libvpx"
  # compiling libvpx needs NASM command
  environment:
    PATH: "{{ tool_bin_dir }}:{{ ansible_env.PATH }}"
- name: Install libvpx
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/libvpx"

- name: Download and Extract libaom archive
  git:
    repo: "https://aomedia.googlesource.com/aom"
    dest: "{{ ffmpeg_src_dir }}/aom"
- name: Create libaom directory
  file: path="{{ item }}" state=directory owner=root group=root mode=0755
  with_items:
    - "{{ ffmpeg_src_dir }}/aom/build"
- name: Compile libaom
  shell: >-
    cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="{{ ffmpeg_build_dir }}" -DENABLE_SHARED=off -DENABLE_NASM=on ../ &&
    make
    chdir="{{ ffmpeg_src_dir }}/aom/build"
- name: Install libaom
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/aom/build"

### FFmpeg BUILD ###
- name: Download and Extract FFmpeg archive
  unarchive:
    src: "https://ffmpeg.org/releases/ffmpeg-{{ ffmpeg_version }}.tar.gz"
    dest: "{{ ffmpeg_src_dir }}"
    remote_src: yes
- name: Compile FFmpeg
  shell: >-
    ./configure --prefix="{{ ffmpeg_build_dir }}" --extra-cflags="-I{{ ffmpeg_build_dir }}/include" --extra-ldflags="-L{{ ffmpeg_build_dir }}/lib" --extra-libs="-lpthread -lm" --bindir="{{ tool_bin_dir }}" --pkg-config-flags="--static" --enable-gpl --enable-nonfree --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libaom &&
    make
    chdir="{{ ffmpeg_src_dir }}/ffmpeg-{{ ffmpeg_version }}"
  # compiling FFmpeg needs NASM command
  environment:
    PATH: "{{ tool_bin_dir }}:{{ ansible_env.PATH }}"
    PKG_CONFIG_PATH: "{{ ffmpeg_build_dir }}/lib/pkgconfig:{{ ffmpeg_build_dir }}/lib64/pkgconfig"
- name: Install FFmpeg
  shell: >-
    make install
    chdir="{{ ffmpeg_src_dir }}/ffmpeg-{{ ffmpeg_version }}"

```

# 動作確認
正常にインストール完了すると、ffmpegコマンドが使用可能になります。

```
[root@localhost ~]# ffmpeg -version
ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-36)
configuration: --prefix=/usr/local/src/ffmpeg-4.1/ffmpeg_build --extra-cflags=-I/usr/local/src/ffmpeg-4.1/ffmpeg_build/include --extra-ldflags=-L/usr/local/src/ffmpeg-4.1/ffmpeg_build/lib --extra-libs='-lpthread -lm' --bindir=/usr/local/bin --pkg-config-flags=--static --enable-gpl --enable-nonfree --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libaom
libavutil      56. 22.100 / 56. 22.100
libavcodec     58. 35.100 / 58. 35.100
libavformat    58. 20.100 / 58. 20.100
libavdevice    58.  5.100 / 58.  5.100
libavfilter     7. 40.101 /  7. 40.101
libswscale      5.  3.100 /  5.  3.100
libswresample   3.  3.100 /  3.  3.100
libpostproc    55.  3.100 / 55.  3.100

```

# うまくいかない場合は
ビルドの途中で以下のように異常終了することがあります。その場合は最初から作業をやり直します。

特にlibx265のコンパイルには多量のメモリを使うのでメモリは十分用意しておきます。
Vagrant環境の場合のデフォルト値の**1Gバイト**メモリでは、Ubuntu18でlibx265が異常終了することがあります。

関連ソースをダウンロードする箇所で取得先のサーバがダウンしている場合などで異常終了することがあります。

止まっているように見える場合は**処理中**なのでコンソールが返ってくるまで待ちます。

# ソースコード
ロールにまとめた実際のソースコードはこちらから参照できます。

https://github.com/czbone/oneliner-env