Ce que vous faites est comme le titre l'indique, mais le contenu concerne principalement l'utilisation de Jackson
.
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
.
Le résultat de l'appel est le suivant (il est long, donc pliez-le).
<détails> 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. Cette fois, nous allons mapper aux objets suivants ( Dans l'annotation suivante, le type de destination de la carte est contrôlé par la valeur de 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. 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.{
"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
Objet de destination de la carte
@ 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
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")
})
@JsonIgnoreProperties(ignoreUnknown = true)
Mapper de la chaîne de résultat de la sonde au tableau de flux
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());
}