[Java] Output the result of ffprobe -show_streams in JSON and map it to an object with Jackson

What you do is as the title says, but the content is mainly about how to use Jackson.

ffprobe option specification

ffprobe works as follows.

cat ${file name} | ffprobe -hide_banner -v error -print_format json -show_streams  -i pipe:0

I have specified various things, but the following two points are important.

---print_format json-> Output processing result in JSON format ---show_streams-> Output each stream information such as sound, video, subtitles, etc.

Please refer to the following article for how to call from Java.

-[Java] Enter into stdin of Process -Qiita

Call result

The result of the call is as follows (it's long, so fold it).

Call result
{
    "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"
            }
        }
    ]
}

Map by Jackson

I will map the probe result I got earlier to the object. The output will be an array of streams in the video.

Map destination object

This time, we will map to the following objects (@ Getter and @ Setter are written assuming lombok). The basis of the result is stream, and the types are separated by video or ʻaudio` (or other).

@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;
    }
}

Commentary

In the following annotation, the type of the map destination is controlled by the value of codec_type. There is no way to create a god object and map it there, but it is easier to do the rest, so it is better to control the type of the map destination.

@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")
})

The following annotations ignore fields that cannot be mapped. This time, only some fields of the result are prepared, so if you do not specify this, you will get an error if you can not map.

@JsonIgnoreProperties(ignoreUnknown = true)

Map probe result string to stream array

You can map the probe results to an array of streams in your video with the following code. Details are as commented.

static List<FfprobeStream> parseFfprobeResult(String ffprobeResult) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    //ffprobe outputs Property Naming Strategy.SNAKE_Since it is JSON of CASE, specify it as such
    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

    // JSON ->Implement Java object conversion
    Map<String, List<FfprobeStream>> map
            = mapper.readValue(ffprobeResult, new TypeReference<Map<String, List<FfprobeStream>>>() {});

    //Since the parse result comes out in Map, get and return by specifying the parameter
    return map.getOrDefault("streams", Collections.emptyList());
}

Recommended Posts

[Java] Output the result of ffprobe -show_streams in JSON and map it to an object with Jackson
[Ruby] How to use the map method. How to process the value of an object and get it by hash or symbol.
JSON in Java and Jackson Part 1 Return JSON from the server
Be sure to compare the result of Java compareTo with 0
[Java] I want to perform distinct with the key in the object
[Android] Convert Map to JSON using GSON in Kotlin and Java
How to get the length of an audio file in java
How to increment the value of Map in one line in Java
Graph the sensor information of Raspberry Pi in Java and check it with a web browser
Get the result of POST in Java
Output of the book "Introduction to Java"
JSON in Java and Jackson Part ③ Embed JSON in HTML and use it from JavaScript
Sample code to serialize and deserialize Java Enum enums and JSON in Jackson
The story of forgetting to close a file in Java and failing
Android development, how to check null in the value of JSON object
An error occurred in the free course of RubyOnRails Udemy, solved it, and went through to the end
I received the data of the journey (diary application) in Java and visualized it # 001
JSON with Java and Jackson Part 2 XSS measures
Make the JSON of the snake case correspond to the field of the camel case in Java (JVM)
[Java] Is it unnecessary to check "identity" in the implementation of the equals () method?
Conditional branching of the result of SQL statement to search only one in Java
I want to find the MD5 checksum of a file in Java and get the result as a string in hexadecimal notation.
[Android development] Get an image from the server in Java and set it in ImageView! !!
[Java] How to get the key and value stored in Map by iterative processing
How to use git with the power of jgit in an environment without git commands
[Ruby] Difference between get and post
Get the result of POST in Java
I want to return an object in CSV format with multi-line header & filter in Java
Summary of how to use the proxy set in IE when connecting with Java
Convert JSON and YAML in Java (using Jackson and SnakeYAML)
Convert Java enum enums and JSON to and from Jackson
Convert the array of errors.full_messages to characters and output
[Java] Convert JSON to Java and Java to JSON-How to use GSON and Jackson-
Gzip-compress byte array in Java and output to file
[Memo] MyBatis's mysterious movement, set null to the element of the list object and return it.
A program (Java) that outputs the sum of odd and even numbers in an array
Store in Java 2D map and turn with for statement
[Note] Java Output of the sum of odd and even elements
I tried to summarize the basics of kotlin and java
Command to check the number and status of Java threads
Initialization with an empty string to an instance of Java String type
What happened in "Java 8 to Java 11" and how to build an environment
Even in Java, I want to output true with a == 1 && a == 2 && a == 3
How to derive the last day of the month in Java
[Java] JSON communication with jackson
[Rails] Get access_token at the time of Twitter authentication with Sorcery and save it in DB
I tried to express the result of before and after of Date class with a number line
[Java] How to search for a value in an array (or list) with the contains method
Convert Excel to Blob with java, save it, read it from DB and output it as a file!
Read the data of Shizuoka point cloud DB with Java and try to detect the tree height.
Generate a serial number with Hibernate (JPA) TableGenerator and store it in the Id of String.
[Java] Various summaries attached to the heads of classes and members
It doesn't respond to the description in .js of the packs file
[Java] Get the dates of the past Monday and Sunday in order
I want to return to the previous screen with kotlin and java!
Output the difference between each field of two objects in Java
I tried the input / output type of Java Lambda ~ Map edition ~
How to output the value when there is an array in the array
The story of toString () starting with passing an array to System.out.println
The milliseconds to set in /lib/calendars.properties of Java jre is UTC
Cast an array of Strings to a List of Integers in Java
Read the first 4 bytes of the Java class file and output CAFEBABE