启动AutoMagicCalib发布容器Skill "amc-setup-calibration-stack"

该技能用于基于NGC发布镜像,通过Docker Compose部署AutoMagicCalib自动标定微服务和Web UI。涵盖AMC仓库解析、NGC认证、可选VGGT模型下载、Compose环境配置、目录权限设置、服务启动与健康检查,快速搭建多相机自动标定环境。关键词:AutoMagicCalib、自动标定、Docker Compose、NGC、DeepStream、微服务、Web UI、VGGT。

视频标定工具 0 次安装 1 次浏览 更新于 9/7/2026
名称 “amc-setup-calibration-stack”
描述 “通过 Docker Compose 从 NGC 发布镜像启动 AutoMagicCalib 微服务和 Web UI。当用户说“部署自动标定”、“启动自动标定”、“启动 AMC”、“启动 MS+UI”或“设置 auto-magic-calib”时使用。需要 NGC API 密钥。” metadata:
作者 “NVIDIA CORPORATION” tags: [amc, deepstream, docker, calibration, setup, ngc] owner: “NVIDIA CORPORATION” service: “auto-magic-calib”
版本 “1.0.0” reviewed: “2026-04-28”
开源协议 “Apache-2.0”

技能:启动 AutoMagicCalib 发布容器

从发布容器配置 AutoMagicCalib 微服务和 UI:解析 AMC 代码签出,认证到 NGC,可选下载 VGGT,配置 Docker Compose,启动服务,并验证就绪状态。

先决条件

  • 已安装 Docker 和 Docker Compose
  • 已配置 NVIDIA Docker Runtime(用于 GPU 支持)
  • 磁盘上存在 auto-magic-calib 仓库。步骤 0b 会解析当前仓库、DeepStream 的 tools/auto-magic-calibDEEPSTREAM_REPO_ROOT~/auto-magic-calib;否则在克隆 https://github.com/NVIDIA-AI-IOT/auto-magic-calib 之前会先询问。
  • NGC 账户,并拥有访问 NVIDIA 容器注册表的权限
  • Docker 无需 sudo 即可运行;继续之前请用 docker ps 验证。

操作说明

步骤 0:验证 Docker 无需 sudo 即可运行

docker ps
  • 如果执行成功 → 继续。
  • 如果失败并提示“permission denied” → 用户不在 docker 组中。请用户运行:
    sudo usermod -aG docker $USER && newgrp docker
    
    然后请用户确认 docker ps 正常后再继续。

智能体提示:如果在智能体沙箱中无法运行 docker ps,请用户确认它可以正常运行(例如“您能确认 docker ps 无需 sudo 即可运行吗?”)然后再继续。

步骤 0b:解析仓库签出

该技能需要 AMC 仓库资产(compose/、示例数据和 models/)。首先解析现有签出;在克隆到 ~/auto-magic-calib 之前要先询问。

REPO_URL="https://github.com/NVIDIA-AI-IOT/auto-magic-calib.git"
DEFAULT_CLONE_DIR="$HOME/auto-magic-calib"
CURRENT_GIT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"

is_amc_checkout() {
  [ -n "$1" ] \
    && [ -f "$1/README.md" ] \
    && grep -q "AutoMagicCalib" "$1/README.md" 2>/dev/null \
    && [ -f "$1/compose/compose.yml" ] \
    && grep -q "auto-magic-calib-ms" "$1/compose/ms/compose.yml" 2>/dev/null \
    && grep -q "auto-magic-calib-ui" "$1/compose/ui/compose.yml" 2>/dev/null
}

REPO_ROOT=""
for candidate in \
  "$CURRENT_GIT_ROOT" \
  "${CURRENT_GIT_ROOT:+$CURRENT_GIT_ROOT/tools/auto-magic-calib}" \
  "${DEEPSTREAM_REPO_ROOT:+$DEEPSTREAM_REPO_ROOT/tools/auto-magic-calib}" \
  "$PWD/tools/auto-magic-calib" \
  "$DEFAULT_CLONE_DIR"; do
  if is_amc_checkout "$candidate"; then
    REPO_ROOT="$candidate"
    echo "✓ Using auto-magic-calib checkout: $REPO_ROOT"
    break
  fi
done

if [ -z "$REPO_ROOT" ]; then
  if [ -n "$CURRENT_GIT_ROOT" ] && [ -d "$CURRENT_GIT_ROOT/tools/auto-magic-calib" ]; then
    echo "Found $CURRENT_GIT_ROOT/tools/auto-magic-calib, but it is not an initialized AMC checkout."
    echo "If running from the DeepStream repository root:"
    echo "  git submodule update --init tools/auto-magic-calib"
  fi

  # 这里没有任何可用的签出 — 停下来,使用主机的提问机制向用户请求确认;如果没有,则在聊天中询问并等待。
  # 不要从此处静默克隆,也不要克隆到受跟踪的子模块路径。
  echo "No usable auto-magic-calib checkout found. Ask the user for confirmation:"
  echo "  Clone $REPO_URL into $DEFAULT_CLONE_DIR? [y/N]"
  echo "On 'y' — run: git clone \"$REPO_URL\" \"$DEFAULT_CLONE_DIR\""
  exit 1
