Benchmark Video Summarization logo

Benchmark Video Summarization

OrganizationPopular
NVIDIA-AI-Blueprints
benchmark-video-summarization

Benchmark a deployed LVS instance — set up test media, run single-file latency and burst-throughput tests, analyze GPU and latency metrics, and get configuration recommendations to improve performance.

Overview

PublisherNVIDIA-AI-Blueprints
Repositoryvideo-search-and-summarization
Skill namebenchmark-video-summarization
Stars
1.9K
Forks
393
Bundled files
19
LicenseApache-2.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 19 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by NVIDIA-AI-Blueprints on GitHub. Read the source before you install it.

Installation

Install the Benchmark Video Summarization AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/NVIDIA-AI-Blueprints/video-search-and-summarization.git /tmp/video-search-and-summarization
mkdir -p .claude/skills
cp -r /tmp/video-search-and-summarization/skills/benchmarking/benchmark-video-summarization .claude/skills/benchmark-video-summarization
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Benchmark Video Summarization in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Benchmark Video Summarization on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Benchmark Video Summarization is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Instructions

Follow the routing table and step-by-step workflow below. Execute each step in order on a first run. For repeat runs, go directly to the Repeat Runs section. Detailed reference material lives in references/ and benchmark scripts live in scripts/.

⚠️ Shared GPU systems: On a multi-user host, multiple LVS instances may be running on different ports. Always benchmark against the instance YOU deployed. Never assume port 38111 — always use the exact endpoint URL returned by vss-build-vision-ai when you deployed LVS. If you did not deploy an LVS instance in this session, deploy one first before running benchmarks.

Purpose

Measure the latency and throughput limits of a deployed LVS (Long Video Summarization) instance, identify GPU and pipeline bottlenecks, and suggest configuration changes that improve performance. Produces XLSX reports and JSON result files per scenario, plus a natural-language analysis with improvement recommendations.

Do NOT use this skill for:

  • Deploying LVS — use the vss-build-vision-ai skill with the lvs profile.
  • Production monitoring or alerting — this is an offline benchmarking tool.
  • Non-LVS VSS profiles (RTVI, search-only, etc.) — the /files API and /summarize endpoint are LVS-specific.

Routing

SituationAction
User has not deployed LVS in this sessionDeploy LVS with vss-build-vision-ai (lvs profile) using a unique COMPOSE_PROJECT_NAME — note the exact endpoint URL it returns, then return here
LVS_BACKEND is not setAsk the user for the endpoint URL of the LVS instance they deployed — do not guess or default
Results directory already exists with data and user asks to analyze onlySkip to Step 6: Analyze Results
First run or new hardware configurationRun the full workflow Steps 0–7
Repeat run, setup already completeUse run_benchmark.sh (see Repeat Runs section)

Prerequisites

RequirementHow to Check
LVS deployed by you via vss-build-vision-ai (lvs profile) with a unique COMPOSE_PROJECT_NAMEcurl -sf ${LVS_BACKEND}/v1/ready returns 200
LVS_BACKEND set to your deployment's endpointecho $LVS_BACKEND (e.g. http://localhost:38111)
LVS_CONTAINER_NAME set to your LVS container nameecho $LVS_CONTAINER_NAME (e.g. vss-lvs)
VIA_DEV_API=true on YOUR LVS containerdocker inspect ${LVS_CONTAINER_NAME} --format '{{range .Config.Env}}{{println .}}{{end}}' | grep VIA_DEV_API
NGC_API_KEY set in shellecho $NGC_API_KEY (non-empty)
ngc CLI installedngc --version
Python 3.10+python3 --version
ffprobe and ffmpeg installedffprobe -version && ffmpeg -version
Docker with Compose plugindocker compose version

Deploy LVS for Benchmarking

Before benchmarking, deploy a fresh LVS instance using vss-build-vision-ai. On shared systems, always use a unique COMPOSE_PROJECT_NAME so your containers and volumes are isolated from other users.

bash
# Choose a unique project name (e.g. your username)
export COMPOSE_PROJECT_NAME="lvs-bench-$(whoami)"

cd <repo>/deploy/docker

# REQUIRED FOR BENCHMARKING: the benchmark uploads videos via the LVS dev /files
# route, which is gated by VIA_DEV_API (default false; POST /files returns 404 when
# off). The lvs-server container loads its environment from
# services/video-summarization/.env (the compose `env_file:`), so VIA_DEV_API must
# be set THERE — putting it in any other env file will NOT reach the container.
# Set it before deploying:
grep -q '^VIA_DEV_API=' services/video-summarization/.env \
  && sed -i 's/^VIA_DEV_API=.*/VIA_DEV_API=true/' services/video-summarization/.env \
  || echo 'VIA_DEV_API=true' >> services/video-summarization/.env

