magicciv/scripts/run/audio.sh

162 lines
5.3 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Audio subcommands — sourcing pipeline + design app DX.
#
# The launch-pack assets are sourced via per-pack TSV mappings under
# `tools/audio-batch-*.tsv`. Each row goes:
# curl → ffmpeg loudnorm + Ogg Vorbis encode → write to assets tree →
# append `sources.csv` → re-render LICENSES.md → run audio-validate.py.
# Idempotent: re-running skips files already on disk + already in the
# ledger.
#
# ./run audio show status (file count, manifest health)
# ./run audio:fetch run every batch in tools/audio-batch-*.tsv
# ./run audio:fetch:01 run a single numbered batch (01/02/03/04)
# ./run audio:design start the design-app dev server (port 7777)
# ./run audio:validate python3 tools/audio-validate.py
# ./run audio:render regenerate LICENSES.md from sources.csv
#
# `./run validate` (in test.sh) already calls audio-validate.py +
# audio-licenses-render.py --check; the audio:* targets here are the
# write-side complement.
AUDIO_THEME="${AUDIO_THEME:-age-of-dwarves}"
AUDIO_ASSETS="$REPO_ROOT/public/games/$AUDIO_THEME/assets/audio"
AUDIO_MANIFEST="$REPO_ROOT/public/games/$AUDIO_THEME/data/audio.json"
AUDIO_DESIGN_APP="$REPO_ROOT/.project/designs/app"
AUDIO_DESIGN_PORT="${AUDIO_DESIGN_PORT:-7777}"
cmd_audio() {
echo -e "${BLUE}Audio status — theme '$AUDIO_THEME'${NC}"
if [[ ! -f "$AUDIO_MANIFEST" ]]; then
echo -e " ${RED}✗ manifest missing: $AUDIO_MANIFEST${NC}"
return 1
fi
local ogg_count
ogg_count=$(find "$AUDIO_ASSETS" -name '*.ogg' 2>/dev/null | wc -l | tr -d ' ')
local sources_rows
sources_rows=$(grep -c '^audio/' "$AUDIO_ASSETS/sources.csv" 2>/dev/null || echo 0)
local manifest_refs
manifest_refs=$(python3 -c "
import json
m = json.load(open('$AUDIO_MANIFEST'))
n = 0
for e in m['sfx'].values():
streams = e.get('streams') or ([e['stream']] if e.get('stream') else [])
n += len(streams)
n += len(m['music']['tracks'])
print(n)
")
echo " Manifest references: $manifest_refs streams"
echo " Files on disk: $ogg_count .ogg"
echo " Sources.csv rows: $sources_rows"
if [[ -x "$REPO_ROOT/tools/audio-validate.py" ]]; then
echo ""
python3 "$REPO_ROOT/tools/audio-validate.py" --theme "$AUDIO_THEME"
fi
echo ""
echo " Available batches:"
for tsv in "$REPO_ROOT"/tools/audio-batch-*.tsv; do
[[ -f "$tsv" ]] || continue
local rows
rows=$(grep -cE '^audio/' "$tsv")
printf " %-50s %d rows\n" "$(basename "$tsv")" "$rows"
done
echo ""
echo -e " ${DIM}./run audio:fetch run every batch${NC}"
echo -e " ${DIM}./run audio:design open the design app at http://localhost:$AUDIO_DESIGN_PORT/audio${NC}"
}
cmd_audio_validate() {
python3 "$REPO_ROOT/tools/audio-validate.py" --theme "$AUDIO_THEME" "$@"
}
cmd_audio_render() {
python3 "$REPO_ROOT/tools/audio-licenses-render.py" --theme "$AUDIO_THEME" "$@"
}
_audio_run_batch() {
local tsv="$1"
if [[ ! -f "$tsv" ]]; then
echo -e "${RED}batch not found: $tsv${NC}"
return 1
fi
bash "$REPO_ROOT/tools/audio-fetch-batch.sh" "$tsv"
}
cmd_audio_fetch() {
# Run every TSV under tools/audio-batch-*.tsv in lexical order. Each
# batch is idempotent so re-running is cheap.
local any=0
local failed=0
for tsv in "$REPO_ROOT"/tools/audio-batch-*.tsv; do
[[ -f "$tsv" ]] || continue
any=1
echo ""
echo -e "${BLUE}── $(basename "$tsv") ─────────────────${NC}"
if ! _audio_run_batch "$tsv"; then
failed=$((failed + 1))
fi
done
if [[ $any -eq 0 ]]; then
echo -e "${YELLOW}No tools/audio-batch-*.tsv files found.${NC}"
return 1
fi
if [[ $failed -gt 0 ]]; then
echo ""
echo -e "${RED}$failed batch(es) had failures — see output above${NC}"
return 1
fi
}
# Numbered batch shortcuts: ./run audio:fetch:01 → tools/audio-batch-01-*.tsv
cmd_audio_fetch_01() { _audio_fetch_numbered 01; }
cmd_audio_fetch_02() { _audio_fetch_numbered 02; }
cmd_audio_fetch_03() { _audio_fetch_numbered 03; }
cmd_audio_fetch_04() { _audio_fetch_numbered 04; }
cmd_audio_fetch_05() { _audio_fetch_numbered 05; }
cmd_audio_fetch_06() { _audio_fetch_numbered 06; }
cmd_audio_fetch_07() { _audio_fetch_numbered 07; }
cmd_audio_fetch_08() { _audio_fetch_numbered 08; }
cmd_audio_fetch_09() { _audio_fetch_numbered 09; }
_audio_fetch_numbered() {
local n="$1"
local matches=( "$REPO_ROOT"/tools/audio-batch-${n}-*.tsv )
if [[ ! -f "${matches[0]}" ]]; then
echo -e "${RED}no batch matching tools/audio-batch-${n}-*.tsv${NC}"
return 1
fi
_audio_run_batch "${matches[0]}"
}
cmd_audio_options() {
bash "$REPO_ROOT/tools/audio-fetch-options.sh" "$@"
}
cmd_audio_design() {
if [[ ! -d "$AUDIO_DESIGN_APP" ]]; then
echo -e "${RED}design app not found: $AUDIO_DESIGN_APP${NC}"
return 1
fi
if [[ ! -d "$AUDIO_DESIGN_APP/node_modules" ]]; then
echo -e "${BLUE}Installing design-app dependencies...${NC}"
(cd "$AUDIO_DESIGN_APP" && pnpm install) || return 1
fi
echo -e "${BLUE}Starting audio design app on http://localhost:$AUDIO_DESIGN_PORT/audio${NC}"
exec pnpm --dir "$AUDIO_DESIGN_APP" dev -- --port "$AUDIO_DESIGN_PORT"
}