fi

cd "$REPO_ROOT"
export REPO_ROOT
echo "REPO_ROOT=$REPO_ROOT"

智能体提示:绝不静默克隆。优先使用已初始化的 DeepStream tools/auto-magic-calib;不要克隆到该子模块路径上。如果该路径存在但为空,请用户运行 git submodule update --init tools/auto-magic-calib。如果提供了其他 AMC 路径,请遵循该路径。

步骤 0c:安装 Python venv(仅限新系统)

在新系统上,pippython3-venv 可能不可用。请先安装它们:

# 为 HuggingFace CLI 创建 venv(优先使用项目本地目录)
REPO_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
HF_VENV="${REPO_DIR}/venv"
python3 -m venv "$HF_VENV" 2>/dev/null || {
  echo "ERROR: python3-venv not available." >&2
  echo "Install it manually: sudo apt install -y python3-venv python3-pip" >&2
  exit 1
}

# 安装 HuggingFace hub(VGGT 下载需要)
"$HF_VENV/bin/pip" install --upgrade pip huggingface_hub

注意:如果已存在带 hf 的 venv(检查仓库根目录的 venv/bin/hf~/venv/amc/bin/hf),则跳过此步骤。

步骤 1:登录 NGC

请使用主机的提问机制向用户询问他们的 NGC API 密钥;如果没有,则在聊天中询问并等待。然后运行:

echo "<NGC_API_KEY>" | docker login nvcr.io --username '$oauthtoken' --password-stdin
echo "✓ NGC authentication complete"

步骤 2:下载 VGGT 模型(如果尚未存在)

export REPO_ROOT=$(git rev-parse --show-toplevel)
cd "$REPO_ROOT"

if [ -f "models/vggt/vggt_1B_commercial.pt" ]; then
  echo "✓ VGGT model already present"
else
  echo "✗ VGGT model not found"
  echo "Options:"
  echo "  1. Continue without VGGT (AMC only - sufficient for most use cases)"
  echo "  2. Download VGGT model (~4.7GB, requires HuggingFace account)"
fi

要下载 VGGT:请用户接受 https://huggingface.co/facebook/VGGT-1B-Commercial 上的许可,并使用主机的提问机制从 https://huggingface.co/settings/tokens 提供读取令牌。通过 HF_TOKEN 传递,以便不会在 ps 输出中暴露:

REPO_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
cd "$REPO_DIR"

# 找到 HuggingFace CLI 二进制文件(名为 'hf',不是 'huggingface-cli')
HF_BIN="$(find "$REPO_DIR/venv" ~/venv/amc -name hf -type f 2>/dev/null | head -1)"
{ [ -z "$HF_BIN" ] || [ ! -x "$HF_BIN" ]; } && { echo "ERROR: hf binary not found or not executable; install the hf CLI (Step 0c) or set HF_BIN" >&2; exit 1; }

# 不要在命令行使用 --token(会通过 ps/argv 泄漏)。HF CLI
# 会自动从环境中读取 HF_TOKEN。
HF_TOKEN="<HF_TOKEN>" "$HF_BIN" download facebook/VGGT-1B-Commercial \
  --local-dir models/vggt/

# 验证
ls -lh models/vggt/vggt_1B_commercial.pt
# 应该显示约 4.7GB 的文件

重要:必须在设置 chown 1000:1000 之前下载 —— 当前用户在下载期间需要写权限。请在步骤 4 下载完成后设置权限。

步骤 3:配置 Compose 环境变量

Compose 环境文件控制端口和路径。在启动前更新它:

cd $REPO_ROOT/compose

# 查找可用的后端端口 (8000-8009)
for port in {8000..8009}; do
  if ! lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
    MS_PORT=$port
    echo "Using backend port: $MS_PORT"
    break
  fi
done
[ -z "$MS_PORT" ] && { echo "ERROR: no free backend port in 8000-8009; free one or widen the range." >&2; exit 1; }

# 查找可用的 UI 端口 (5000-5009)
for port in {5000..5009}; do
  if ! lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
    UI_PORT=$port
    echo "Using UI port: $UI_PORT"
    break
  fi
done
[ -z "$UI_PORT" ] && { echo "ERROR: no free UI port in 5000-5009; free one or widen the range." >&2; exit 1; }

# 获取主机 IP
HOST_IP=$(hostname -I | awk '{print $1}')
echo "Host IP: $HOST_IP"

