为了标准化我的视频库,我试图找到一种方法来快速创建需要转换的文件列表。在查看这问题及其答案(以及大量的谷歌搜索)我想我已经弄清楚了基础知识,但我在阐述 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"
}