> ## Documentation Index
> Fetch the complete documentation index at: https://docs.steerai.autos/llms.txt
> Use this file to discover all available pages before exploring further.

# API de video 360

> Sube y procesa videos 360 de vehiculos para inspecciones inmersivas

## Resumen

La API de video 360 permite subir videos 360 de vehiculos, extraer frames automaticamente y generar vistas 360 interactivas. Ideal para mostrar exteriores, interiores y detalles.

## Funcionalidades clave

<CardGroup cols={2}>
  <Card title="Carga de video" icon="upload">
    Sube videos 360 hasta 100MB por archivo
  </Card>

  <Card title="Extraccion de frames" icon="images">
    Extraccion automatica en intervalos optimos
  </Card>

  <Card title="Multiples lados" icon="car-side">
    Soporte para vistas OUTSIDE, INSIDE y OPEN (baul/capo)
  </Card>

  <Card title="Almacenamiento en la nube" icon="cloud">
    S3 seguro con URLs firmadas
  </Card>
</CardGroup>

## Formatos de video soportados

La API acepta:

* **MP4** (.mp4) - Recomendado
* **AVI** (.avi)
* **MOV** (.mov)
* **WMV** (.wmv)
* **FLV** (.flv)
* **WebM** (.webm)
* **MKV** (.mkv)
* **QuickTime** (.mov, .qt)

## Endpoints

### Subir video 360

<ParamField path="POST" type="endpoint">
  /360/upload
</ParamField>

Sube un video 360 a S3 y dispara extraccion de frames.

**Content Type:** `multipart/form-data`

**Form Parameters:**

<ParamField body="video" type="file" required>
  Archivo de video (max 100MB)
</ParamField>

<ParamField body="side" type="enum" required>
  Lado del vehiculo: `OUTSIDE`, `INSIDE`, `OPEN`
</ParamField>

**Response:**

```json theme={null}
{
  "success": true,
  "message": "360 video uploaded successfully",
  "data": {
    "message": "Video uploaded and processing started",
    "jobId": "job_550e8400-e29b-41d4-a716",
    "video": {
      "key": "360/videos/job_550e8400/OUTSIDE/video.mp4",
      "url": "https://s3.amazonaws.com/bucket/360/videos/job_550e8400/OUTSIDE/video.mp4",
      "originalName": "exterior_360.mp4",
      "size": 45678901,
      "mimetype": "video/mp4",
      "jobId": "job_550e8400-e29b-41d4-a716"
    }
  }
}
```

**Campos de respuesta:**

<ResponseField name="jobId" type="string">
  Identificador unico del job para seguimiento
</ResponseField>

<ResponseField name="key" type="string">
  Key en S3 del video subido
</ResponseField>

<ResponseField name="url" type="string">
  URL publica del video
</ResponseField>

<ResponseField name="originalName" type="string">
  Nombre original del archivo
</ResponseField>

<ResponseField name="size" type="number">
  Tamano del archivo en bytes
</ResponseField>

<ResponseField name="mimetype" type="string">
  Tipo MIME del archivo
</ResponseField>

**Ejemplo de request:**

```bash theme={null}
curl -X POST "https://api.steerai.autos/v1/360/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "video=@exterior_360.mp4" \
  -F "side=OUTSIDE"
```

***

### Obtener frames procesados

<ParamField path="GET" type="endpoint">
  /360/frames
</ParamField>

Obtiene frames extraidos con URLs firmadas.

**Query Parameters:**

<ParamField query="jobId" type="string" required>
  Job ID del upload
</ParamField>

<ParamField query="side" type="enum" required>
  Lado del vehiculo: `OUTSIDE`, `INSIDE`, `OPEN`
</ParamField>

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Frames retrieved successfully",
  "data": {
    "message": "360 frames found",
    "jobId": "job_550e8400-e29b-41d4-a716",
    "side": "OUTSIDE",
    "frames": [
      "https://s3.amazonaws.com/bucket/360/frames/job_550e8400/OUTSIDE/frame_001.jpg?X-Amz-Signature=...",
      "https://s3.amazonaws.com/bucket/360/frames/job_550e8400/OUTSIDE/frame_002.jpg?X-Amz-Signature=...",
      "https://s3.amazonaws.com/bucket/360/frames/job_550e8400/OUTSIDE/frame_003.jpg?X-Amz-Signature=..."
    ],
    "frameCount": 72
  }
}
```

**Campos de respuesta:**

<ResponseField name="frames" type="array">
  Arreglo de URLs firmadas (validas por 1 hora)
</ResponseField>

<ResponseField name="frameCount" type="number">
  Total de frames extraidos
</ResponseField>

<Info>
  Las URLs expiran en 1 hora. Genera nuevas URLs llamando este endpoint otra vez.
</Info>

***

### Obtener mask frames

<ParamField path="GET" type="endpoint">
  /360/mask-frames
</ParamField>

Obtiene mask frames (usados para overlays de deteccion IA) con URLs firmadas.

**Query Parameters:**

<ParamField query="carId" type="string" required>
  Vehicle UUID
</ParamField>

<ParamField query="side" type="enum" required>
  Lado del vehiculo: `OUTSIDE`, `INSIDE`, `OPEN`
</ParamField>

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Mask frames retrieved successfully",
  "data": {
    "message": "360 mask frames found",
    "carId": "car_550e8400-e29b-41d4-a716",
    "side": "OUTSIDE",
    "frames": [
      "https://s3.amazonaws.com/bucket/360/masks/car_550e8400/OUTSIDE/mask_001.png?X-Amz-Signature=...",
      "https://s3.amazonaws.com/bucket/360/masks/car_550e8400/OUTSIDE/mask_002.png?X-Amz-Signature=..."
    ],
    "frameCount": 72
  }
}
```

