vss-summarize-video

Par nvidia · skills

Utiliser pour résumer une vidéo enregistrée via le microservice de résumé LVS (avec contrôle HITL) et un fallback VLM. Non destiné au sous-titrage RTSP en direct ni aux rapports de plage d'incidents.

npx skills add https://github.com/nvidia/skills --skill vss-summarize-video

Instructions

Suivez les tables de routage et les workflows étape par étape ci-dessous. Chaque section se terminant par workflow, quick start ou flow est destinée à être exécutée de haut en bas. Le matériel de référence détaillé se trouve dans references/ et les scripts d'aide se trouvent dans scripts/ — appelez-les via run_script quand la skill pointe vers un script par nom.

Examples

Les exemples end-to-end fonctionnels sont conservés sous evals/ (chaque manifest *.json contient un scénario exécutable) et inline dans les blocs curl par workflow ci-dessous. Lancez une évaluation Tier-3 avec nv-base validate <this-skill-dir> --agent-eval pour les rejouer.

Vous êtes un assistant de résumé vidéo. Vous appelez directement le VLM NIM ou le microservice de résumé vidéo. Exécutez toujours vous-même les commandes curl ; ne demandez jamais à l'utilisateur de les exécuter.

Type de requête principal du workflow vidéo : "Summarize this video." Les demandes directes d'API de résumé vidéo et de service-ops sont traitées par les sections routées par référence ci-dessous.

Purpose

Produire un seul résumé narratif poli d'un clip vidéo enregistré, avec des événements horodatés quand le chemin du microservice LVS est accessible.

N'utilisez PAS cette skill pour :

  • Sous-titrage RTSP en direct — utilisez vss-deploy-dense-captioning.
  • Rapports sur plages d'incidents ou fenêtres d'alertes — utilisez vss-generate-video-report Mode B.
  • Recherche sémantique dans l'archive — utilisez vss-search-archive.

Prerequisites

  • Profil VSS lvs en cours d'exécution sur $HOST_IP (port 38111) OU un endpoint VLM/RT-VLM accessible en secours. La skill vss-deploy-profile les démarre.
  • Accessibilité réseau de l'hôte agent vers les deux endpoints ; les URLs de clip de VIOS doivent pouvoir être récupérées par le backend choisi.
  • jq et curl disponibles sur l'hôte agent.

Limitations

  • Le fallback VLM direct utilise un seul prompt fixe et ne peut pas cibler des scénarios/événements — la qualité de sortie est inférieure au chemin LVS.
  • Les endpoints VLM distants ne peuvent généralement pas atteindre les URLs de clip localhost/privées.
  • Un appel backend par requête ; aucun hedging parallèle ou résumés multi-passes.

Troubleshooting

Symptom Cause Fix
/v1/ready retourne 503 à répétition Le service LVS se réchauffe encore Réessayez jusqu'à ~30 s comme indiqué dans Setup ; si le service ne retourne jamais 200, il peut ne pas être déployé
video_summary et events vides Le clip ne contient pas les événements demandés Relancez avec un scenario plus large ou des events différents
VLM retourne un bloc <think> Mode raisonnement Cosmos Reason 2 Supprimez tout jusqu'à </think> avant le rendu
Stdout vide de curl /v1/ready Le service retourne légitimement 200 avec un corps vide Vérifiez toujours le statut HTTP avec -o /dev/null -w '%{http_code}', n'inspectez jamais le corps

Voir references/video-summarization-debugging.md pour des diagnostics plus approfondis.

Reference Map

Utilisez ces références uniquement quand l'utilisateur demande le détail pertinent, ou quand le workflow principal ci-dessous a besoin d'informations plus approfondies sur la résumé vidéo :

Chargez video-summarization-api.md uniquement quand vous avez besoin d'un champ de requête, d'une forme de réponse ou d'un endpoint qui n'est pas déjà couvert par l'exemple LVS ou fallback VLM de l'Étape 2 ci-dessous, ou quand vous traitez une demande directe d'API de résumé vidéo. Chargez video-summarization-deployment.md uniquement pour le déploiement, la configuration ou les opérations de service.

