この記事の目的
Azure Function のアプリで FFmpeg を使えるようにする
背景
個人開発しているアプリが音声ファイルを扱うもので、ライブラリが FFmpeg を必要としていた。
Azure Functions Core Tools でのローカル開発時には exe インストールするだけで済んだが、Azure Functions にデプロイするにあたって当然 function にも FFmpeg を仕込まないといけない。そのためどうやって使えるようにするか試行錯誤した。
当初 Docker コンテナーイメージを作成して Azure Functions にデプロイしていたものの (後述)、アプリを改修するたびのビルド&デプロイにものすごく時間がかかり、辟易していた。
後に GitHub Actions での CI/CD の手軽さを知ってしまったので、脱 Docker する方法を模索した。
解決方法
- Azure ストレージのファイル共有に FFmpeg のバイナリファイルを配置する
- Function Appにストレージのファイル共有をマウントする
- Function のコードで FFmpeg の PATH を通す
シンプル。
実は 依存関係とサードパーティ製ライブラリを Azure Functions に取り込む | Microsoft Learn で紹介されている。(全く気付かなかった)
実装
以下の説明では Python v2 モデルを使用しています。
Azure ストレージのファイル共有に FFmpeg のバイナリファイルを配置する
-
FFmpeg 公式 > [Download] > Linux Static Builds > [32-bit and 64-bit for kernel 3.2.0 and above] からバイナリファイルをダウンロード
- ffmpeg-git-amd64-static.tar.xz については動作確認済み
- 任意の Azure ストレージにファイル共有を作成しておく
- ストレージアカウントは Premium Files でなく Standard v2 のものでOK
- ダウンロードした tar.xz を解凍し、中のファイルをファイル共有に配置する
ここでは fs01 というファイル共有に ffmpeg ディレクトリを作成し、その中に配置している
バイナリファイルは ffmpeg と ffprobe の両方を配置する必要があります。
Function App にストレージのファイル共有をマウントする
Azure CLI でマウントを実行(Windows での例)
- Azure PowerShell にも同様のコマンドは用意されている(New-AzWebAppAzureStoragePath)
$resourceGroup = "リソースグループ名"
$functionApp = "Function App 名"
$shareId = "任意の文字列 (複数のファイル共有をマウントした時に一意であればOK)"
$share = "ファイル共有名"
$mountPath = "任意のマウントパス"
$AZURE_STORAGE_ACCOUNT = "ストレージアカウント名"
$AZURE_STORAGE_KEY = "ストレージアカウントキー"
az webapp config storage-account add `
--resource-group $resourceGroup `
--name $functionApp `
--custom-id $shareId `
--storage-type AzureFiles `
--share-name $share `
--mount-path $mountPath `
--account-name $AZURE_STORAGE_ACCOUNT `
--access-key $AZURE_STORAGE_KEY
実行結果は az webapp config storage-account list
で確認できる
マウントしたファイル共有は Function App のコンテナーから確認できる(= /st01fs01)
- ffmpeg ディレクトリ下に ffmpeg, ffprobe を確認できる
ファイル共有は Kudu サービス(アプリとは別コンテナー)からも確認できる
実はマウント操作は Azure ポータルからも設定できる
(追記 Flex Consumption のものではできない? App Service plan と通常の Consumption では確認済み)
Function のコードで FFmpeg の PATH を通す
ドキュメントではマウントパスを直接参照する方法は紹介されているものの、やりたいのは PATH を通すこと(= ライブラリに FFmpeg を使わせたい)
マウントパスを Azure Functions の環境変数として設定
PATH にマウントパスを追記する(プログラム内でのみ PATH を通させる)
FFMPEG_PATH = os.getenv("ffmpeg_path")
# 本番環境の Azure Functions でのみ実行
# プログラム内でのみ環境変数を上書きして PATH を通す
if PY_ENV == "production":
os.environ["PATH"] = os.environ["PATH"] + os.pathsep + FFMPEG_PATH
else:
pass
これで各ライブラリが FFmpeg を使えるようになる。
補足(Docker での実装パターン)
上記一切のマウント作業をせずとも、Docker コンテナーイメージでも実行環境を作れる。
ビルド時に apt-get install -y ffmpeg
させるだけ。
ただし先述の通りビルド&デプロイにものすごい時間がかかることがある。
当然コンテナーなので動作の確実性は高い。安定性を重視するならこちらでも全然アリ。
FROM mcr.microsoft.com/azure-functions/python:4-python3.11-appservice
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
RUN apt-get update && \
apt-get install -y ffmpeg && \
rm -rf /var/lib/apt/lists/*
COPY requirements.txt /
RUN python -m pip install --upgrade pip && \
python -m pip install -r /requirements.txt
COPY . /home/site/wwwroot
上記の Dockerfile は func init --docker-only
で生成できるもので、コンテナーイメージだけ SSH 対応版に変更しています。
使用できるイメージは Microsoft 公式リポジトリ で確認できます。
参考リンク
Microsoft Learn 公式ドキュメント
- Azure Functions のストレージに関する考慮事項 | Microsoft Learn
- ファイル共有を Python Function App にマウントする - Azure CLI | Microsoft Learn
- az webapp config storage-account | Microsoft Learn
- 依存関係とサードパーティ製ライブラリを Azure Functions に取り込む | Microsoft Learn