Azure Video Indexer

Spread the love

En este artículo, exploraremos las capacidades de Azure Video Indexer. Azure Video Indexer es un servicio de Microsoft que permite extraer información valiosa de nuestros videos. Es importante destacar que no se trata de un análisis en tiempo real.

Los videos se pueden enviar mediante la API o directamente desde el Portal. Una vez procesado el video, podemos recuperar toda la información extraída y guardarla en una base de datos. Además de descargar el JSON, es posible obtener recursos visuales como fotogramas clave y fotos de personas detectadas.

Hasta aquí, podría parecer un servicio simple, pero en realidad es un servicio compuesto por muchos otros que tienen la capacidad de extraer información tanto del análisis visual como del audio de los videos. Para entender mejor, veamos el diagrama de la cantidad de información que se puede extraer.

Video Indexer

En el diagrama, podemos ver que hay una separación de la información obtenida por audio y la información obtenida por video. Vamos a ver en detalle cada una de ellas.

Por audio podemos obtener:

  • Idioma: Es capaz de detectar varios idiomas en el mismo video.
  • Diarización: Analiza el audio y asigna un identificador único a cada hablante.
  • Transcripción: Convierte el audio en texto, y se presenta en dos formatos: por escena y por transcripción individual. Las transcripciones por escena abarcan segmentos más extensos, incluyendo periodos de silencio. Las transcripciones individuales son más cortas y útiles para buscar diálogos específicos. Sin embargo, en las escenas con silencio, no habrá transcripción. Esto puede generar «huecos» en la información. En mis pruebas, observé que en algunos videos no había información transcrita hasta el minuto 2.
  • Análisis de sentimientos: Detecta el tono emocional general del audio, indicando si es positivo, negativo o neutral.
  • Reconocimiento de emociones: Identifica emociones específicas en las voces de los hablantes, como alegría, tristeza o enojo.
  • Efectos de audio: Detecta varios efectos de audio presentes en el contenido, como aplausos, risas o silencio.
  • Moderación de contenido textual: Analiza el texto transcrito y detecta lenguaje inapropiado o sensible.
  • Marcas mencionadas: Reconoce y extrae los nombres de marcas comerciales que se mencionan en el audio o video.
  • Personas mencionadas: Identifica y extrae los nombres de personas que se mencionan en el contenido.
  • Lugares mencionados: Reconoce y extrae los nombres de lugares geográficos que se mencionan.
  • Extracción de palabras clave: Identifica y extrae las palabras y frases más relevantes del contenido.
  • Modelado de temas: Agrupa el contenido en temas relevantes, lo que facilita la búsqueda y organización.

Por imagen podemos extraer la siguiente información:

  • OCR (Reconocimiento Óptico de Caracteres): Extrae texto de imágenes dentro del video, como letreros o subtítulos.
  • Segmentación de escenas: Divide el video en segmentos basados en cambios visuales significativos.
  • Extracción de fotogramas clave: Identifica automáticamente los fotogramas más representativos del video.
  • Segmentación de tomas: Divide el video en tomas, que son secuencias de fotogramas tomadas por la misma cámara.
  • Detección de rostros: Localiza y marca las caras de las personas que aparecen en el video.
  • Agrupación de rostros: Agrupa las caras detectadas en el video, identificando cuando la misma persona aparece múltiples veces.
  • Selección del mejor rostro: Dentro de un grupo de rostros, selecciona la imagen de mayor calidad.
  • Identificación de rostros: Reconoce a personas conocidas o entrenadas en el sistema.
  • Personas observadas: Realiza un seguimiento de las personas detectadas mientras se mueven dentro del video.
  • Detección de vestimenta: Detecta las prendas de vestir de las personas en el video.
  • Detección de objetos: Identifica y etiqueta objetos presentes en el video, como coches o animales.
  • Etiquetas: Asigna etiquetas descriptivas a elementos visuales clave en el video.
  • Detección de créditos rodantes: Detecta y extrae el texto que aparece en los créditos finales de un video.
  • Moderación de contenido visual: Detecta contenido visual inapropiado o sensible.
  • Detección de claqueta: Detecta la claqueta utilizada en la producción de video.
  • Patrones digitales: Detecta patrones digitales, como códigos QR, dentro del video.
  • Material sin texto: Detecta secciones del video que no contienen texto visual.
  • Ropa destacada: Identifica y destaca prendas de vestir específicas en el video.
  • Persona coincidida: Permite la búsqueda de personas que coinciden con una imagen de referencia.

Como puedes ver, este servicio hace uso de muchos otros para obtener toda esta información.