# 保留现有键并限制 Compose 环境文件的权限。
COMPOSE_ENV_BASENAME="env"
ENV_FILE=".${COMPOSE_ENV_BASENAME}"
if [ -f "$ENV_FILE" ]; then
  BACKUP="${ENV_FILE}.bak.$(date +%s)"
  cp "$ENV_FILE" "$BACKUP"
  chmod 600 "$BACKUP"
fi
touch "$ENV_FILE"
chmod 600 "$ENV_FILE"
set_env_key() {
  local k="$1" v="$2"
  if grep -qE "^${k}=" "$ENV_FILE"; then
    sed -i "s|^${k}=.*|${k}=${v}|" "$ENV_FILE"
  else
    echo "${k}=${v}" >> "$ENV_FILE"
  fi
}
set_env_key AUTO_MAGIC_CALIB_MS_PORT "${MS_PORT}"
set_env_key AUTO_MAGIC_CALIB_UI_PORT "${UI_PORT}"
set_env_key PROJECT_DIR "../../projects"
set_env_key MODEL_DIR "../../models"
set_env_key HOST_IP "${HOST_IP}"

# 让带时间戳的 Compose 环境备份远离 git。
GITIGNORE="$REPO_ROOT/.gitignore"
touch "$GITIGNORE"
BACKUP_PATTERN="compose/${ENV_FILE}.bak.*"
grep -qxF "$BACKUP_PATTERN" "$GITIGNORE" || echo "$BACKUP_PATTERN" >> "$GITIGNORE"

echo "✓ Compose environment file updated"
cat "$ENV_FILE"

重要HOST_IP 必须是机器的网络 IP(不是 localhost),这样 UI 容器才能从浏览器访问后端。

可选:仅当 VGGT 模型挂载在非默认容器路径时,设置 VGGT_MODEL_PATH;默认为 MS 容器内的 /tmp/vggt_model/vggt_1B_commercial.pt

RTSP 标定可选:启动后请使用 skills/amc-run-rtsp-calibration/SKILL.md。该技能会在需要时验证 VIOS 可达性,并使用临时 compose override 重新启动微服务,导出 VIOS_BASE_URL,而不修改已检查的 compose 文件。

步骤 4:设置目录权限

容器以 UID/GID 1000 运行。projectsmodels 目录必须归该 UID 所有,容器才能正常读写:

cd "$REPO_ROOT"

# 如果 projects 目录不存在则创建
mkdir -p projects

# 设置所有权(容器写入标定输出所必需)。
# 一定要在 VGGT 下载完成后再执行(下载期间当前用户需要写权限)。
# 在执行 sudo chown 前需获得用户明确确认 — 它会递归更改
# $REPO_ROOT/projects 和 $REPO_ROOT/models 的所有者为 UID/GID 1000。
[ -d projects ] && [ -d models ] || {
  echo "ERROR: expected projects/ and models/ under $REPO_ROOT" >&2; exit 1;
}
echo "About to chown -R 1000:1000 on:"
echo "  $REPO_ROOT/projects"
echo "  $REPO_ROOT/models"
echo "(required because containers run as UID 1000). Confirm before proceeding."
sudo chown 1000:1000 -R projects
sudo chown 1000:1000 -R models

echo "✓ Permissions set"

步骤 5:启动服务

在拉取之前,快速失败:如果步骤 1 中认证的 NGC 密钥实际上无法访问某个发布镜像,则 docker compose up 会在部分工作完成后以 401/403 中止。

cd $REPO_ROOT/compose

# 快速失败镜像访问检查:确认 NGC 密钥可以访问所有发布的镜像,
# 然后再进行拉取。`docker manifest inspect` 检查注册表的访问权限而不下载层。
# 镜像列表从解析后的 compose 中读取,因此会自动跟踪发布标签。
IMAGES=$(docker compose config --images | sort -u)
[ -z "$IMAGES" ] && { echo "ERROR: no images resolved from compose — check the Compose environment settings and chosen profile." >&2; exit 1; }
for img in $IMAGES; do
  echo "Checking access: $img"
  if ! docker manifest inspect "$img" >/dev/null 2>&1; then
    echo "NGC login succeeded, but this key cannot access the required image:" >&2
    echo "  $img" >&2
    echo "Provide an NGC key with access to this image's namespace, then re-run Step 1 (login) and retry." >&2
    exit 1
  fi
done

# 启动所有服务(首次运行时会自动拉取镜像)
docker compose up -d

# 检查容器是否正在运行
docker compose ps

确切的镜像标签随版本而变化;请从当前的 compose 文件中读取,而不是硬编码版本。

步骤 6:验证服务是否正在运行

