Мне нужно извлечь codec_name второго видеопотока (изображение) из видеофайла.

Итак, я делаю это:

$ ffprobe -hide_banner -v error -show_streams -of json Resurrection_Sunday_Online_Experience_12_April_2020_5.30pm_New_Creation_Church.mp4  | jq . > ffmpeg_output.json

Файл JSON выглядит так:

$  cat ffmpeg_output.json
{
  "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": "1411877/84712500",
      "codec_tag_string": "avc1",
      "codec_tag": "0x31637661",
      "width": 854,
      "height": 480,
      "coded_width": 864,
      "coded_height": 480,
      "has_b_frames": 0,
      "sample_aspect_ratio": "1:1",
      "display_aspect_ratio": "427:240",
      "pix_fmt": "yuv420p",
      "level": 31,
      "color_range": "tv",
      "color_space": "bt709",
      "color_transfer": "bt709",
      "color_primaries": "bt709",
      "chroma_location": "left",
      "refs": 1,
      "is_avc": "true",
      "nal_length_size": "4",
      "r_frame_rate": "30/1",
      "avg_frame_rate": "42356250/1411877",
      "time_base": "1/90000",
      "start_pts": 0,
      "start_time": "0.000000",
      "duration_ts": 677700960,
      "duration": "7530.010667",
      "bit_rate": "387395",
      "bits_per_raw_sample": "8",
      "nb_frames": "225900",
      "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": {
        "language": "und",
        "handler_name": "VideoHandler"
      }
    },
    {
      "index": 1,
      "codec_name": "aac",
      "codec_long_name": "AAC (Advanced Audio Coding)",
      "profile": "-1",
      "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": 361441280,
      "duration": "7530.026667",
      "bit_rate": "125374",
      "max_bit_rate": "129296",
      "nb_frames": "352970",
      "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": {
        "language": "und",
        "handler_name": "SoundHandler"
      }
    },
    {
      "index": 2,
      "codec_name": "mjpeg",
      "codec_long_name": "Motion JPEG",
      "profile": "192",
      "codec_type": "video",
      "codec_time_base": "0/1",
      "codec_tag_string": "[0][0][0][0]",
      "codec_tag": "0x0000",
      "width": 1280,
      "height": 720,
      "coded_width": 1280,
      "coded_height": 720,
      "has_b_frames": 0,
      "sample_aspect_ratio": "1:1",
      "display_aspect_ratio": "16:9",
      "pix_fmt": "yuvj420p",
      "level": -99,
      "color_range": "pc",
      "color_space": "bt470bg",
      "chroma_location": "center",
      "refs": 1,
      "r_frame_rate": "90000/1",
      "avg_frame_rate": "0/0",
      "time_base": "1/90000",
      "start_pts": 0,
      "start_time": "0.000000",
      "duration_ts": 677702430,
      "duration": "7530.027000",
      "bits_per_raw_sample": "8",
      "disposition": {
        "default": 0,
        "dub": 0,
        "original": 0,
        "comment": 0,
        "lyrics": 0,
        "karaoke": 0,
        "forced": 0,
        "hearing_impaired": 0,
        "visual_impaired": 0,
        "clean_effects": 0,
        "attached_pic": 1,
        "timed_thumbnails": 0
      }
    }
  ]
}

Я пытался это, но он не извлекает codec_name должным образом

$ cat ffmpeg_output.json | jq '[select(.streams[].codec_type=="video")][1].codec_name' 
null

Я также заметил, что он выбрал все потоки:

$ cat ffmpeg_output.json | jq '[select(.streams[].codec_type=="video")][1]' | grep codec_type      
      "codec_type": "video",
      "codec_type": "audio",
      "codec_type": "video",

Можешь мне помочь ?

2
SebMa 28 Апр 2020 в 11:02

2 ответа

Ваш jq фильтр просто неверен. Ваше select() выражение неверно. Помните, что select() выражение возвращает логическое значение, и ваше условие .streams[].codec_type=="video" подтверждается true для двух из предоставленных входных объектов, т.е. для streams с "index": 0 и {{ X7}}, и для каждого из этих истинных условий фильтр печатает все 3 объекта, т.е. реплицирует весь JSON, потому что select() был на верхнем уровне. Вам нужно сделать select() после .streams

.streams[] | select(.codec_type=="video").codec_name

Для выбора объекта по определенному индексу используйте стандартную запись массива .[0], .[1]

[ .streams[] | select(.codec_type=="video") ][1] | .codec_name
1
Inian 28 Апр 2020 в 08:47

Вам не нужен JQ для этого.

$ ffprobe -hide_banner -v error -of compact=nk=1:p=0 -select_streams v:1 -show_entries stream=codec_name video.mp4
h264
1
oguz ismail 28 Апр 2020 в 08:18