<Info>
  Los mask frames muestran danos detectados por IA sobre las imagenes.
</Info>

***

### Limpiar datos 360

<ParamField path="POST" type="endpoint">
  /360/cleanup
</ParamField>

Elimina videos 360 y frames de un vehiculo y lado especifico.

**Request Body:**

```json theme={null}
{
  "carId": "car_550e8400-e29b-41d4-a716",
  "side": "OUTSIDE",
  "removeProcessed": true
}
```

<ParamField body="carId" type="string" required>
  Vehicle UUID
</ParamField>

<ParamField body="side" type="enum" required>
  Lado del vehiculo: `OUTSIDE`, `INSIDE`, `OPEN`
</ParamField>

<ParamField body="removeProcessed" type="boolean">
  Eliminar frames procesados (default: true)
</ParamField>

**Response:**

```json theme={null}
{
  "success": true,
  "message": "360 data cleaned up successfully",
  "data": {
    "filesDeleted": 73,
    "rawVideoDeleted": true,
    "framesDeleted": true,
    "masksDeleted": true
  }
}
```

<Warning>
  Esta operacion elimina datos permanentemente. No se puede deshacer.
</Warning>

***

## Flujo de video 360

```mermaid theme={null}
graph TD
    A[Record 360 Video] --> B[Upload Video]
    B --> C[Video Stored in S3]
    C --> D[Processing Job Created]
    D --> E[Frame Extraction]
    E --> F[Store Frames in S3]
    F --> G[AI Damage Detection]
    G --> H[Generate Mask Frames]
    H --> I[Frames Ready]
    I --> J[Display 360 Viewer]
    J --> K{Need to Update?}
    K -->|Yes| L[Cleanup Old Data]
    L --> A
    K -->|No| M[Keep Displaying]

    style B fill:#282F75
    style I fill:#4360B1
    style J fill:#28a745
```

## Lados del vehiculo explicados

### OUTSIDE

Vista exterior completa:

* Los cuatro lados del vehiculo
* Llantas y ruedas
* Condicion exterior
* Calidad de pintura
* Danos en carroceria

**Best Practice:** Camina alrededor en circulo completo, manteniendo altura consistente.

### INSIDE

Vista interior completa:

* Tablero y controles
* Asientos delanteros y traseros
* Consola central
* Condicion interior
* Todas las funciones de cabina

**Best Practice:** Graba desde el asiento del conductor y luego el lado pasajero.

### OPEN

Compartimientos abiertos:

* Baul
* Compartimiento del motor
* Inspeccion bajo el capot
* Compartimientos de almacenamiento

**Best Practice:** Posiciona la camara para mostrar profundidad y componentes.

## Consideraciones de tamano de archivo

| Calidad       | Resolucion | Duracion | Tamano aprox. | Recomendado |
| ------------- | ---------- | -------- | ------------- | ----------- |
| **Standard**  | 1080p      | 30-60s   | 20-40 MB      | ✅ Si        |
| **High**      | 2K         | 30-60s   | 40-70 MB      | ✅ Si        |
| **Ultra**     | 4K         | 30-60s   | 70-100 MB     | ⚠️ Limite   |
| **Too Large** | 4K+        | 60s+     | 100+ MB       | ❌ Excede    |

<Warning>
  Archivos mayores a 100MB seran rechazados. Comprime si es necesario sin perder calidad.
</Warning>

## Detalles de extraccion de frames

### Extraccion automatica

* **Frame Rate:** 5 frames por segundo (configurable)
* **Total Frames:** \~60-120 frames por video
* **Formato:** JPEG (calidad optimizada)
* **Resolucion:** Mantiene resolucion de origen
* **Tiempo de proceso:** 1-3 minutos

### Convencion de nombres

Los frames se nombran secuencialmente:

```
frame_001.jpg
frame_002.jpg
frame_003.jpg
...
frame_072.jpg
```

## Casos de uso

### Ejemplo 1: Carga completa de vehiculo

