Ir al contenido

Exportar video para una investigación

De principio a fin: encuentra la alerta o el momento, solicita un clip con spliceV3, espera a que se procese, descarga el MP4 del host de medios o compártelo con un enlace protegido con contraseña. Python y cURL.

En esta página

Esta guía exporta el video de un incidente como un archivo MP4 que puedes guardar con un caso o compartir con un enlace. Requiere cuatro llamadas: encontrar el momento, solicitar un clip, esperar a que se procese y descargarlo.

Necesitas una clave de API cuyo rol pueda ver la cámara y su video guardado. Una app OAuth puede seguir los mismos pasos con Authorization: Bearer <access token> en lugar de los encabezados de la clave de API; solicitar y compartir un clip son operaciones de escritura, así que su grant necesita los scopes read y write. Los ejemplos usan el host de EE. UU.; las organizaciones de la UE usan api2.eu.rhombussystems.com y media.eu.rhombussystems.com.

1. Encuentra el momento

Si ya conoces la cámara y la hora, pasa al paso 2. Para empezar desde una alerta, lista las alertas recientes de la cámara con getPolicyAlerts:

cURLbash
curl -X POST "https://api2.rhombussystems.com/api/event/getPolicyAlerts" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: $RHOMBUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"deviceFilter": ["CAMERA_UUID"], "afterTimestampMs": 1767225600000, "maxResults": 20}'

Cada alerta tiene un uuid, un timestampMs (cuándo empezó), un durationSec y, en las alertas de cámara, el deviceUuid. Anota el uuid de la alerta en el registro del caso.

2. Solicita un clip

Pide el video con spliceV3: la cámara, la hora de inicio en milisegundos de época y la duración en segundos. Empieza un poco antes del evento y termina un poco después:

Python
import os
import time
import requests

API = "https://api2.rhombussystems.com/api"
HEADERS = {"x-auth-scheme": "api-token", "x-auth-apikey": os.environ["RHOMBUS_API_KEY"]}

def call(path, body):
    response = requests.post(f"{API}/{path}", headers=HEADERS, json=body)
    response.raise_for_status()
    data = response.json()
    if data.get("error"):
        raise RuntimeError(data.get("errorMsg"))
    return data

alert_ms = 1767230000000  # the alert's timestampMs
clip = call("video/spliceV3", {
    "deviceUuids": ["CAMERA_UUID"],
    "startTimeMillis": alert_ms - 30_000,  # 30 seconds before
    "durationSec": 120,
    "title": "Case 2026-0142: loading dock",
    "description": "Alert AAAAAAAAAAAAAAAAAAAAAA",
})
clip_uuid = clip["clipUuid"]

El clip se procesa en segundo plano, así que la llamada responde de inmediato con su clipUuid. La creación de clips tiene un límite por cámara: si la llamada devuelve 429, espera los segundos que indica Retry-After antes de volver a intentarlo con esa cámara.

3. Espera a que se procese

Consulta getClipWithProgress cada pocos segundos hasta que status sea COMPLETE. INITIATING, UPLOADING y RENDERING indican que sigue en proceso, y percentComplete muestra el avance del paso actual; cualquier otro estado significa que no se completará:

Python
IN_PROGRESS = {"INITIATING", "UPLOADING", "RENDERING"}
deadline = time.time() + 30 * 60
while True:
    saved = call("event/getClipWithProgress", {"clipUuid": clip_uuid})["clip"]
    if saved["status"] == "COMPLETE":
        break
    if saved["status"] not in IN_PROGRESS or time.time() > deadline:
        raise RuntimeError(f"clip {clip_uuid} is {saved['status']}")
    time.sleep(5)

region = saved["clipLocation"]["region"]

El tiempo de procesamiento depende de la duración del clip y de si la cámara ya subió ese video.

4. Descarga el MP4

Descarga el clip terminado del host de medios, con la región del paso 3 y los mismos encabezados de la clave de API:

media = f"https://media.rhombussystems.com/media/metadata/{region}/{clip_uuid}.mp4"
with requests.get(media, headers=HEADERS, stream=True) as response:
    response.raise_for_status()
    with open(f"{clip_uuid}.mp4", "wb") as out:
        for chunk in response.iter_content(chunk_size=1 << 20):
            out.write(chunk)

El host de medios acepta las mismas credenciales que la API REST: los encabezados de la clave de API, o Authorization: Bearer <access token> para un token de OAuth con el scope read. Para que un navegador descargue el clip, dale un token federado como parámetros de consulta (?x-auth-scheme=federated-token&x-auth-ft=<token>); un token generado con deviceUUid solo puede obtener el clip si todas sus cámaras son ese dispositivo. Medios y transmisiones explica el host de medios, incluida la reproducción del clip en línea en lugar de descargarlo.

Compartir en lugar de descargar

Para dar acceso a alguien fuera de tu organización sin enviar un archivo, crea una página compartida con createSharedClipGroupV3. Recibe los UUID de los clips, una contraseña opcional y un vencimiento, y devuelve una shareUrl:

json
{
  "uuids": ["CLIP_UUID"],
  "title": "Case 2026-0142",
  "plaintextPassword": "a-long-random-passphrase",
  "expirationTimeSecs": 1769904000
}

expirationTimeSecs es la hora Unix (en segundos) en que el enlace deja de funcionar, no una duración. Cualquiera que tenga el enlace y la contraseña puede ver el video hasta entonces.

Lleva un registro

Para cada exportación, guarda el uuid de la alerta, el clipUuid, la cámara, el rango de tiempo solicitado, quién lo pidió y cuándo. Las acciones hechas con una clave de API aparecen en el registro de auditoría de tu organización con el nombre de la clave; consulta Permisos y rotación de claves.