# 从 Compose 环境文件读取端口。
COMPOSE_ENV_BASENAME="env"
COMPOSE_ENV_FILE="$REPO_ROOT/compose/.${COMPOSE_ENV_BASENAME}"
MS_PORT=$(grep AUTO_MAGIC_CALIB_MS_PORT "$COMPOSE_ENV_FILE" | cut -d= -f2)
UI_PORT=$(grep AUTO_MAGIC_CALIB_UI_PORT "$COMPOSE_ENV_FILE" | cut -d= -f2)
HOST_IP=$(grep HOST_IP "$COMPOSE_ENV_FILE" | cut -d= -f2)

# 等待微服务就绪。冷拉取镜像或首次启动可能需要
# `docker compose up -d` 返回后额外的时间。
READY_URL="http://localhost:${MS_PORT}/v1/ready"
echo "Waiting for microservice readiness at ${READY_URL} ..."
ready_response=""
for attempt in $(seq 1 24); do
  if ready_response=$(curl -fsS --max-time 5 "${READY_URL}" 2>/dev/null) && \
     echo "${ready_response}" | grep -q '"code"[[:space:]]*:[[:space:]]*0'; then
    echo "Microservice ready: ${ready_response}"
    break
  fi
  if [ "${attempt}" -lt 24 ]; then
    printf "  [%02d/24] Microservice not ready yet; retrying in 5s...
" "${attempt}"
    sleep 5
  fi
done

if ! echo "${ready_response}" | grep -q '"code"[[:space:]]*:[[:space:]]*0'; then
  echo "ERROR: microservice did not report ready within 120 seconds: ${READY_URL}" >&2
  echo "Check status and logs:" >&2
  echo "  cd ${REPO_ROOT}/compose && docker compose ps" >&2
  echo "  cd ${REPO_ROOT}/compose && docker compose logs auto-magic-calib-ms" >&2
  exit 1
fi

# 检查 UI 是否在提供页面
UI_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "http://localhost:${UI_PORT}")
if [ "${UI_STATUS}" != "200" ]; then
  echo "ERROR: Web UI returned HTTP ${UI_STATUS}; check docker compose ps and UI logs." >&2
  exit 1
fi
echo "Web UI ready: HTTP ${UI_STATUS}"

echo "Microservice: http://${HOST_IP}:${MS_PORT}"
echo "Web UI:       http://${HOST_IP}:${UI_PORT}"

成功标准

  • docker compose ps 显示 MS 和 UI 容器为 Up;MS 应为 healthy。
  • /v1/ready 返回 code:0,并且步骤 6 打印微服务和 UI 的 URL。
  • 浏览器通过 http://<HOST_IP>:<AUTO_MAGIC_CALIB_UI_PORT> 可访问。
  • 项目会持久化在 $REPO_ROOT/projects/ 下。

故障排查

问题 修复方法
Docker 权限被拒绝 请用户运行 sudo usermod -aG docker $USER && newgrp docker,然后重试 docker ps
docker login 被拒绝 请求一个当前的 NGC 密钥并重新登录。
所需镜像不可访问 密钥缺少镜像命名空间访问权限;请提供一个有权限的密钥,然后重试步骤 1 和步骤 5。
python3 -m venvpiphf 缺失 安装 python3-venv/python3-pip;HF 二进制文件名为 hf
VGGT 权限错误 chown 1000:1000 之前下载 VGGT;恢复时,将 models/ 的所有者恢复为当前用户并重新下载。
端口被占用 在 8000-8009 选择一个空闲的 MS 端口,在 5000-5009 选择一个空闲的 UI 端口,然后更新 Compose 环境文件。
就绪超时或容器退出 运行 cd $REPO_ROOT/compose && docker compose ps 并检查 docker compose logs auto-magic-calib-ms
项目/模型权限被拒绝 仅对 projects/models/ 重新执行步骤 4。
UI 无法访问后端 检查 Compose 环境文件中的 HOST_IP 是否为机器网络 IP,而不是 localhost
GPU 不可用 docker run --rm --runtime=nvidia --gpus all ubuntu:20.04 nvidia-smi 验证 NVIDIA runtime。

常用修复

cd $REPO_ROOT/compose

# 查看日志
docker compose logs -f

# 查看特定服务的日志
docker compose logs -f auto-magic-calib-ms

# 重启所有服务
docker compose restart

# 停止并移除容器
docker compose down

# 更新 Compose 环境设置并重新启动
docker compose up -d

停止服务

cd $REPO_ROOT/compose

# 停止所有服务(容器移除,数据保留)
docker compose down

# 停止并移除卷
docker compose down -v

相关技能

  • skills/amc-run-sample-calibration/SKILL.md - 使用自带的示例数据集对已运行的堆栈进行健康检查
  • skills/amc-run-video-calibration/SKILL.md - 通过 REST API 使用您自己预先录制的 MP4 进行标定
  • skills/amc-run-rtsp-calibration/SKILL.md - 通过 VIOS 采集对实时 RTSP 流进行标定

<!-- signing marker -->