[Java] Affiche le résultat de ffprobe -show_streams dans JSON et mappe-le à un objet dans Jackson

Ce que vous faites est comme le titre l'indique, mais le contenu concerne principalement l'utilisation de Jackson.

spécification de l'option ffprobe

ffprobe fonctionne comme suit.

cat ${nom de fichier} | ffprobe -hide_banner -v error -print_format json -show_streams  -i pipe:0

J'ai précisé diverses choses, mais les deux points suivants sont importants.

---print_format json-> Résultat du traitement de sortie au format JSON ---show_streams-> Sortie de chaque information de flux comme le son, la vidéo, les sous-titres, etc.

Veuillez consulter l'article suivant pour savoir comment appeler depuis Java.

Résultat de l'appel

Le résultat de l'appel est le suivant (il est long, donc pliez-le).

<détails>

Résultat de l'appel </ summary>

{
    "streams": [
        {
            "index": 0,
            "codec_name": "h264",
            "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
            "profile": "Main",
            "codec_type": "video",
            "codec_time_base": "752/45075",
            "codec_tag_string": "avc1",
            "codec_tag": "0x31637661",
            "width": 1920,
            "height": 1080,
            "coded_width": 1920,
            "coded_height": 1088,
            "has_b_frames": 1,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "16:9",
            "pix_fmt": "yuv420p",
            "level": 41,
            "color_range": "tv",
            "chroma_location": "left",
            "refs": 1,
            "is_avc": "true",
            "nal_length_size": "4",
            "r_frame_rate": "30000/1001",
            "avg_frame_rate": "45075/1504",
            "time_base": "1/30000",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 601600,
            "duration": "20.053333",
            "bit_rate": "6653705",
            "bits_per_raw_sample": "8",
            "nb_frames": "601",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0
            },
            "tags": {
                "creation_time": "2014-03-30T07:09:03.000000Z",
                "language": "eng",
                "handler_name": "\u001fMainconcept Video Media Handler",
                "encoder": "AVC Coding"
            }
        },
        {
            "index": 1,
            "codec_name": "aac",
            "codec_long_name": "AAC (Advanced Audio Coding)",
            "profile": "LC",
            "codec_type": "audio",
            "codec_time_base": "1/48000",
            "codec_tag_string": "mp4a",
            "codec_tag": "0x6134706d",
            "sample_fmt": "fltp",
            "sample_rate": "48000",
            "channels": 2,
            "channel_layout": "stereo",
            "bits_per_sample": 0,
            "r_frame_rate": "0/0",
            "avg_frame_rate": "0/0",
            "time_base": "1/48000",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 962560,
            "duration": "20.053333",
            "bit_rate": "317375",
            "max_bit_rate": "317625",
            "nb_frames": "942",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0
            },
            "tags": {
                "creation_time": "2014-03-30T07:09:03.000000Z",
                "language": "eng",
                "handler_name": "#Mainconcept MP4 Sound Media Handler"
            }
        }
    ]
}

Carte par Jackson

Je mapperai le résultat de la sonde que j'ai obtenu plus tôt à l'objet. La sortie sera un tableau de flux dans la vidéo.

Objet de destination de la carte

Cette fois, nous allons mapper aux objets suivants (@ Getter et @ Setter sont écrits en supposant lombok). La base du résultat est «stream» et les types sont séparés par «video» ou «audio» (ou autre).

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "codec_type", defaultImpl = NoClass.class)
@JsonSubTypes({
        @JsonSubTypes.Type(value = FfprobeStream.VideoStream.class, name = "video"),
        @JsonSubTypes.Type(value = FfprobeStream.AudioStream.class, name = "audio")
})
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Setter
abstract class FfprobeStream {
    private Double duration;
    private String codecName;

    @Getter @Setter
    static class VideoStream extends FfprobeStream {
        private Integer width;
        private Integer height;
    }

    @Getter @Setter
    static class AudioStream extends FfprobeStream {
        private String channelLayout;
    }
}

Commentaire

Dans l'annotation suivante, le type de destination de la carte est contrôlé par la valeur de codec_type. Il n'y a aucun moyen de créer un objet divin et de le mapper là-bas, mais il est plus facile de faire le reste, il est donc préférable de contrôler le type de destination de la carte.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "codec_type", defaultImpl = NoClass.class)
@JsonSubTypes({
        @JsonSubTypes.Type(value = FfprobeStream.VideoStream.class, name = "video"),
        @JsonSubTypes.Type(value = FfprobeStream.AudioStream.class, name = "audio")
})

Les annotations suivantes ignorent les champs qui ne peuvent pas être mappés. Cette fois, seuls certains champs du résultat sont préparés, donc si vous ne le spécifiez pas, vous obtiendrez une erreur si vous ne pouvez pas mapper.

@JsonIgnoreProperties(ignoreUnknown = true)

Mapper de la chaîne de résultat de la sonde au tableau de flux

Vous pouvez mapper les résultats de la sonde à un tableau de flux dans votre vidéo avec le code suivant. Les détails sont comme commentés.