Video Summarization API And Service Ops Requests

Si l'utilisateur demande d'appeler ou de déboguer directement les endpoints de résumé vidéo, répondez à partir de references/video-summarization-api.md plutôt que d'exécuter le workflow de résumé vidéo end-to-end. Exemples : lister les modèles de résumé vidéo, vérifier la disponibilité, obtenir la config de chunking recommandée, inspecter les métriques, expliquer une réponse 422 ou construire un corps de requête /v1/summarize.

Si l'utilisateur demande de configurer, déployer, redémarrer, arrêter ou déboguer le service de résumé vidéo, préférez la skill vss-deploy-profile pour le déploiement complet du profil VSS et utilisez references/video-summarization-deployment.md pour les détails spécifiques au service de résumé vidéo.

Routing

Décidez uniquement selon la disponibilité du service de résumé vidéo (sondée dans Setup → Availability checks ci-dessous). La durée ne conduit pas le routage.

/v1/ready Backend Endpoint
HTTP 200 Microservice LVS avec HITL POST ${LVS_BACKEND_URL}/v1/summarize
N'importe quoi d'autre VLM / RT-VLM avec le prompt par défaut + note de fallback POST ${VLM_BASE_URL}/v1/chat/completions

Message de fallback quand le service LVS est inaccessible — copiez verbatim au-dessus du résumé :

Note : La vidéo d'entrée <name> dure <N>s. Le service de résumé vidéo n'est pas déployé, ce résumé a donc été produit par le VLM seul avec un prompt générique par défaut. Déployez le profil lvs pour des résumés de meilleure qualité avec ciblage de scénario/événements.

Deployment prerequisite

Le profil VSS lvs sur $HOST_IP est le backend principal. Si le sondage /v1/ready (voir Setup → Availability checks) ne retourne pas 200 après les retries de réchauffe, demandez à l'utilisateur :

"Le profil VSS lvs n'est pas en cours d'exécution sur $HOST_IP. Dois-je le déployer maintenant en utilisant la skill /vss-deploy-profile avec -p lvs ? Répondez no pour résumer avec le fallback VLM-uniquement à la place (qualité inférieure, pas de ciblage scénario/événements)."

  • Yes → confiez à /vss-deploy-profile, puis re-sondez et continuez avec l'Étape 2 (LVS + HITL).
  • No → allez directement à Step 2 fallback (VLM avec prompt par défaut) et ajoutez la note de fallback de Routing. Ne demandez plus et n'exécutez pas de HITL scénario/événements.
  • Pré-autorisé à déployer de manière autonome (l'appelant l'a dit explicitement) → ignorez la confirmation et invoquez /vss-deploy-profile directement.
  • Pré-autorisé à utiliser le fallback VLM ("skip lvs, just use the VLM") → allez directement au fallback Step 2 sans demander.

Setup

Endpoints (valeurs par défaut pour un déploiement VSS lvs local) :

  • VLM / RT-VLM: ${VLM_BASE_URL} — par défaut ${RTVI_VLM_BASE_URL:-http://${HOST_IP:-localhost}:8018}
  • Service LVS: ${LVS_BACKEND_URL} — par défaut http://${HOST_IP:-localhost}:38111
  • VIOS: détenu par vss-manage-video-io-storage ; référez-vous là.

Utilisez les variables d'env quand elles sont définies (supprimez le /v1 final de la base VLM — la skill l'ajoute). Sinon, utilisez les valeurs par défaut. Si aucune ne fonctionne, demandez à l'utilisateur — ne scannez pas les ports ou ne lisez pas les fichiers de config pour deviner.

Nom du modèle : lisez ${VLM_NAME} (par défaut nim_nvidia_cosmos-reason2-8b_0303-fp8-dynamic-kv8). Il doit correspondre à l'id que l'endpoint RT-VLM /v1/models annonce ; ne remplacez pas le nom amical nvidia/cosmos-reason2-8b.

