The cross-source study needs two 4K recordings and a hand-sorted set of face crops, neither of which belongs in git. Adds an xsource target to both artifact scripts. Push uploads the clips as-is (already compressed) and zips labelling/. Pull fetches both and regenerates frames with ffmpeg rather than downloading them: ~320 MB of PNG that is deterministic from the clips. The extraction settings are pinned in the script, not left to the caller, because the manifests key on frame filenames and on detection order within each frame — verify_labels.py runs afterwards and fails loudly if they drift. Pull refuses to overwrite an existing labelling/. It is human ground truth: somebody looked at 167 crops and placed each one, and silently replacing that with a remote copy would destroy the expensive half of the study. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> TRACES: VR-013
157 lines
6.5 KiB
Bash
Executable File
157 lines
6.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# push_artifacts.sh — upload benchmark artifacts (galleries, montage frames) to the
|
|
# Gitea generic package registry, decoupled from git history entirely. These are
|
|
# NOT needed to run the main app — only for benchmarks/experiments/reports.
|
|
#
|
|
# Requires GITEA_TOKEN in the environment (a Gitea access token with package
|
|
# read/write scope). Never hardcode the token; export it in your shell:
|
|
# export GITEA_TOKEN=...
|
|
#
|
|
# Usage:
|
|
# scripts/artifacts/push_artifacts.sh galleries
|
|
# scripts/artifacts/push_artifacts.sh montage-frames
|
|
# scripts/artifacts/push_artifacts.sh experiment-data
|
|
# scripts/artifacts/push_artifacts.sh report-highlights
|
|
# scripts/artifacts/push_artifacts.sh xsource
|
|
# scripts/artifacts/push_artifacts.sh galleries montage-frames experiment-data report-highlights
|
|
#
|
|
# Package layout (owner=dtourolle, repo=scene-actor-extraction):
|
|
# generic/galleries/<version>/gallery_<model>.h5 (one file per model)
|
|
# generic/montage-frames/<version>/<film-slug>.zip (zipped per-film frames)
|
|
# generic/experiment-data/<version>/experiment-data.zip (manifests/trajectories/results)
|
|
# generic/report-highlights/<version>/<name>.jpg (individual, hand-picked
|
|
# illustrative frames referenced by docs/*.md that aren't reproducible via
|
|
# the automated best/worst montage selection — see scripts/docs/build_site.sh)
|
|
# version = current git short SHA, so artifacts are traceable to the code that
|
|
# produced them. Re-running with the same SHA overwrites that version's files.
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
OWNER="dtourolle"
|
|
PKG_REPO="scene-actor-extraction"
|
|
# NOTE: the generic package registry lives under /api/packages/ (no /v1/) —
|
|
# distinct from the regular REST API under /api/v1/packages/ used for listing.
|
|
BASE_URL="https://gitea.tourolle.paris/api/packages/${OWNER}"
|
|
VERSION="$(git -C "$REPO_ROOT" rev-parse --short HEAD)"
|
|
|
|
if [ -z "${GITEA_TOKEN:-}" ]; then
|
|
echo "error: GITEA_TOKEN is not set. export GITEA_TOKEN=<your token> and retry." >&2
|
|
exit 1
|
|
fi
|
|
|
|
upload() {
|
|
local package="$1" filename="$2" filepath="$3"
|
|
local url="${BASE_URL}/generic/${package}/${VERSION}/${filename}"
|
|
echo " uploading ${filename} -> ${package}/${VERSION}..."
|
|
curl -sf -X PUT "$url" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/octet-stream" \
|
|
--upload-file "$filepath" \
|
|
-o /dev/null -w " HTTP %{http_code}\n"
|
|
}
|
|
|
|
push_galleries() {
|
|
echo "=== galleries (version ${VERSION}) ==="
|
|
local dir="${REPO_ROOT}/experiments/galleries"
|
|
shopt -s nullglob
|
|
for f in "$dir"/gallery_*.h5; do
|
|
upload "galleries" "$(basename "$f")" "$f"
|
|
done
|
|
shopt -u nullglob
|
|
}
|
|
|
|
push_montage_frames() {
|
|
echo "=== montage-frames (version ${VERSION}) ==="
|
|
local root="${REPO_ROOT}/experiments/results/holdout/montage_bestworst"
|
|
if [ ! -d "$root" ]; then
|
|
echo " no montage_bestworst dir found, skipping" >&2
|
|
return
|
|
fi
|
|
local tmp
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp"' RETURN
|
|
for filmdir in "$root"/*/; do
|
|
[ -d "$filmdir" ] || continue
|
|
local slug ascii_slug zipfile
|
|
slug="$(basename "$filmdir")"
|
|
# Gitea's generic package registry rejects non-ASCII filenames (verified:
|
|
# a bare é in the name 400s). Transliterate for the upload name only —
|
|
# the local directory name (with accents) is untouched.
|
|
ascii_slug="$(echo "$slug" | iconv -f utf-8 -t ascii//translit 2>/dev/null || echo "$slug")"
|
|
zipfile="${tmp}/${ascii_slug}.zip"
|
|
(cd "$filmdir" && zip -qr "$zipfile" .)
|
|
upload "montage-frames" "${ascii_slug}.zip" "$zipfile"
|
|
done
|
|
}
|
|
|
|
push_experiment_data() {
|
|
echo "=== experiment-data (version ${VERSION}) ==="
|
|
# manifests/trajectories/results are all small text/JSON — no source paths
|
|
# (manifests never carry a "movie" field; see experiments/file-lut.json)
|
|
# so this is safe to share as one bundle.
|
|
local tmp; tmp="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp"' RETURN
|
|
local zipfile="${tmp}/experiment-data.zip"
|
|
(cd "$REPO_ROOT" && zip -qr "$zipfile" \
|
|
experiments/manifests experiments/trajectories experiments/results \
|
|
-x '*.log' -x '*/holdout/montage_bestworst/*' -x '*/holdout/frames/*' \
|
|
-x '*/holdout/montage/*' -x '*/holdout/*.jsonl' -x '*/holdout/pred_*.json' \
|
|
-x '*/holdout/raw_*.jsonl')
|
|
upload "experiment-data" "experiment-data.zip" "$zipfile"
|
|
}
|
|
|
|
push_report_highlights() {
|
|
echo "=== report-highlights (version ${VERSION}) ==="
|
|
local src="${REPO_ROOT}/experiments/results/holdout/montage/many_saints/out_of_cast_fpi/10_t003641.jpg"
|
|
if [ ! -f "$src" ]; then
|
|
echo " [warn] $src not found, skipping" >&2
|
|
return
|
|
fi
|
|
upload "report-highlights" "germar_beats_xray.jpg" "$src"
|
|
}
|
|
|
|
push_xsource() {
|
|
echo "=== xsource (version ${VERSION}) ==="
|
|
local root="${REPO_ROOT}/experiments/xsource"
|
|
if [ ! -d "$root/labelling" ]; then
|
|
echo " no experiments/xsource/labelling found, skipping" >&2
|
|
return
|
|
fi
|
|
|
|
# Source recordings. Already compressed, so uploaded as-is rather than zipped.
|
|
shopt -s nullglob
|
|
for f in "$root"/clips/*.mp4; do
|
|
upload "xsource" "$(basename "$f")" "$f"
|
|
done
|
|
shopt -u nullglob
|
|
|
|
# The hand-sorted crops and their manifests. This is human ground truth and
|
|
# the expensive part of the study — a person looked at every crop and put it
|
|
# in a folder. Frames are deliberately NOT pushed: they are deterministic
|
|
# from the clips, and pulling regenerates them.
|
|
local tmp; tmp="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp"' RETURN
|
|
local zipfile="${tmp}/labelling.zip"
|
|
(cd "$root" && zip -qr "$zipfile" labelling -x 'labelling/*.html' -x 'labelling/review_*.jpg' \
|
|
-x 'labelling/verify_*.jpg')
|
|
upload "xsource" "labelling.zip" "$zipfile"
|
|
}
|
|
|
|
if [ $# -eq 0 ]; then
|
|
echo "usage: $0 <galleries|montage-frames|experiment-data|report-highlights|xsource> [...]" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for target in "$@"; do
|
|
case "$target" in
|
|
galleries) push_galleries ;;
|
|
montage-frames) push_montage_frames ;;
|
|
experiment-data) push_experiment_data ;;
|
|
report-highlights) push_report_highlights ;;
|
|
xsource) push_xsource ;;
|
|
*) echo "unknown target: $target (expected galleries, montage-frames, experiment-data, report-highlights, or xsource)" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
echo "Done. Browse at: https://gitea.tourolle.paris/${OWNER}/${PKG_REPO}/packages"
|