如何构建 jq 过滤器以从 ffprobe 返回视频和音频编解码器信息?

如何构建 jq 过滤器以从 ffprobe 返回视频和音频编解码器信息?

为了标准化我的视频库,我试图找到一种方法来快速创建需要转换的文件列表。在查看问题及其答案(以及大量的谷歌搜索)我想我已经弄清楚了基础知识,但我在阐述 jq 部分时遇到了麻烦。作为参考,我开始使用的 jq 命令如下:

jq -c '.format.filename as $path | 
    .streams[]? | 
    select(.codec_type=="video" and .codec_name!="h264") | 
    .codec_name as $vcodec | 
    {video: $vcodec, path: $path}'

为了简单起见,我们假设这是输入到 jq 的内容:

{
    "streams": [
        {
            "index": 0,
            "codec_name": "hevc",
            "codec_type": "video"
        },
        {
            "index": 1,
            "codec_name": "aac",
            "codec_type": "audio"
        }
    ],
    "format": {
        "filename": "Video.mkv"
    }
}

输出结果如下:

{"video":"hevc","path":"./Video.mkv"}

这很棒,但我想更进一步 - 我还想包含用于任何音频流的编解码器。因此,给定相同的输入,我希望得到以下输出:

{"video":"hevc","audio":"aac","path":"./Video.mkv"}

我如何实现这个目标?

答案1

要选择音频和视频编解码器类型并排除h264视频:

$ jq '.format.filename as $path |
    [.streams[]? | select(.codec_type=="audio" 
                          or (.codec_type=="video" 
                              and .codec_name!="h264")) | 
     {(.codec_type): .codec_name, $path}] | 
    group_by(.path) | map(add) | .[]' input.json
$ jq --version      
jq-1.5-1-a5b5cbe  

如果 shell 命令变得复杂并且需要多行代码;我会切换到更详细的 Python 来管理复杂性:

result = dict(path=data['format']['filename'])
for stream in data['streams']:
    if (stream['codec_type'] == 'audio'
        or (stream['codec_type'] == 'video'
            and stream['codec_name'] != 'h264')):
        result[stream['codec_type']] = stream['codec_name'] # last value wins

data是输入(data = json.loads(json_text)),result是期望输出(print(json.dumps(result)))。

如果您更熟悉 Python 中的命令式编程,而不是更具函数式风格的编程,那么根据您的特定情况调整上述代码应该相对简单jq

答案2

这是另一种方法。

$ jq -M '
  def getpath: {path: .format.filename} ;
  def getcodecs: [
        .streams[]?
      | {(.codec_type):.codec_name}
      | if . == {"video":"h264"} then empty else . end
    ] | add
  ;
  getpath + getcodecs
  ' input.json

输出

{
  "path": "Video.mkv",
  "video": "hevc",
  "audio": "aac"
}

相关内容