static List<FfprobeStream> parseFfprobeResult(String ffprobeResult) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    //Stratégie de dénomination des propriétés.SNAKE_Puisqu'il s'agit d'un JSON de CASE, spécifiez-le comme tel
    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

    // JSON ->Implémentation de la conversion d'objets Java
    Map<String, List<FfprobeStream>> map
            = mapper.readValue(ffprobeResult, new TypeReference<Map<String, List<FfprobeStream>>>() {});

    //Puisque le résultat de l'analyse sort dans Map, obtenez et retournez en spécifiant le paramètre
    return map.getOrDefault("streams", Collections.emptyList());
}

Recommended Posts

[Java] Affiche le résultat de ffprobe -show_streams dans JSON et mappe-le à un objet dans Jackson
JSON en Java et Jackson Partie 1 Renvoyer JSON à partir du serveur
Assurez-vous de comparer le résultat Java compareTo avec 0
[Java] Je veux effectuer distinctement avec la clé dans l'objet
[Android] Convertissez Map en JSON à l'aide de GSON avec Kotlin et Java
Comment obtenir la longueur d'un fichier audio avec Java
Comment incrémenter la valeur de Map sur une ligne en Java
Représentez graphiquement les informations du capteur de Raspberry Pi en Java et vérifiez-les avec un navigateur Web
Obtenez le résultat de POST en Java
Sortie du livre "Introduction à Java"
JSON en Java et Jackson Part ③ Incorporer JSON dans HTML et l'utiliser à partir de JavaScript
Exemple de code pour la sérialisation et la désérialisation des énumérations Java Enum et JSON dans Jackson
L'histoire de l'oubli de fermer un fichier en Java et de l'échec
Développement Android, comment vérifier null dans la valeur de l'objet JSON
Une erreur s'est produite dans le cours gratuit de RubyOnRails Udemy, l'a résolue et est allée jusqu'au bout
J'ai reçu les données du voyage (application agenda) en Java et j'ai essayé de les visualiser # 001
JSON avec Java et Jackson Part 2 XSS mesures
Faire correspondre le JSON du cas du serpent au champ du cas du chameau en Java (JVM)
[Java] Est-il inutile de vérifier "l'identité" dans l'implémentation de la méthode equals ()?
Branchement conditionnel du résultat de l'instruction SQL pour n'en rechercher qu'une seule en Java
Je veux trouver la somme de contrôle MD5 d'un fichier en Java et obtenir le résultat sous forme de chaîne de caractères en notation hexadécimale.
[Développement Android] Obtenez des images du serveur avec Java et définissez-les dans ImageView! !!
[Java] Comment obtenir la clé et la valeur stockées dans Map par traitement itératif
Comment utiliser git avec la puissance de jgit dans un environnement sans commandes git
[Ruby] Différence entre obtenir et publier
Obtenez le résultat de POST en Java
Je souhaite renvoyer un objet au format CSV avec en-tête et filtre multilignes en Java
Résumé de l'utilisation du jeu de proxy dans IE lors de la connexion avec Java
Convertir JSON et YAML en Java (en utilisant Jackson et SnakeYAML)
Convertir l'énumération Java et JSON vers et depuis Jackson
Convertit le tableau d'erreurs.full_messages en caractères et sortie
[Java] Convertir JSON en Java et Java en JSON-Comment utiliser GSON et Jackson-
[Mémo] Le mouvement mystérieux de My Batis, définissez null sur l'élément de l'objet liste et renvoyez-le.
Un programme (Java) qui génère la somme des nombres pairs et impairs dans un tableau
Stocker dans une carte Java 2D et tourner avec pour instruction
[Note] Sortie Java de la somme des éléments pairs et impairs
J'ai essayé de résumer les bases de kotlin et java
Commande pour vérifier le nombre et l'état des threads Java
Initialisation avec une chaîne vide vers une instance de type Java String
Que s'est-il passé dans «Java 8 to Java 11» et comment créer un environnement
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3
Comment dériver le dernier jour du mois en Java
[Java] Communication JSON avec jackson
[Rails] Obtenez access_token au moment de l'authentification Twitter avec Sorcery et enregistrez-le dans la base de données
J'ai essayé d'exprimer les résultats avant et après de la classe Date avec une ligne droite numérique
[Java] Comment rechercher des valeurs dans un tableau (ou une liste) avec la méthode contains
Convertissez Excel en Blob avec java, enregistrez-le, lisez-le à partir de DB et exportez-le sous forme de fichier!
Lisez les données de Shizuoka Prefecture Point Cloud DB avec Java et essayez de détecter la hauteur de l'arbre.
Générez un numéro de série avec TableGenerator of Hibernate (JPA) et stockez-le dans l'ID de String.
[Java] Divers résumés joints aux chefs de classe et aux membres
Il ne répond pas à la description en .js du fichier packs
[Java] Obtenez les dates des derniers lundi et dimanche dans l'ordre
Je veux revenir à l'écran précédent avec kotlin et java!
Sortie de la différence entre chaque champ de deux objets en Java
J'ai essayé le type d'entrée / sortie de Java Lambda ~ Map edition ~
Comment afficher la valeur lorsqu'il y a un tableau dans le tableau
L'histoire de toString () commençant par le passage d'un tableau à System.out.println
La milliseconde définie dans /lib/calendars.properties de Java jre est UTC
Convertir un tableau de chaînes en une liste d'entiers en Java
Lire les 4 premiers octets du fichier de classe Java et générer CAFEBABE