Lo puedes probar gratis aquí: https://www.videoindexer.ai/

 

El reconocimiento facial de personas no conocidas, como en mi caso, requiere permisos especiales.

En mis pruebas, configuré para que me detectara a mí y a Wally, como puedes ver en la captura.

Captura Azure Video Indexer

 

Hay más cosas interesantes sobre este servicio. Podemos configurar Azure OpenAI para que nos haga un resumen del video. Esta funcionalidad es muy útil si pensamos en usarla, por ejemplo, para un buscador de videos sobre reuniones. Podemos elegir resumen corto o largo, además de un tono formal o informal.

 

Captura de Azure indexer Video Portal

 

Toda la información devuelta por el servicio (emociones, objetos, transcripciones, etc.) incluye la duración y las marcas de tiempo de inicio y fin. Cuando la información se refiere al mismo objeto o persona, se presenta en un array. Por ejemplo:

 

 

"faces": [
            {
                "videoId": "hm899uxybd",
                "referenceId": "0d47c987-0042-5576-15e8-97af601614fa",
                "referenceType": "Bing",
                "confidence": 0.8044,
                "description": "William Henry Gates III, conocido como Bill Gates, es un magnate empresarial, desarrollador de software, inversor, autor y filántropo estadounidense. Es cofundador de Microsoft, junto con su difunto amigo de la infancia Paul Allen. Durante su carrera en Microsoft, Gates ocupó los cargos de presidente, director ejecutivo, presidente y arquitecto jefe de software, además de ser el mayor accionista individual hasta mayo de 2014. Fue uno de los principales empresarios de la revolución de las microcomputadoras de las décadas de 1970 y 1980.",
                "title": "Empresario estadounidense",
                "thumbnailId": "b90bd27a-1a25-4a12-968c-15badfa547c4",
                "seenDuration": 70.2,
                "seenDurationRatio": 0.061,
                "id": 1306,
                "name": "Bill Gates",
                "appearances": [
                    {
                        "startTime": "0:03:07",
                        "endTime": "0:03:28.9333333",
                        "startSeconds": 187,
                        "endSeconds": 208.9
                    },
                    {
                        "startTime": "0:10:09.9333333",
                        "endTime": "0:10:23.0666667",
                        "startSeconds": 609.9,
                        "endSeconds": 623.1
                    }
                ]

 

Al convertir el JSON devuelto por Azure Video Indexer en clases de C#, obtendríamos una estructura jerárquica, donde ‘RootResponse’ representaría el nodo raíz

 

 

public class RootResponse
    {
        public object partition { get; set; }
        public object description { get; set; }
        public string privacyMode { get; set; }
        public string state { get; set; }
        public string accountId { get; set; }
        public string id { get; set; }
        public string name { get; set; }
        public string userName { get; set; }
        public DateTime created { get; set; }
        public bool isOwned { get; set; }
        public bool isEditable { get; set; }
        public bool isBase { get; set; }
        public int durationInSeconds { get; set; }
        public string duration { get; set; }
        public SummarizedInsights summarizedInsights { get; set; }
        public List<Video> videos { get; set; }
        public List<VideosRange> videosRanges { get; set; }
    }

    public class Appearance
    {
        public string startTime { get; set; }
        public string endTime { get; set; }
        public double startSeconds { get; set; }
        public double endSeconds { get; set; }
        public double confidence { get; set; }
    }

    public class AudioEffect
    {
        public string audioEffectKey { get; set; }
        public double seenDurationRatio { get; set; }
        public double seenDuration { get; set; }
        public List<Appearance> appearances { get; set; }
        public int id { get; set; }
        public string type { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Block
    {
        public int id { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Brand
    {
        public string referenceId { get; set; }
        public string referenceUrl { get; set; }
        public double confidence { get; set; }
        public string description { get; set; }
        public double seenDuration { get; set; }
        public int id { get; set; }
        public string name { get; set; }
        public List<Appearance> appearances { get; set; }
        public string referenceType { get; set; }
        public List<object> tags { get; set; }
        public bool isCustom { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class DetectedObject
    {
        public int id { get; set; }
        public string type { get; set; }
        public string thumbnailId { get; set; }
        public string displayName { get; set; }
        public string wikiDataId { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Duration
    {
        public string time { get; set; }
        public int seconds { get; set; }
    }

    public class Emotion
    {
        public string type { get; set; }
        public double seenDurationRatio { get; set; }
        public List<Appearance> appearances { get; set; }
        public int id { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Face
    {
        public string videoId { get; set; }
        public string referenceId { get; set; }
        public string referenceType { get; set; }
        public double confidence { get; set; }
        public string description { get; set; }
        public string title { get; set; }
        public string thumbnailId { get; set; }
        public double seenDuration { get; set; }
        public double seenDurationRatio { get; set; }
        public int id { get; set; }
        public string name { get; set; }
        public List<Appearance> appearances { get; set; }
        public string knownPersonId { get; set; }
        public string imageUrl { get; set; }
        public bool highQuality { get; set; }
        public List<Thumbnail> thumbnails { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class FramePattern
    {
        public string displayName { get; set; }
        public int id { get; set; }
        public string name { get; set; }
        public List<Appearance> appearances { get; set; }
        public string patternType { get; set; }
        public int confidence { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Insights
    {
        public string version { get; set; }
        public string duration { get; set; }
        public string sourceLanguage { get; set; }
        public List<string> sourceLanguages { get; set; }
        public string language { get; set; }
        public List<string> languages { get; set; }
        public List<Transcript> transcript { get; set; }
        public List<Ocr> ocr { get; set; }
        public List<Keyword> keywords { get; set; }
        public List<Topic> topics { get; set; }
        public List<Face> faces { get; set; }
        public List<Label> labels { get; set; }
        public List<Scene> scenes { get; set; }
        public List<Shot> shots { get; set; }
        public List<Brand> brands { get; set; }
        public List<NamedLocation> namedLocations { get; set; }
        public List<NamedPerson> namedPeople { get; set; }
        public List<AudioEffect> audioEffects { get; set; }
        public List<DetectedObject> detectedObjects { get; set; }
        public List<Sentiment> sentiments { get; set; }
        public List<Emotion> emotions { get; set; }
        public List<Block> blocks { get; set; }
        public List<FramePattern> framePatterns { get; set; }
        public List<Speaker> speakers { get; set; }
        public TextualContentModeration textualContentModeration { get; set; }
        public Statistics statistics { get; set; }
    }

    public class Instance
    {
        public string adjustedStart { get; set; }
        public string adjustedEnd { get; set; }
        public string start { get; set; }
        public string end { get; set; }
        public string brandType { get; set; }
        public string instanceSource { get; set; }
        public double confidence { get; set; }
        public List<string> thumbnailsIds { get; set; }
        public string thumbnailId { get; set; }
    }

    public class KeyFrame
    {
        public int id { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Keyword
    {
        public bool isTranscript { get; set; }
        public int id { get; set; }
        public string name { get; set; }
        public List<Appearance> appearances { get; set; }
        public string text { get; set; }
        public double confidence { get; set; }
        public string language { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Label
    {
        public int id { get; set; }
        public string name { get; set; }
        public List<Appearance> appearances { get; set; }
        public string referenceId { get; set; }
        public string language { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class NamedLocation
    {
        public string referenceId { get; set; }
        public string referenceUrl { get; set; }
        public double confidence { get; set; }
        public string description { get; set; }
        public double seenDuration { get; set; }
        public int id { get; set; }
        public string name { get; set; }
        public List<Appearance> appearances { get; set; }
        public List<object> tags { get; set; }
        public bool isCustom { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class NamedPerson
    {
        public string referenceId { get; set; }
        public string referenceUrl { get; set; }
        public double confidence { get; set; }
        public string description { get; set; }
        public double seenDuration { get; set; }
        public int id { get; set; }
        public string name { get; set; }
        public List<Appearance> appearances { get; set; }
        public List<object> tags { get; set; }
        public bool isCustom { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Ocr
    {
        public int id { get; set; }
        public string text { get; set; }
        public double confidence { get; set; }
        public int left { get; set; }
        public int top { get; set; }
        public int width { get; set; }
        public int height { get; set; }
        public int angle { get; set; }
        public string language { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Range
    {
        public string start { get; set; }
        public string end { get; set; }
    }


    public class Scene
    {
        public int id { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Sentiment
    {
        public string sentimentKey { get; set; }
        public double seenDurationRatio { get; set; }
        public List<Appearance> appearances { get; set; }
        public int id { get; set; }
        public double averageScore { get; set; }
        public string sentimentType { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Shot
    {
        public int id { get; set; }
        public List<string> tags { get; set; }
        public List<KeyFrame> keyFrames { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Speaker
    {
        public int id { get; set; }
        public string name { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class SpeakerLongestMonolog
    {
        [JsonProperty("1")]
        public int _1 { get; set; }

        [JsonProperty("2")]
        public int _2 { get; set; }
    }

    public class SpeakerNumberOfFragments
    {
        [JsonProperty("1")]
        public int _1 { get; set; }

        [JsonProperty("2")]
        public int _2 { get; set; }
    }

    public class SpeakerTalkToListenRatio
    {
        [JsonProperty("1")]
        public double _1 { get; set; }

        [JsonProperty("2")]
        public double _2 { get; set; }
    }

    public class SpeakerWordCount
    {
        [JsonProperty("1")]
        public int _1 { get; set; }

        [JsonProperty("2")]
        public int _2 { get; set; }
    }

    public class Statistics
    {
        public int correspondenceCount { get; set; }
        public SpeakerTalkToListenRatio speakerTalkToListenRatio { get; set; }
        public SpeakerLongestMonolog speakerLongestMonolog { get; set; }
        public SpeakerNumberOfFragments speakerNumberOfFragments { get; set; }
        public SpeakerWordCount speakerWordCount { get; set; }
    }

    public class SummarizedInsights
    {
        public string name { get; set; }
        public string id { get; set; }
        public string privacyMode { get; set; }
        public Duration duration { get; set; }
        public string thumbnailVideoId { get; set; }
        public string thumbnailId { get; set; }
        public List<Face> faces { get; set; }
        public List<Keyword> keywords { get; set; }
        public List<Sentiment> sentiments { get; set; }
        public List<Emotion> emotions { get; set; }
        public List<AudioEffect> audioEffects { get; set; }
        public List<Label> labels { get; set; }
        public List<FramePattern> framePatterns { get; set; }
        public List<Brand> brands { get; set; }
        public List<NamedLocation> namedLocations { get; set; }
        public List<NamedPerson> namedPeople { get; set; }
        public Statistics statistics { get; set; }
        public List<Topic> topics { get; set; }
    }

    public class TextualContentModeration
    {
        public int id { get; set; }
        public int bannedWordsCount { get; set; }
        public int bannedWordsRatio { get; set; }
        public List<object> instances { get; set; }
    }

    public class Thumbnail
    {
        public string id { get; set; }
        public string fileName { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Topic
    {
        public string referenceUrl { get; set; }
        public string iptcName { get; set; }
        public string iabName { get; set; }
        public double confidence { get; set; }
        public int id { get; set; }
        public string name { get; set; }
        public List<Appearance> appearances { get; set; }
        public string referenceId { get; set; }
        public string fullName { get; set; }
        public string referenceType { get; set; }
        public string language { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Transcript
    {
        public int id { get; set; }
        public string text { get; set; }
        public double confidence { get; set; }
        public int speakerId { get; set; }
        public string language { get; set; }
        public List<Instance> instances { get; set; }
    }

    public class Video
    {
        public string accountId { get; set; }
        public string id { get; set; }
        public string state { get; set; }
        public string moderationState { get; set; }
        public string reviewState { get; set; }
        public string privacyMode { get; set; }
        public string processingProgress { get; set; }
        public string failureMessage { get; set; }
        public object externalId { get; set; }
        public object externalUrl { get; set; }
        public object metadata { get; set; }
        public Insights insights { get; set; }
        public string thumbnailId { get; set; }
        public int width { get; set; }
        public int height { get; set; }
        public bool detectSourceLanguage { get; set; }
        public string languageAutoDetectMode { get; set; }
        public string sourceLanguage { get; set; }
        public List<string> sourceLanguages { get; set; }
        public string language { get; set; }
        public List<string> languages { get; set; }
        public string indexingPreset { get; set; }
        public string streamingPreset { get; set; }
        public string linguisticModelId { get; set; }
        public string personModelId { get; set; }
        public object logoGroupId { get; set; }
        public bool isAdult { get; set; }
        public List<object> excludedAIs { get; set; }
        public bool isSearchable { get; set; }
        public string publishedUrl { get; set; }
        public object publishedProxyUrl { get; set; }
        public object viewToken { get; set; }
    }

    public class VideosRange
    {
        public string videoId { get; set; }
        public Range range { get; set; }
    }

 

En futuros artículos, exploraremos cómo utilizar la información extraída por Azure Video Indexer para construir un buscador de videos robusto. Este buscador se basará en Azure AI Search para el almacenamiento y la búsqueda de datos, Ada 002 para la generación de vectores semánticos a partir de las transcripciones, y Node.js para el desarrollo del backend.

 

Como demostración temporal de esta prueba de concepto (POC), puedes acceder a una versión funcional en la siguiente URL: https://buscador-para-videos-ia.azurewebsites.net .

 

Poc Video Indexer

Ten en cuenta que esta POC es provisional y podría ser desactivada en cualquier momento.

Deja un comentario