ffmpegをAWS Lambdaで動かしてみました
何を思ったかRubyのラッパー使ってみました
途中結構躓くことが多かったので面倒でした
Dockerfile
FROM lambci/lambda:build-ruby2.7
RUN gem install bundler -p
WORKDIR /var/task
RUN export TASK=/var/task
RUN mkdir ffmpeg_sources
RUN mkdir ffmpeg_dist
RUN mkdir bin
RUN yum install autoconf automake bzip2 bzip2-devel cmake freetype-devel gcc gcc-c++ git libtool make pkgconfig zlib-devel -y
RUN yum install -y libpng-devel
WORKDIR /var/task/ffmpeg_sources
RUN curl -O -L https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.bz2
RUN tar xjvf nasm-2.14.02.tar.bz2
WORKDIR nasm-2.14.02
RUN ./autogen.sh
RUN ./configure --prefix="$TASK/ffmpeg_build" --bindir="$TASK/bin"
RUN make
RUN make install
RUN
WORKDIR /var/task/ffmpeg_sources
RUN curl -O -L https://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
RUN tar xzvf yasm-1.3.0.tar.gz
WORKDIR yasm-1.3.0
RUN ./configure --prefix="$TASK/ffmpeg_build" --bindir="$TASK/bin"
RUN make
RUN make install
WORKDIR /var/task/ffmpeg_sources
RUN git clone --depth 1 https://code.videolan.org/videolan/x264.git
WORKDIR x264
RUN PKG_CONFIG_PATH="$TASK/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$TASK/ffmpeg_build" --bindir="$TASK/bin" --enable-static
RUN make
RUN make install
WORKDIR /var/task/ffmpeg_sources
RUN git clone https://bitbucket.org/multicoreware/x265_git.git
WORKDIR /var/task/ffmpeg_sources/x265_git/source
RUN cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$TASK/ffmpeg_build" -DENABLE_SHARED:bool=off .
RUN make
RUN make install
WORKDIR /var/task/ffmpeg_sources
RUN git clone --depth 1 https://github.com/mstorsjo/fdk-aac
WORKDIR fdk-aac
RUN autoreconf -fiv
RUN ./configure --prefix="$TASK/ffmpeg_build" --disable-shared
RUN make
RUN make install
WORKDIR /var/task/ffmpeg_sources
RUN curl -O -L https://downloads.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz
RUN tar xzvf lame-3.100.tar.gz
WORKDIR lame-3.100
RUN ./configure --prefix="$TASK/ffmpeg_build" --bindir="$TASK/bin" --disable-shared --enable-nasm
RUN make
RUN make install
WORKDIR /var/task/ffmpeg_sources
RUN curl -O -L https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz
RUN tar xzvf opus-1.3.1.tar.gz
WORKDIR opus-1.3.1
RUN ./configure --prefix="$TASK/ffmpeg_build" --disable-shared
RUN make
RUN make install
WORKDIR /var/task/ffmpeg_sources
RUN git clone --depth 1 https://chromium.googlesource.com/webm/libvpx.git
WORKDIR libvpx
RUN ./configure --prefix="$TASK/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm
RUN make
RUN make install
WORKDIR /var/task/ffmpeg_sources
RUN curl -O -L https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
RUN tar xjvf ffmpeg-snapshot.tar.bz2
WORKDIR ffmpeg
RUN PATH="$TASK/bin:$PATH" PKG_CONFIG_PATH="$TASK/ffmpeg_build/lib/pkgconfig" ./configure \
--prefix="$TASK/ffmpeg_build" \
--pkg-config-flags="--static" \
--extra-cflags="-I$TASK/ffmpeg_build/include" \
--extra-ldflags="-L$TASK/ffmpeg_build/lib" \
--extra-libs=-lpthread \
--extra-libs=-lm \
--bindir=../../ffmpeg_dist \
--enable-gpl \
--enable-libfdk_aac \
--enable-libfreetype \
--enable-libmp3lame \
--enable-libopus \
--enable-libvpx \
--enable-libx264 \
--enable-libx265 \
--enable-nonfree
RUN make
RUN make install
RUN chmod -R a+x ../../ffmpeg_dist
RUN mkdir /var/task/dist
RUN cp -r ../../ffmpeg_dist/* /var/task/dist
RUN yum install -y yum-utils rpmdevtools
WORKDIR /tmp
RUN yumdownloader unixODBC.x86_64 libtool-ltdl.x86_64 gnutls.x86_64 \
bzip2-libs.x86_64 freetype.x86_64 libpng.x86_64
RUN rpmdev-extract *rpm
RUN cp /tmp/*/usr/lib64/* /var/task/dist
WORKDIR /var/task/dist
COPY . .
RUN bundle config set --local path 'vendor/bundle'
RUN bundle install
RUN zip -r dist.zip .
RUN mkdir /var/task/output
CMD cp dist.zip /var/task/output
上のDockerfileと一緒のディレクトリにlambda_functionをおいて
docker build . -t lambda_ruby_ffmpeg
docker run -v "{PWD}":/var/task/output lambda_ruby_ffmpeg
でstreamio-ffmpegが使えます
githubの方にも上げておいたのでlambda_function.rbを編集してdocker上でビルドして走らせるだけでデプロイパッケージのzipが出てくると思います。
ただrequireはbundleに依存するので
require 'bundler'
Bundler.require
は忘れないでください。
それとバイナリにパスは通っていないはずなのでカレントディレクトリ(/var/task)にパスを通してください
躓いたところ
以下文体崩壊
--pathが古い
bundle install --path vendor/bundle
を実行したら--pathが古いといわれた。AWSの公式サンプルにも乗っていたのにそれでいいのかAmazon
RUN bundle config set --local path 'vendor/bundle'
ffmprobeの実行権限がないと言われた
windowsでzipファイルの作業してたらはまった。Lambdaのコンテナ上で圧縮しないと
実行権限の付与も忘れずに
RUN chmod -R a+x ../../ffmpeg_dist
x265のリポジトリがない
MercurialというGitに似たものがあったらしい(無知)。
これを見ればわかる通りffmpegの公式のビルド手順にもx265のビルドにはMercurialを使うように書かれているが、
公式(かどうかはわからないが)のx265のビルド方法を見てみると gitを使っていた。
Mercurialからgitに乗り換えるという歴史的な瞬間に立ち会ってしまった。
考えてみればGitもBitKeeperに触発それて作られているわけでほかにも分散型バージョン管理システムがあっても不思議じゃない。
AWSにせよなんにせよクラウドサービスの多くがgithubフレンドリーな姿勢になるほどGitはデファクトスタンダードになっているが、その一方で他の分散型バージョン管理システムのシェアを奪っているんだなあと寂寥感に苛まれた。
そして苦労して入れたところでおそらく使われない。
ffmpegで必要なライブラリ、例えばLameとかもgitで管理されているわけではなくsourceforgeで進められていて、tarボールをcurlするような形になっていて常に最新のバージョンをとってこられるよう指定できない。そう考えたらgitもMercurialもいい感じなのになあ。
* .so. * エラー
「2021年までにモバイルトラフィックの80%は動画で占められます」
https://media.kaizenplatform.com/n/n51e413c8087c
これほどまでに動画は我々の世界に身近になったけれど、動画を再生するまでに何があるのか知っている人はほとんどいない
ffmpegはビルドすると30MBほどになる巨大なプログラムだが、動かすにはまだ足りない。
これらの
START RequestId: 51a2ee5f-3cfc-4647-a1cf-58096076e7b6 Version: $LATEST
ffprobe: error while loading shared libraries: libbz2.so.1: cannot open shared object file: No such file or directory
END RequestId: 51a2ee5f-3cfc-4647-a1cf-58096076e7b6
REPORT RequestId: 51a2ee5f-3cfc-4647-a1cf-58096076e7b6 Duration: 2024.82 ms Billed Duration: 2100 ms Memory Size: 128 MB Max Memory Used: 111 MB Init Duration: 748.18 ms
RequestId: 51a2ee5f-3cfc-4647-a1cf-58096076e7b6 Error: Runtime exited with error: exit status 127
Runtime.ExitError
START RequestId: 47eaba0a-f985-4103-a452-935a78e4e6e1 Version: $LATEST
ffprobe: error while loading shared libraries: libpng15.so.15: cannot open shared object file: No such file or directory
END RequestId: 47eaba0a-f985-4103-a452-935a78e4e6e1
REPORT RequestId: 47eaba0a-f985-4103-a452-935a78e4e6e1 Duration: 2530.37 ms Billed Duration: 2600 ms Memory Size: 128 MB Max Memory Used: 128 MB Init Duration: 887.27 ms
RequestId: 47eaba0a-f985-4103-a452-935a78e4e6e1 Error: Runtime exited with error: exit status 127
Runtime.ExitError
エラーメッセージは実行しようとしたときに必要になった共通ライブラリ。lambdaで実行するにはこれらを含めなければならなかった。
つくづく動画をデジタル信号に変えるのはあらゆる処理が必要なのだなと感じた。