mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-23 19:31:44 +00:00
mkvmerge: output warnings/errors as JSON in JSON identification mode
Implements #1537.
This commit is contained in:
parent
de4734f962
commit
a3a25225c6
@ -1,5 +1,10 @@
|
||||
2015-12-16 Moritz Bunkus <moritz@bunkus.org>
|
||||
|
||||
* mkvmerge: enhancement: if JSON identification mode is active
|
||||
then warnings and errors will be output as JSON as well. They're
|
||||
output as arrays of strings as the keys "warnings" and "errors" of
|
||||
the main JSON object. Implements #1537.
|
||||
|
||||
* all: reversion of a change: several ISO 639-2 codes of languages
|
||||
that are very old and not spoken anymore have been re-added
|
||||
(e.g. "English, Middle (1100-1500)") due to feedback from users
|
||||
|
345
doc/json-schema/mkvmerge-identification-output-schema-v2.json
Normal file
345
doc/json-schema/mkvmerge-identification-output-schema-v2.json
Normal file
@ -0,0 +1,345 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "https://mkvtoolnix.download/doc/mkvmerge-identification-output-schema-v2.json",
|
||||
"title": "mkvmerge identification output",
|
||||
"description": "The JSON output produced by mkvmerge's file identification mode",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attachments": {
|
||||
"description": "an array describing the attachments found if any",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content_type": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"file_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uid": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"file_name",
|
||||
"id",
|
||||
"properties",
|
||||
"size"
|
||||
]
|
||||
}
|
||||
},
|
||||
"chapters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"num_entries": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"num_entries"
|
||||
]
|
||||
}
|
||||
},
|
||||
"container": {
|
||||
"description": "information about the identified container",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"properties": {
|
||||
"description": "additional properties for the container varying by container format",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"container_type": {
|
||||
"description": "A unique number identifying the container type that's supposed to stay constant over all future releases of MKVToolNix",
|
||||
"type": "integer",
|
||||
"minLength": 1
|
||||
},
|
||||
"duration": {
|
||||
"description": "The file's/segment's duration in nanoseconds",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"is_providing_timecodes": {
|
||||
"description": "States whether or not the container has timestamps for the packets (e.g. Matroska, MP4) or not (e.g. SRT, MP3)",
|
||||
"type": "boolean"
|
||||
},
|
||||
"segment_uid": {
|
||||
"description": "A hexadecimal string of the segment's UID (only for Matroska files)",
|
||||
"type": "string",
|
||||
"minLength": 32,
|
||||
"maxLength": 32
|
||||
},
|
||||
"next_segment_uid": {
|
||||
"description": "A hexadecimal string of the next segment's UID (only for Matroska files)",
|
||||
"type": "string",
|
||||
"minLength": 32,
|
||||
"maxLength": 32
|
||||
},
|
||||
"previous_segment_uid": {
|
||||
"description": "A hexadecimal string of the previous segment's UID (only for Matroska files)",
|
||||
"type": "string",
|
||||
"minLength": 32,
|
||||
"maxLength": 32
|
||||
},
|
||||
"other_file": {
|
||||
"description": "The file name of an additional file processed as well",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"playlist": {
|
||||
"description": "States whether or not the identified file is a playlist (e.g. MPLS) referring to several other files",
|
||||
"type": "boolean"
|
||||
},
|
||||
"playlist_chapters": {
|
||||
"description": "The number of chapters in a playlist if it is a one",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"playlist_duration": {
|
||||
"description": "The total duration in nanoseconds of all files referenced by the playlist if it is a one",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"playlist_size": {
|
||||
"description": "The total size in bytes of all files referenced by the playlist if it is a one",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"recognized": {
|
||||
"description": "States whether or not mkvmerge knows about the format",
|
||||
"type": "boolean"
|
||||
},
|
||||
"supported": {
|
||||
"description": "States whether or not mkvmerge can read the format",
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"description": "A human-readable description/name for the container format",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"recognized",
|
||||
"supported"
|
||||
]
|
||||
},
|
||||
"errors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"file_name": {
|
||||
"description": "the identified file's name",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"global_tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
}
|
||||
},
|
||||
"identification_format_version": {
|
||||
"description": "The output format's version",
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"track_tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"num_entries": {
|
||||
"type": "integer"
|
||||
},
|
||||
"track_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"num_entries",
|
||||
"track_id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"tracks": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"codec": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"minLength": 0
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aac_is_sbr": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"true",
|
||||
"false",
|
||||
"unknown"
|
||||
]
|
||||
},
|
||||
"audio_bits_per_sample": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"audio_channels": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"audio_sampling_frequency": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"codec_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"codec_private_data": {
|
||||
"type": "string"
|
||||
},
|
||||
"codec_private_length": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"content_encoding_algorithms": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"default_duration": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"default_track": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"display_dimensions": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+x[0-9]+$"
|
||||
},
|
||||
"enabled_track": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"forced_track": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"number": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"packetizer": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"pixel_dimensions": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+x[0-9]+$"
|
||||
},
|
||||
"stereo_mode": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"stream_id": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-f]{2}$"
|
||||
},
|
||||
"sub_stream_id": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-f]{2}$"
|
||||
},
|
||||
"tag_artist": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag_bitsps": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag_bps": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag_fps": {
|
||||
"type": "string"
|
||||
},
|
||||
"tag_title": {
|
||||
"type": "string"
|
||||
},
|
||||
"text_subtitles": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"track_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"ts_pid": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"uid": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"codec",
|
||||
"id",
|
||||
"type"
|
||||
]
|
||||
}
|
||||
},
|
||||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -33,6 +33,44 @@ charset_converter_cptr g_cc_stdio = charset_converter_cptr(new charset_converter
|
||||
std::shared_ptr<mm_io_c> g_mm_stdio = std::shared_ptr<mm_io_c>(new mm_stdio_c);
|
||||
|
||||
static mxmsg_handler_t s_mxmsg_info_handler, s_mxmsg_warning_handler, s_mxmsg_error_handler;
|
||||
static std::vector<std::string> s_warnings_emitted, s_errors_emitted;
|
||||
|
||||
static nlohmann::json
|
||||
to_json_array(std::vector<std::string> const &messages) {
|
||||
auto result = nlohmann::json::array();
|
||||
|
||||
for (auto const &message : messages)
|
||||
result.push_back(message);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
display_json_output(nlohmann::json json) {
|
||||
json["warnings"] = to_json_array(s_warnings_emitted);
|
||||
json["errors"] = to_json_array(s_errors_emitted);
|
||||
|
||||
mxinfo(boost::format("%1%\n") % json.dump(2));
|
||||
}
|
||||
|
||||
static void
|
||||
json_warning_error_handler(unsigned int level,
|
||||
std::string const &message) {
|
||||
if (MXMSG_WARNING == level)
|
||||
s_warnings_emitted.push_back(message);
|
||||
|
||||
else {
|
||||
s_errors_emitted.push_back(message);
|
||||
display_json_output(nlohmann::json{});
|
||||
mxexit(2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
redirect_warnings_and_errors_to_json() {
|
||||
set_mxmsg_handler(MXMSG_WARNING, json_warning_error_handler);
|
||||
set_mxmsg_handler(MXMSG_ERROR, json_warning_error_handler);
|
||||
}
|
||||
|
||||
void
|
||||
redirect_stdio(const mm_io_cptr &stdio) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "common/locale.h"
|
||||
#include "common/mm_io.h"
|
||||
#include "nlohmann-json/src/json.hpp"
|
||||
|
||||
using namespace libebml;
|
||||
|
||||
@ -36,6 +37,9 @@ extern std::shared_ptr<mm_io_c> g_mm_stdio;
|
||||
void redirect_stdio(const mm_io_cptr &new_stdio);
|
||||
bool stdio_redirected();
|
||||
|
||||
void redirect_warnings_and_errors_to_json();
|
||||
void display_json_output(nlohmann::json json);
|
||||
|
||||
void init_common_output(bool no_charset_detection);
|
||||
void set_cc_stdio(const std::string &charset);
|
||||
|
||||
|
@ -415,7 +415,7 @@ generic_reader_c::display_identification_results_as_json() {
|
||||
};
|
||||
|
||||
auto json = nlohmann::json{
|
||||
{ "identification_format_version", 1 },
|
||||
{ "identification_format_version", 2 },
|
||||
{ "file_name", m_ti.m_fname },
|
||||
{ "tracks", nlohmann::json::array() },
|
||||
{ "attachments", nlohmann::json::array() },
|
||||
@ -465,7 +465,7 @@ generic_reader_c::display_identification_results_as_json() {
|
||||
};
|
||||
}
|
||||
|
||||
mxinfo(boost::format("%1%\n") % json.dump(2));
|
||||
display_json_output(json);
|
||||
}
|
||||
|
||||
std::string
|
||||
|
@ -33,7 +33,7 @@ static void
|
||||
output_container_unsupported_json(std::string const &filename,
|
||||
translatable_string_c const &info) {
|
||||
auto json = nlohmann::json{
|
||||
{ "identification_format_version", 1 },
|
||||
{ "identification_format_version", 2 },
|
||||
{ "file_name", filename },
|
||||
{ "container", {
|
||||
{ "recognized", true },
|
||||
@ -42,7 +42,7 @@ output_container_unsupported_json(std::string const &filename,
|
||||
} },
|
||||
};
|
||||
|
||||
mxinfo(boost::format("%1%\n") % json.dump(2));
|
||||
display_json_output(json);
|
||||
|
||||
mxexit(0);
|
||||
}
|
||||
|
@ -369,7 +369,7 @@ list_file_types() {
|
||||
static void
|
||||
display_unsupported_file_type_json(filelist_t const &file) {
|
||||
auto json = nlohmann::json{
|
||||
{ "identification_format_version", 1 },
|
||||
{ "identification_format_version", 2 },
|
||||
{ "file_name", file.name },
|
||||
{ "container", {
|
||||
{ "recognized", false },
|
||||
@ -377,7 +377,7 @@ display_unsupported_file_type_json(filelist_t const &file) {
|
||||
} },
|
||||
};
|
||||
|
||||
mxinfo(boost::format("%1%\n") % json.dump(2));
|
||||
display_json_output(json);
|
||||
|
||||
mxexit(0);
|
||||
}
|
||||
@ -1843,10 +1843,11 @@ parse_arg_identification_format(std::vector<std::string>::const_iterator &sit,
|
||||
else if (next_arg == "gui")
|
||||
g_identification_output_format = identification_output_format_e::gui;
|
||||
|
||||
else if (next_arg == "json")
|
||||
else if (next_arg == "json") {
|
||||
g_identification_output_format = identification_output_format_e::json;
|
||||
redirect_warnings_and_errors_to_json();
|
||||
|
||||
else
|
||||
} else
|
||||
mxerror(boost::format(Y("Invalid identification format in '%1% %2%'.\n")) % *sit % *(sit + 1));
|
||||
|
||||
++sit;
|
||||
|
@ -357,6 +357,6 @@ T_508splitting_by_parts_with_segment_linking:existence0-true-true-true-existence
|
||||
T_509rerender_track_headers_chapters_attachments:1ad646e49e231108ed8b5d1c6dce8b1c:passed:20151115-230226:0.287840782
|
||||
T_510propedit_add_attachments_without_meta_seek_present:770103c238a0f502c9ec55f0599d8544:passed:20151121-101043:0.070892905
|
||||
T_511propedit_ensure_seek_head_exists_at_front:20f53afd94e39f5bbf3f1091eefbe31d:passed:20151129-194025:0.152563199
|
||||
T_512json_identification:231941d7da79ca0eab3f8f5cd2a66e3c-ok-793233ac68c8c0af280898ec33aa6e05-ok-06dde7e7bcbec8fc9cd8f101662906dd-ok-8797f2adcd279428afa4834d93f0be34-ok-90de565f88767c95673e7b2d5ecf85d9-ok-d9c71aaad86e27979d1b5bf71cb1143f-ok-acddfd1324aa62e187f8d4023f24ec2a-ok-6c20b604bd1652766e442bf52f284a18-ok-cdf24911aad494277fd2a032affdf498-ok-dd2d4b55d2fe3f56c697371325b7d8e9-ok-7dc0464e838aa187128964387b9adcba-ok-6d365dd230156e30bfe3d60a3c6c24dc-ok-7fada0edcbd9818093ba57b78ae5706a-ok-ca5e66fad9ed5af2d672c4432cbded48-ok-b859b2500847aca0ac91918fdc8eae70-ok:passed:20151207-223859:6.280036064
|
||||
T_512json_identification:dc56910afee27e5f42414fde294a262c-ok-4d5b44ce8fea381a4de100ed77ee77bc-ok-4ce52c415319a3c9ace3394b251bfa04-ok-b31447af73fb7453a6801f6817a5f904-ok-d9eb73880861a423ee0d33364685d0a5-ok-4147bc09272d6a650f3ebac47008129a-ok-966a3a948e86b73f25d0cbd20e659dda-ok-5105d97f6ca79db07caab7bb66f12ef4-ok-76d5c58b6fc06efcfea66e447ad8bf44-ok-bb52b7e2c30f3741c92e5152bef8ea8a-ok-8dd46981cf9e1787ea682fe03aba4d92-ok-ebaf88003f5d09295d18e255edf689be-ok-c56940a2497513380531e693ec06b76c-ok-ee1ae1f2602ebaef4e83772ab5e39804-ok-617e011e200630baff85bc674b2a1292-ok:passed:20151207-223859:6.280036064
|
||||
T_513vp9_10bit_key_frame_detection:9eab6e85ec792dcf670873d70a87f6ea:passed:20151208-224613:0.267556245
|
||||
T_514remove_track_statistics_tags_during_remux:022578a22c45c06ab23dc453df71f7c0-afe190e36be530592fe3b83fb28d3e69-a7f246fe02132a1fb9cd3d7d0f85f180:passed:20151215-134129:1.426290351
|
||||
|
@ -302,7 +302,7 @@ class SimpleTest
|
||||
json_store = JsonSchema::DocumentStore.new
|
||||
parser = JsonSchema::Parser.new
|
||||
expander = JsonSchema::ReferenceExpander.new
|
||||
schema = parser.parse JSON.load(File.read("../doc/json-schema/mkvmerge-identification-output-schema-v1.json"))
|
||||
schema = parser.parse JSON.load(File.read("../doc/json-schema/mkvmerge-identification-output-schema-v2.json"))
|
||||
|
||||
expander.expand(schema, store: json_store)
|
||||
json_store.add_schema schema
|
||||
|
Loading…
Reference in New Issue
Block a user