Hola comunidad 👋
Quiero compartir un script en Python que desarrolló para convertir metadatos de video en formato SRT (común en drones comerciales) a un CSV compatible con ArcGIS Full Motion Video , siguiendo la estructura utilizada por los estándares MISB para video con información geoposicional codificada.
Muchos drones generan metadatos en archivos SRT (posición, altitud, orientación, tiempo), pero ArcGIS Pro FMV requiere metadatos estructurados en CSV para poder habilitar:
Seguimiento de plataforma
Orientación del sensor
Visualización espacial del vídeo
Análisis FMV sobre el mapa
Este script permite democratizar el uso de FMV , incluso con plataformas que no generan metadatos MISB directamente.
El código:
Lee un archivo SRT con metadatos embebidos por frame.
Extra:
Marca de tiempo
Latitud / Longitud
Altitud absoluta
Yaw, Pitch y Roll de la plataforma
Aplicaciones correcciones geométricas comunes:
Desplazamiento del geoide
Corrección de orientación del marco
Ajuste fino de encabezado
Calcular campos clave para FMV:
Encabezado de plataforma (similar a MISB)
Altitud verdadera del sensor
Campo de visión horizontal y vertical.
Genera un CSV listo para cargar en ArcGIS Pro → Full Motion Video usando plantillas estándar.
Vídeos de drones DJI u otros fabricantes
Drones sin soporte FMV nativo
Proyectos de seguridad, monitoreo, tráfico, defensa, emergencias.
Integración de vídeo + GIS sin hardware especializado
ArcGIS Pro
Python 3.x
Librerías estándar ( re , csv , datetime )
import re
import csv
from datetime import datetime
def srt_to_fmv_csv(srt_file_path, csv_output_path, heading_fine_adjust=18.0):
"""
Convierte un archivo SRT de metadatos de dron a un CSV compatible con ArcGIS Full Motion Video (MISB-like).
Parámetros:
- srt_file_path: Ruta al archivo .srt
- csv_output_path: Ruta de salida del archivo .csv
- heading_fine_adjust: Ajuste fino del heading en grados
"""
# Patrones regex para extracción de metadatos
time_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})'
lat_pattern = r'latitude:\s*(-?\d+\.\d+)'
lon_pattern = r'longitude:\s*(-?\d+\.\d+)'
abs_alt_pattern = r'abs_alt:\s*(-?\d+\.\d+)'
yaw_pattern = r'gb_yaw:\s*(-?\d+\.\d+)'
pitch_pattern = r'gb_pitch:\s*(-?\d+\.\d+)'
roll_pattern = r'gb_roll:\s*(-?\d+\.\d+)'
# Parámetros de cámara (ajustables según el dron)
horizontal_fov = 83.8
vertical_fov = 71.5
sensor_relative_azimuth = 0.0
sensor_relative_roll = 0.0
# Correcciones fijas
geoid_offset = 30.0
perpendicular_offset = 90.0
mirror_fix = 180.0
with open(srt_file_path, 'r', encoding='utf-8') as srt_file, \
open(csv_output_path, 'w', newline='', encoding='utf-8') as csv_file:
writer = csv.writer(csv_file)
writer.writerow([
"TimeStamp", "UnixTimeStamp", "SensorLatitude", "SensorLongitude",
"PlatformHeading", "PlatformPitch", "PlatformRoll",
"SensorTrueAltitude", "HorizontalFOV", "VerticalFOV",
"SensorRelativeAzimuth", "SensorRelativeElevation", "SensorRelativeRoll"
])
content = srt_file.read()
times = re.findall(time_pattern, content)
latitudes = re.findall(lat_pattern, content)
longitudes = re.findall(lon_pattern, content)
altitudes = re.findall(abs_alt_pattern, content)
yaws = re.findall(yaw_pattern, content)
pitches = re.findall(pitch_pattern, content)
rolls = re.findall(roll_pattern, content)
if not (len(times) == len(latitudes) == len(longitudes) == len(altitudes) == len(yaws)):
print("Error: Los metadatos no tienen la misma longitud.")
return
for i in range(len(times)):
dt = datetime.strptime(times[i], '%Y-%m-%d %H:%M:%S.%f')
unix_time = int(dt.timestamp() * 1_000_000)
heading = (90 - float(yaws[i]) +
perpendicular_offset +
mirror_fix +
heading_fine_adjust) % 360
true_altitude = float(altitudes[i]) - geoid_offset
writer.writerow([
times[i],
unix_time,
float(latitudes[i]),
float(longitudes[i]),
heading,
float(pitches[i]),
float(rolls[i]),
true_altitude,
horizontal_fov,
vertical_fov,
sensor_relative_azimuth,
float(pitches[i]),
sensor_relative_roll
])
print("CSV FMV generado correctamente.")