# Deploy LVS on your designated GPUs
./scripts/dev-profile.sh up \
  --profile lvs \
  --hardware-profile RTXPRO6000BW \
  --llm-device-id <LLM_GPU> \
  --vlm-device-id <VLM_GPU>

# If LVS was already running, re-run the deploy command above so compose
# recreates the container with the new env (a plain `docker restart` does
# NOT re-read env_file changes).

Note the LVS endpoint (http://<HOST_IP>:38111) and container name: the compose file sets it statically to vss-lvs (verify with docker ps --filter name=lvs). Set these before continuing:

bash
export LVS_BACKEND=http://localhost:38111
export LVS_CONTAINER_NAME=vss-lvs
export VLM_GPUS=<VLM_GPU>
export LLM_GPUS=<LLM_GPU>

Model downloads: First deployment downloads LLM (~20 GB) and VLM (~17 GB) model weights. This takes 20–40 minutes depending on network speed. Subsequent deployments reuse the volumes created under your COMPOSE_PROJECT_NAME and start in minutes.


Step 0: Pre-flight Check

On shared systems another tenant may hold port 38111 — so the benchmark must verify it is hitting YOUR instance and YOUR GPUs, not someone else's. preflight.sh does this (and fails fast if not).

Set your deployment's values, then run the pre-flight check:

bash
export LVS_BACKEND=http://localhost:38111                          # YOUR LVS /summarize endpoint
export LVS_CONTAINER_NAME=vss-lvs                                   # YOUR LVS container (see deploy step)
export VLM_GPUS=<VLM_GPU>                                           # GPU(s) your VLM uses
export LLM_GPUS=<LLM_GPU>                                           # GPU(s) your LLM uses

./scripts/preflight.sh

preflight.sh exits non-zero unless all of the following hold:

  • the config parses and vlm_gpus/llm_gpus are valid GPU ids within the host's GPU range;
  • LVS_BACKEND is reachable (/v1/ready → 200) and the dev /files route is enabled (not 404);
  • your LVS_CONTAINER_NAME actually owns the backend port — its server bound successfully (no address already in use in its logs) and no other container publishes that port;
  • the configured VLM_GPUS/LLM_GPUS are reserved by your LVS's VLM/LLM containers — so you can't silently benchmark idle GPUs or another tenant's instance (the exact failure this guards against).

run_benchmark.sh runs preflight.sh automatically before every run; you can also run it standalone (above) any time.

If /files returns 404, the dev route is off — enable VIA_DEV_API=true on your LVS (see the deploy step) before continuing.


Step 1: Download Test Videos

The benchmark uses warehouse surveillance videos from the VSS sample dataset, hosted in NGC. scripts/fetch-videos.sh downloads the package and places a curated set — warehouse_4min.mp4, warehouse_5min.mp4, warehouse_10min.mp4 — into <VSS_BENCHMARK_DATA_DIR>/videos/, the exact filenames the default scripts/config.yaml references. It requires the ngc CLI and an NGC API key, and prints install/auth instructions if either is missing.

bash
export VSS_BENCHMARK_DATA_DIR=${VSS_BENCHMARK_DATA_DIR:-$HOME/vss-benchmark-data}

# Idempotent; add FORCE=1 to re-fetch, or pass a package version (default 3.2.0)
./scripts/fetch-videos.sh

# Probe video durations to verify what was downloaded
find "${VSS_BENCHMARK_DATA_DIR}/videos" -name "*.mp4" | while read f; do
  dur=$(ffprobe -v quiet -show_entries format=duration -of csv=p=0 "$f" 2>/dev/null | cut -d. -f1)
  echo "$(basename $f): ${dur}s"
done

Step 2: Generate Test Clips (if needed)

Normally Step 1 provides real 5- and 10-minute clips and this step can be skipped. Use it only if a curated clip is missing (e.g. the NGC package layout changed) or you need custom durations: loop an available source video into the filenames the default scripts/config.yaml references — warehouse_5min.mp4 (300s) and warehouse_10min.mp4 (600s).

bash
# Find a source video to loop from
SOURCE=$(find "${VSS_BENCHMARK_DATA_DIR}" -name "*.mp4" | head -1)
echo "Using source: ${SOURCE}"

# Create a videos/ subdirectory where the media server expects files
mkdir -p "${VSS_BENCHMARK_DATA_DIR}/videos"

for spec in warehouse_5min:300 warehouse_10min:600; do
  NAME="${spec%%:*}"; DURATION="${spec##*:}"
  OUT="${VSS_BENCHMARK_DATA_DIR}/videos/${NAME}.mp4"
  [ -f "$OUT" ] && echo "Already exists: ${OUT}" && continue
  ffmpeg -stream_loop -1 -i "${SOURCE}" -t ${DURATION} -c copy "${OUT}" -y -loglevel error
  echo "Created: ${OUT}"
done

# Verify clips
find "${VSS_BENCHMARK_DATA_DIR}/videos" -name "*.mp4" | while read f; do
  dur=$(ffprobe -v quiet -show_entries format=duration -of csv=p=0 "$f" 2>/dev/null | cut -d. -f1)
  echo "$(basename $f): ${dur}s"
done

Step 3: Start Media Server

The media server serves test videos over HTTP so the LVS /files endpoint can download them by URL.

bash
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Start the media server (nginx:alpine)
cd "${SKILL_DIR}"
docker compose -f scripts/media-server.yaml up -d
sleep 2

# Verify health
curl -sf "http://localhost:8888/health" && echo "Media server ready" || echo "Media server not ready"

# List available videos (JSON directory listing)
curl -s "http://localhost:8888/videos/" | python3 -m json.tool 2>/dev/null || \
  find "${VSS_BENCHMARK_DATA_DIR}/videos" -name "*.mp4" -exec basename {} \; | sed 's|^|http://localhost:8888/videos/|'

Note the filenames returned — you will need them in the next step to update config.yaml.


Step 4: Configure

Edit scripts/config.yaml with the actual video filenames discovered in Step 3:

  1. Update video URLs — In both single_file_test and file_burst_test sections, replace HOST_IP with your host's LAN IP (hostname -I | awk '{print $1}' — NOT localhost; LVS downloads videos from inside its container) and make sure the filenames match those served by the media server (e.g., http://<HOST_IP>:8888/videos/warehouse_5min.mp4).

  2. Set GPU assignments — Update vlm_gpus and llm_gpus to match your LVS deployment. Check YOUR container:

bash
docker inspect "${LVS_CONTAINER_NAME}" \
  --format '{{range .Config.Env}}{{println .}}{{end}}' | grep -E "VLM_GPUS|LLM_GPUS|CUDA_VISIBLE"
  1. Adjust chunk sizes — The default chunk_sizes: [10, 30] tests both 10-second and 30-second chunking. Larger chunks reduce API call overhead but increase per-chunk latency.

  2. Adjust concurrency levels — The default concurrency_levels: [1, 2, 4, 8] for file_burst. Remove levels that exceed your hardware's memory capacity.


Step 5: Run Benchmark

bash
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SKILL_DIR}/scripts"