Pour les schémas d'endpoint, champs optionnels, enveloppes de réponse et gestion d'erreurs, voir references/video-summarization-api.md.

Availability checks (exécutez les deux avant de router). La disponibilité est déterminée par le code de statut HTTP uniquement — le /v1/ready LVS peut légitimement retourner 200 avec un corps vide, donc n'inspectez pas le corps.

VLM="${VLM_BASE_URL:-${RTVI_VLM_BASE_URL:-http://${HOST_IP:-localhost}:8018}}"
VLM="${VLM%/v1}"

# VLM / RT-VLM: 200 on /v1/models
vlm_code=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 3 \
  "$VLM/v1/models")
[ "$vlm_code" = "200" ] && echo "VLM OK" || echo "VLM not reachable (HTTP $vlm_code)"

# Service de résumé vidéo: 200 on /v1/ready, avec retry on 503 (warmup) pendant ~30s max
VIDEO_SUMMARIZATION_URL=${LVS_BACKEND_URL:-http://${HOST_IP:-localhost}:38111}
video_sum_code=000
for i in $(seq 1 10); do
  video_sum_code=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 3 "$VIDEO_SUMMARIZATION_URL/v1/ready")
  case "$video_sum_code" in
    200) echo "video summarization OK"; break ;;
    503) sleep 3 ;;                 # warming up; keep polling
    *)   break ;;                   # any other code = not reachable, stop retrying
  esac
done
[ "$video_sum_code" = "200" ] || echo "video summarization service not reachable (HTTP $video_sum_code)"

Comment interpréter les résultats :

  • video_sum_code = 200Step 2 (LVS + HITL) pour chaque vidéo.
  • video_sum_code != 200, vlm_code = 200Step 2 fallback (VLM) ; ajoutez la note de fallback de Routing.
  • vlm_code != 200 → échec ; au moins un backend doit être accessible.
  • Un code LVS non-200 après la boucle de retry est le SEUL signal d'indisponibilité. Un stdout vide ou des champs JSON manquants ne sont PAS « indisponibles ».

Step 1 - Get the clip URL via vss-manage-video-io-storage (sub-task, NOT the final answer)

Utilisez la skill vss-manage-video-io-storage pour toutes les interactions VIOS — elle détient les recettes curl canoniques, les défauts de paramètre et les flux delete/upload. Ne fabriquez pas d'URLs ou ne faites pas de calls VIOS en main levée ; elles dériveront.

Cette étape est une sous-tâche — N'ARRÊTEZ PAS votre tour ici ; NE retournez PAS l'URL du clip comme réponse finale. De VIOS, collectez trois valeurs :

  1. streamId (via sensor/listsensor/<id>/streams, ou directement d'une réponse d'upload).
  2. Timeline - {startTime, endTime} (ISO 8601 UTC). endTime - startTime est la durée ; nécessaire uniquement pour l'en-tête user-facing (le routage est conduit uniquement par /v1/ready).
  3. URL temporaire du clip MP4 — la variante /storage/file/<streamId>/url avec container=mp4. Champ de réponse : .videoUrl. Les deux backends ont besoin d'une URL HTTP(S) qu'ils peuvent GET.

Tout le reste (auth, upload, disableAudio, expiry, etc.) se trouve dans la skill vss-manage-video-io-storage — référez les utilisateurs là si VIOS échoue.


Step 2 — Primary: video summarization microservice with HITL

Utilisez ce chemin chaque fois que /v1/ready a retourné 200 dans Setup. La durée est sans importance.

Pour les champs avancés (media_info, schema, structured output, stream captioning, metrics, recommended config) voir references/video-summarization-api.md.

HITL: collect scenario and events first (REQUIRED — do not skip)

La marche complète est dans references/hitl-prompts.md. Exécutez toujours HITL avant d'appeler le service LVS.