```bash theme={null}
# Upload exterior 360 video
curl -X POST "https://api.steerai.autos/v1/360/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "video=@exterior_360.mp4" \
  -F "side=OUTSIDE"

# Upload interior 360 video
curl -X POST "https://api.steerai.autos/v1/360/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "video=@interior_360.mp4" \
  -F "side=INSIDE"

# Upload trunk/engine 360 video
curl -X POST "https://api.steerai.autos/v1/360/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "video=@open_360.mp4" \
  -F "side=OPEN"
```

### Ejemplo 2: Obtener y mostrar frames

```javascript theme={null}
// Fetch frames after processing
async function get360Frames(jobId, side) {
  const response = await fetch(
    `https://api.steerai.autos/v1/360/frames?jobId=${jobId}&side=${side}`,
    {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    }
  );

  const { data } = await response.json();
  return data.frames;
}

// Display in 360 viewer
async function display360View(jobId) {
  const frames = await get360Frames(jobId, 'OUTSIDE');

  // Initialize 360 viewer library
  const viewer = new Viewer360({
    container: '#viewer-container',
    frames: frames,
    autoRotate: true,
    rotationSpeed: 2
  });
}
```

### Ejemplo 3: Gestion de almacenamiento

```bash theme={null}
# Clean up old 360 data
curl -X POST "https://api.steerai.autos/v1/360/cleanup" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "carId": "car_550e8400-e29b-41d4-a716",
    "side": "OUTSIDE",
    "removeProcessed": true
  }'
```

## Codigos de error

| Code                 | Status | Description                  |
| -------------------- | ------ | ---------------------------- |
| `FILE_TOO_LARGE`     | 413    | Video excede limite de 100MB |
| `INVALID_FILE_TYPE`  | 400    | Formato no soportado         |
| `MISSING_VIDEO_FILE` | 400    | No se proporciono video      |
| `INVALID_SIDE`       | 400    | Lado de vehiculo invalido    |
| `JOB_NOT_FOUND`      | 404    | Job ID no encontrado         |
| `FRAMES_NOT_READY`   | 404    | Frames aun no procesados     |
| `UPLOAD_FAILED`      | 500    | Error al subir a S3          |
| `PROCESSING_FAILED`  | 500    | Error al extraer frames      |

## Mejores practicas

<AccordionGroup>
  <Accordion title="Graba con buena iluminacion">
    Luz natural o showroom bien iluminado. Evita sombras y reflejos.
  </Accordion>

  <Accordion title="Mantén velocidad constante">
    Camina a paso constante. Muy rapido crea frames borrosos.
  </Accordion>

  <Accordion title="Mantén la camara nivelada">
    Altura y angulo consistentes para resultados profesionales.
  </Accordion>

  <Accordion title="Limpia el vehiculo primero">
    Quita polvo, suciedad y objetos para mejor presentacion.
  </Accordion>

  <Accordion title="Revisa tamano antes de subir">
    Comprime si es necesario para estar bajo 100MB.
  </Accordion>

  <Accordion title="Sube los tres lados">
    OUTSIDE, INSIDE y OPEN dan cobertura completa.
  </Accordion>

  <Accordion title="Limpia datos antiguos regularmente">
    Usa cleanup para controlar costos y remover videos antiguos.
  </Accordion>
</AccordionGroup>

## Integracion con API de vehiculos

La API de video 360 se integra con Vehicles API:

```javascript theme={null}
// Complete vehicle listing workflow
async function createVehicleWith360(vehicleData, videoFiles) {
  // Step 1: Create vehicle
  const vehicle = await createVehicle(vehicleData);

  // Step 2: Upload 360 videos
  const outsideJob = await upload360Video(videoFiles.outside, 'OUTSIDE');
  const insideJob = await upload360Video(videoFiles.inside, 'INSIDE');
  const openJob = await upload360Video(videoFiles.open, 'OPEN');

  // Step 3: Wait for processing
  await waitForProcessing([outsideJob.jobId, insideJob.jobId, openJob.jobId]);

  // Step 4: Get frames
  const outsideFrames = await get360Frames(outsideJob.jobId, 'OUTSIDE');
  const insideFrames = await get360Frames(insideJob.jobId, 'INSIDE');
  const openFrames = await get360Frames(openJob.jobId, 'OPEN');

  // Step 5: Update vehicle with frame URLs
  await updateVehicle(vehicle.id, {
    media360: {
      outside: outsideFrames,
      inside: insideFrames,
      open: openFrames
    }
  });

  return vehicle;
}
```

## Recursos relacionados

<CardGroup cols={2}>
  <Card title="API de vehiculos" icon="car" href="/es/api-reference/vehicles/overview">
    Gestiona inventario y listados
  </Card>

  <Card title="API de inspeccion visual" icon="camera" href="/es/api-reference/inspection/visual-inspection">
    Deteccion de danos con IA
  </Card>

  <Card title="Mejores practicas de media" icon="images" href="/es/guides/media-best-practices">
    Guia para fotos y video
  </Card>

  <Card title="Gestion de almacenamiento" icon="database" href="/es/guides/storage-management">
    Optimiza costos de almacenamiento
  </Card>
</CardGroup>