# Create Python virtual environment if it doesn't exist
[ ! -d "vss-bench-env" ] && python3 -m venv vss-bench-env

# Activate venv and install requirements
source vss-bench-env/bin/activate
pip install -r requirements.txt -q

# LVS_BACKEND must already be set to YOUR deployment's endpoint
if [ -z "${LVS_BACKEND}" ]; then
  echo "ERROR: LVS_BACKEND is not set. Set it to your own LVS endpoint before running."
  exit 1
fi
export VIA_BACKEND="${LVS_BACKEND}"
export VIA_VLM_GPUS="${VLM_GPUS:?ERROR: VLM_GPUS must be set (e.g. export VLM_GPUS=6)}"
export VIA_LLM_GPUS="${LLM_GPUS:?ERROR: LLM_GPUS must be set (e.g. export LLM_GPUS=7)}"

# Run single_file scenario
python vss_perf_benchmark.py --config config.yaml --scenario single_file_test

# Run file_burst scenario (can be run separately or together)
python vss_perf_benchmark.py --config config.yaml --scenario file_burst_test

The benchmark creates an output directory (default: vss-perf-report/) with per-scenario subdirectories. Each scenario run generates an XLSX report and execution_summary.json.

Note: The output directory must not exist or must be empty before each run. Move or rename previous results before re-running:

bash
mv vss-perf-report vss-perf-report-$(date +%Y%m%d-%H%M%S)

Step 6: Analyze Results

bash
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUTPUT_DIR="${SKILL_DIR}/vss-perf-report"

# Show top-level execution summary for single_file
echo "=== single_file_test execution summary ==="
cat "${OUTPUT_DIR}/single_file_test/execution_summary.json" | python3 -m json.tool

# Show per-test-case summaries
find "${OUTPUT_DIR}" -name "test_case_summary.json" | while read f; do
  echo ""
  echo "=== $(dirname $f | xargs basename) ==="
  cat "$f" | python3 -m json.tool
done

# List generated XLSX reports
find "${OUTPUT_DIR}" -name "*.xlsx" | while read f; do
  echo "Report: $f"
done