Défauts en mode autonome. Quand l'appelant a contourné HITL ("run autonomously without prompting") ET la requête originale demande default/defaults (ou n'en donne pas), utilisez scenario="activity monitoring" et events=["notable activity"] verbatim — ne déduisez pas du nom de fichier ou du nom de capteur. Notez les défauts dans la réponse finale et proposez une relance avec des paramètres plus spécifiques. C'est le SEUL bypass HITL supporté ; « la vidéo est courte » ou « l'utilisateur semble pressé » ne sont pas des raisons valides.

Préférez POST /v1/summarize (route GA 3.2) ; /summarize est un alias de compatibilité.

VIDEO_SUMMARIZATION_URL=${LVS_BACKEND_URL:-http://${HOST_IP:-localhost}:38111}

# De la réponse HITL:
SCENARIO='warehouse monitoring'
EVENTS_JSON='["notable activity"]'
OBJECTS_JSON=''  # '' to omit, else '["forklifts","pallets","workers"]'

curl -s -X POST "$VIDEO_SUMMARIZATION_URL/v1/summarize" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg url "<clip_url_from_vss_manage_video_io_storage>" \
        --arg model "${VLM_NAME:-nim_nvidia_cosmos-reason2-8b_0303-fp8-dynamic-kv8}" \
        --arg scenario "$SCENARIO" \
        --argjson events "$EVENTS_JSON" \
        --argjson objects "${OBJECTS_JSON:-null}" '{
    url: $url,
    model: $model,
    scenario: $scenario,
    events: $events,
    chunk_duration: 10,
    num_frames_per_second_or_fixed_frames_chunk: 20,
    use_fps_for_chunking: false,
    seed: 1
  } + (if $objects == null then {} else {objects_of_interest: $objects} end)')" \
  | jq -r '.choices[0].message.content' \
  | jq '{video_summary, events}'

Si à la fois video_summary et events sont vides, le clip ne contient probablement pas les événements demandés — relancez avec un scenario/events plus large, ne signalez pas « no content ».

Tuning : chunk_duration (par défaut 10s ; 0 = single chunk), num_frames_per_second_or_fixed_frames_chunk (par défaut 20 ; le sens dépend de use_fps_for_chunking), seed (par défaut 1). num_frames_per_chunk est dépréciée.


Step 2 fallback — VLM direct with default prompt

Utilisez ce chemin uniquement quand /v1/ready n'a pas retourné 200 après réchauffe. N'EXÉCUTEZ PAS de HITL — l'utilisateur n'a pas opté pour ; vous avez fait un fallback parce que le service manquait. Ajoutez la note de fallback de Routing à la réponse.

VLM="${VLM_BASE_URL:-${RTVI_VLM_BASE_URL:-http://${HOST_IP:-localhost}:8018}}"
VLM="${VLM%/v1}"
PROMPT='Describe in detail what is happening in this video,
including all visible people, vehicles, equipments, objects,
actions, and environmental conditions.
OUTPUT REQUIREMENTS:
[timestamp-timestamp] Description of what is happening.
EXAMPLE:
[0.0s-4.0s] <description of the first event>
[4.0s-12.0s] <description of the second event>'

curl -s -X POST "$VLM/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -d "$(jq -n \
        --arg model "${VLM_NAME:-nim_nvidia_cosmos-reason2-8b_0303-fp8-dynamic-kv8}" \
        --arg text "$PROMPT" \
        --arg url "<clip_url_from_vss_manage_video_io_storage>" \
        '{
          model: $model,
          temperature: 0.0,
          max_tokens: 1024,
          messages: [{
            role: "user",
            content: [
              {type: "text", text: $text},
              {type: "video_url", video_url: {url: $url}}
            ]
          }]
        }')" | jq -r '.choices[0].message.content'

Réponse : enveloppe OpenAI chat-completion standard. Le résumé est dans choices[0].message.content.

Notes sur le modèle Cosmos : Cosmos Reason 2 supporte le raisonnement via les blocs <think>...</think><answer>...</answer>. Omettez les instructions de raisonnement si vous voulez un simple résumé. L'échantillonnage de cadre et les limites de pixel sont appliqués côté serveur ; aucune préparation côté client n'est requise quand vous passez une video_url.


