癒し系のアプリを長く運営していると、star が 1 つ落ちる理由の意外な上位に「音」が入ってきます。「就寝前に使ったら急に音が大きくて驚いた」「無音だと思ったら数秒後に鳴った」といった声は、機能のバグより静かに評価を削っていきます。
音のアセットは、コードのようにコンパイルエラーで気づけません。耳で全部を確かめるのは、曲数が増えるほど現実的でなくなります。6/26 の更新で Antigravity が IDE 内で音声ファイルを波形として描画できるようになったことで、この「耳の作業」を目とスクリプトに一部肩代わりさせる道が開けました。個人開発で音を扱ってきた立場から、公開前の音声チェックを検証ループとして仕組み化する設計を書いていきます。
音のアセットで実際に事故が起きるのはどこか
まず、どんな不具合が読者体験を壊すのかを具体的にしておきます。曖昧な「品質チェック」では、エージェントに任せても曖昧な結果しか返りません。
私が運用してきたなかで、クレームや低評価につながりやすかったのは次の四つでした。ラウドネス(体感音量)がトラック間でばらつくこと、ピークがクリップして歪むこと、冒頭に不自然な無音や逆に立ち上がりの唐突さがあること、そしてループ素材の末尾と先頭が滑らかにつながらないことです。
これらは波形を見れば多くが判別できます。逆に言えば、波形として可視化できる項目に落とし込めば、エージェントにも判断の足場を与えられます。
機械で判定できる部分は先に潰す
耳やエージェントに回す前に、数値で機械判定できるものは自動化しておきます。ここを省くと、レビューが主観のやり取りに埋もれます。私は ffprobe と ffmpeg の loudnorm 解析を使った軽いゲートを、公開前に必ず通しています。
#!/usr/bin/env bash
# audio-gate.sh — 公開前の音声アセットを機械判定する
# 使い方: ./audio-gate.sh assets/sounds/*.wav
set -euo pipefail
# 配信基準(自分のアプリに合わせて調整)
TARGET_LUFS=-16 # モバイル再生の目安
MAX_TP=-1.0 # トゥルーピーク上限 dBTP
MIN_SEC=1.0 # 短すぎる素材を弾く
MAX_HEAD_SILENCE=0.3 # 冒頭無音の許容秒数
for f in "$@"; do
# 長さ
dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$f")
# ラウドネスとトゥルーピークを loudnorm の解析パスで取得
stats=$(ffmpeg -i "$f" -af loudnorm=I=$TARGET_LUFS:TP=$MAX_TP:print_format=json -f null - 2>&1 \
| sed -n '/{/,/}/p')
lufs=$(echo "$stats" | python3 -c "import sys,json;print(json.load(sys.stdin)['input_i'])")
tp=$(echo "$stats" | python3 -c "import sys,json;print(json.load(sys.stdin)['input_tp'])")
# 冒頭無音の秒数(-50dB を無音とみなす)
head_sil=$(ffmpeg -i "$f" -af silencedetect=noise=-50dB:d=0.1 -f null - 2>&1 \
| grep -m1 "silence_end" | grep -oE "[0-9.]+" | head -1 || echo 0)
status="OK"
awk "BEGIN{exit !($dur < $MIN_SEC)}" && status="TOO_SHORT"
awk "BEGIN{exit !($tp > $MAX_TP)}" && status="CLIPPING"
awk "BEGIN{exit !($head_sil > $MAX_HEAD_SILENCE)}" && status="HEAD_SILENCE"
printf "%-28s dur=%.1fs LUFS=%s TP=%s headSil=%ss -> %s\n" \
"$(basename "$f")" "$dur" "$lufs" "$tp" "$head_sil" "$status"
doneこのスクリプトを通すだけで、「ある 1 曲だけ 6 dB 大きい」「末尾がクリップしている」といった、耳で聴き比べないと見つけにくい問題が一覧で出ます。私は AdMob の報酬音を差し替えたとき、この段でトゥルーピーク超過を拾い、配信前に直せました。実際、曲間の音量差が 6 dB(体感で約 2 倍の大きさ)あった素材も、この一覧で即座に見つかりました。