Read the JSON result files and extract the following key metrics for analysis:

  • E2E latency (e2e_latency in seconds): total time from request to response
  • VLM pipeline latency (vlm_pipeline_latency): time spent in the vision model pipeline
  • VLM pipeline %: vlm_pipeline_latency / e2e_latency * 100
  • CA-RAG latency (ca_rag_latency): context-aware RAG inference time
  • VLM GPU utilization mean (vlm_gpu_usage_mean): GPU compute utilization % for VLM
  • LLM GPU utilization mean (llm_gpu_usage_mean): GPU compute utilization % for LLM
  • GPU memory mean (vlm_gpu_memory_mean, llm_gpu_memory_mean): memory pressure %
  • File burst throughput (throughput_files_per_second): concurrent files processed per second
  • Optimal concurrency (optimal_target_concurrency.estimated_concurrency): the concurrency level that meets target_latency_seconds

Step 7: Suggest Improvements

After analyzing the results, present a findings table and recommendations based on the following rules:

ObservationLikely CauseRecommended Action
VLM GPU utilization mean < 70%VLM is under-utilized — chunks too small or few framesIncrease chunk_duration (e.g., 10 → 30) or num_frames_per_chunk (e.g., 20 → 40)
VLM pipeline % > 70% of E2E latencyVLM processing dominates — resolution too highReduce vlm_input_width/vlm_input_height (e.g., 1312x736 → 896x504 for ~4k tokens)
GPU memory mean > 85%Near out-of-memory — risk of OOM at higher loadReduce batch size or lower num_frames_per_chunk; avoid higher concurrency levels
File burst throughput plateaus between concurrency levelsHardware is saturated — optimal concurrency foundThe concurrency level just before plateau is the recommended operating point
High iteration variance (std% > 20%)Thermal throttling or memory pressure between runsAllow longer cooldown between iterations; check GPU temperatures
CA-RAG latency > 20% of E2E latencyElasticsearch indexing or retrieval bottleneckCheck Elasticsearch container health; consider increasing heap size
LLM GPU utilization mean < 50%LLM is waiting on VLM outputVLM is the bottleneck; optimize VLM settings first

Repeat Runs

Once setup is complete (Steps 1–4), use run_benchmark.sh for subsequent runs:

bash
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SKILL_DIR}"

# Run single_file scenario
./scripts/run_benchmark.sh --scenario single_file_test

# Run file_burst scenario
./scripts/run_benchmark.sh --scenario file_burst_test

# Run with a versioned output directory
./scripts/run_benchmark.sh --scenario single_file_test --output-dir vss-perf-report-v2

# Run all scenarios in config.yaml
./scripts/run_benchmark.sh

# Debug mode (verbose API payloads)
./scripts/run_benchmark.sh --scenario single_file_test --debug

run_benchmark.sh checks LVS readiness, starts the media server if needed, creates/reuses the Python venv, and passes all extra arguments directly to vss_perf_benchmark.py.


Troubleshooting

SymptomCauseFix
POST /files returns 404VIA_DEV_API not set or set to falseSet VIA_DEV_API=true in services/video-summarization/.env (the lvs-server env_file) and recreate the LVS service
GPU metrics all zerosGPU monitoring requires local execution with NVML accessRun the benchmark on the GPU host directly (not via SSH without GPU passthrough)
Videos not found on media serverVSS_BENCHMARK_DATA_DIR not set correctly or videos/ subdirectory missingCheck path with ls ${VSS_BENCHMARK_DATA_DIR}/videos/; ensure Step 2 clips were created
OOM on LVS container during file_burstToo many concurrent requests consuming GPU memoryReduce concurrency_levels in config.yaml (remove the highest levels)
ngc download failsNGC_API_KEY not set or expiredRun ngc config set and verify the key at https://ngc.nvidia.com/setup/api-key
Output directory not empty errorPrevious run's results existMove previous results: mv vss-perf-report vss-perf-report-backup
ModuleNotFoundError in benchmarkPython venv not activated or requirements not installedRun source scripts/vss-bench-env/bin/activate && pip install -r scripts/requirements.txt

Cross-reference

bump:3

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Benchmark Video Summarization AI skill do?

Benchmark a deployed LVS instance — set up test media, run single-file latency and burst-throughput tests, analyze GPU and latency metrics, and get configuration recommendations to improve performance.

Why use Benchmark Video Summarization on TypingMind?

Because you install it once and use it with any model. Benchmark Video Summarization is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Benchmark Video Summarization in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/NVIDIA-AI-Blueprints/video-search-and-summarization/tree/develop/skills/benchmarking/benchmark-video-summarization. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Benchmark Video Summarization?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Benchmark Video Summarization?

As many as you like. As long as a model supports skills, you can use Benchmark Video Summarization with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Benchmark Video Summarization AI skill free?

Yes. It is published on GitHub by NVIDIA-AI-Blueprints under the Apache-2.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