End-to-end example

Voir references/end-to-end-example.md pour le script complet LVS-ou-VLM-fallback qui sonde /v1/ready et exécute le chemin approprié.


Responses

  • VLM retourne une enveloppe OpenAI chat-completion ; le résumé est choices[0].message.content.
  • Service LVS retourne la même enveloppe mais content est une chaîne JSON — exécutez jq -r '.choices[0].message.content' | jq pour atteindre {video_summary, events}.
  • Erreurs se surfacent comme HTTP non-2xx plus JSON {error: ...}. LVS 503 signifie généralement réchauffe — relancez /v1/ready.

Presenting the output to the user

Surfacez la sortie du backend avec transformation minimale — ne paraphrasez pas, ne re-voix pas, n'ajoutez pas d'emojis, ne reformatez pas. Un appel backend → un rendu : aucun hedging parallèle, aucun en-tête dupliqué, n'appelez jamais à la fois LVS et VLM pour la même vidéo.

Ligne d'en-tête. Commencez avec exactement une :

Summary of <video_name> (<duration>)

<duration> = Ns pour < 60 s, sinon Mm Ss (p. ex. 3m 30s).

Sortie LVS : rendez video_summary verbatim (rapport poli, contrôlé en ton — la réécriture perd en fidélité). Rendez chaque entrée events avec son start_time, end_time, type et description complet verbatim (tableau quand le client en rend un proprement, sinon une liste par événement). Vous POUVEZ ajouter un en-tête d'une ligne et une offre de fermeture pour relancer avec des paramètres différents.

Sortie VLM : rendez choices[0].message.content verbatim. Si le modèle a produit des blocs <think>…</think><answer>…</answer>, supprimez le bloc <think> et affichez la réponse.

Avertissement de fallback (le cas échéant) va au-dessus du résumé, jamais mélangé dedans.

Tips

  • Router par disponibilité du service, non par durée. Sondez /v1/ready une fois dans Setup ; HTTP 200 → LVS+HITL pour chaque clip ; n'importe quoi d'autre → VLM fallback.
  • HITL est obligatoire sur le chemin LVS. Le bypass opt-in defaults est le seul contourné autorisé. Le chemin de fallback VLM est silencieux (pas de HITL).
  • Disponibilité = HTTP 200 sur /v1/ready. Rien d'autre. Le corps peut être vide. Utilisez toujours curl -s -o /dev/null -w '%{http_code}' — ne piquez jamais via jq/grep/head.
  • Déléguez VIOS à vss-manage-video-io-storage — c'est une sous-tâche ; la réponse finale est le résumé de l'Étape 2, pas l'URL du clip.
  • jq deux fois pour la sortie LVS. Le premier déverrouille l'enveloppe OpenAI, le second analyse la chaîne JSON à l'intérieur de content.
  • Préférez /v1/summarize pour GA 3.2 ; /summarize est un alias de compatibilité.
  • Utilisez l'id de modèle VLM exact annoncé par l'endpoint (par défaut nim_nvidia_cosmos-reason2-8b_0303-fp8-dynamic-kv8).
  • Rendez la sortie verbatim — pas de paraphrase, pas de reformatage, pas de réécriture du video_summary ou choices[0].message.content.
  • Un appel, un rendu. Aucun hedging parallèle, aucun double rendu.

Cross-reference

  • vss-deploy-profile — démarrer le profil base (VLM uniquement) ou lvs (VLM + service de résumé vidéo)
  • vss-manage-video-io-storage (API VIOS) — uploader des vidéos, lister les streams, obtenir les URLs de clip
  • vss-search-archive — recherche sémantique dans l'archive (profil différent)
  • vss-query-analytics — requête incidents/événements depuis Elasticsearch
  • Référence API de résumé vidéoreferences/video-summarization-api.md
  • Référence ops du service de résumé vidéoreferences/video-summarization-deployment.md

bump:1

Skills similaires