Change audio settings in mkv files
Rename an audio or video track
I noticed that on multiple mkv files, the audio track was labeled as undefined.
The language was actually english, and it did work correctly, but the video player (correctly) showed tha language as undefined
.
With mkvpropedit
it is possible to change the reported language:
mkvpropedit "$file" --edit track:a1 --set language=eng
Valid languages codes are the ISO 639-2 codes, although I could not find a reference in the documentation.
A video track normally is not associated to a language, therefore it is fine to leave them as undefined
.
On the other hand, there are videos that have slightly different content in different languages. An example would be there is some text that is displayed and localized; for example the title of the movie, book covers and other signs.
This is not uncommon on DVD and Bluray, but I have never had a matroska file with multiple video tracks.
Just in case I might encounter one, the syntax for changing the video language is extremely similar
mkvpropedit "$file" --edit track:v1 --set language=eng
Print properties of file
mkvpropedit is only able to modify a file, to query the structure of a .mkv
file, use mkvinfo
+ EBML head
|+ EBML version: 1
|+ EBML read version: 1
|+ Maximum EBML ID length: 4
|+ Maximum EBML size length: 8
|+ Document type: matroska
|+ Document type version: 4
|+ Document type read version: 2
+ Segment: size 530593499
|+ Seek head (subentries will be skipped)
|+ EBML void: size 80
|+ Segment information
| + Timestamp scale: 1000000
| + Title: <redacted>
| + Multiplexing application: Lavf59.27.100
| + Writing application: HandBrake 1.6.1 2023012900
| + Segment UID: 0xfe 0x9b 0x79 0xbd 0x5a 0x15 0x1c 0xa6 0x76 0x6b 0xbd 0x86 0x96 0x7f 0x8b 0x6a
| + Date: 2023-07-13 22:52:37 UTC
| + Duration: 00:43:40.162000000
|+ Tracks
| + Track
| + Track number: 1 (track ID for mkvmerge & mkvextract: 0)
| + Track UID: 16178120784336989185
| + "Lacing" flag: 0
| + Language: und
| + Codec ID: V_MPEG4/ISO/AVC
| + Track type: video
| + Default duration: 00:00:00.040000000 (25.000 frames/fields per second for a video track)
| + Video track
| + Pixel width: 928
| + Pixel height: 522
| + Video color information
| + Color transfer: 1
| + Color matrix coefficients: 6
| + Color primaries: 5
| + Color range: 1
| + Horizontal chroma siting: 1
| + Vertical chroma siting: 2
| + Codec's private data: size 46 (H.264 profile: Main @L4.0)
| + Track
| + Track number: 2 (track ID for mkvmerge & mkvextract: 1)
| + Track UID: 15400229157947398049
| + "Lacing" flag: 0
| + Name: Stereo
| + Language: und
| + Codec ID: A_AAC
| + Track type: audio
| + Audio track
| + Channels: 2
| + Sampling frequency: 44100
| + Codec's private data: size 5
|+ Tags
| + Tag
| + Targets
| + Simple
| + Name: ENCODER
| + String: Lavf59.27.100
| + Tag
| + Targets
| + Track UID: 16178120784336989185
| + Simple
| + Name: DURATION
| + String: 00:43:40.143000000
| + Tag
| + Targets
| + Track UID: 15400229157947398049
| + Simple
| + Name: DURATION
| + String: 00:43:40.162000000
|+ Cluster
But on somthe same file, after changing the language of the first track, the output of mkvinfo
is much shorter:
+ EBML head |+ EBML version: 1 |+ EBML read version: 1 |+ Maximum EBML ID length: 4 |+ Maximum EBML size length: 8 |+ Document type: matroska |+ Document type version: 4 |+ Document type read version: 2 + Segment: size 530593739 |+ Seek head (subentries will be skipped) |+ EBML void: size 78 |+ Segment information | + Timestamp scale: 1000000 | + Title: <redacted> | + Multiplexing application: Lavf59.27.100 | + Writing application: HandBrake 1.6.1 2023012900 | + Segment UID: 0xfe 0x9b 0x79 0xbd 0x5a 0x15 0x1c 0xa6 0x76 0x6b 0xbd 0x86 0x96 0x7f 0x8b 0x6a | + Date: 2023-07-13 22:52:37 UTC | + Duration: 00:43:40.162000000 |+ EBML void: size 225 |+ Tags | + Tag | + Targets | + Simple | + Name: ENCODER | + String: Lavf59.27.100 | + Tag | + Targets | + Track UID: 16178120784336989185 | + Simple | + Name: DURATION | + String: 00:43:40.143000000 | + Tag | + Targets | + Track UID: 15400229157947398049 | + Simple | + Name: DURATION | + String: 00:43:40.162000000 |+ Cluster
Using the verbose option provides too many details, thus at the moment I’m using mkvmerge
:
mkvmerge --identification-format json --identify file.mkv
{
"attachments": [],
"chapters": [],
"container": {
"properties": {
"container_type": 17,
"date_local": "2023-07-14T00:52:37+02:00",
"date_utc": "2023-07-13T22:52:37Z",
"duration": 2620162000000,
"is_providing_timestamps": true,
"muxing_application": "Lavf59.27.100",
"segment_uid": "fe9b79bd5a151ca6766bbd86967f8b6a",
"timestamp_scale": 1000000,
"title": "<redacted>",
"writing_application": "HandBrake 1.6.1 2023012900"
},
"recognized": true,
"supported": true,
"type": "Matroska"
},
"errors": [],
"file_name": "file.mkv",
"global_tags": [
{
"num_entries": 1
}
],
"identification_format_version": 20,
"track_tags": [
{
"num_entries": 1,
"track_id": 0
},
{
"num_entries": 1,
"track_id": 1
}
],
"tracks": [
{
"codec": "AVC/H.264/MPEG-4p10",
"id": 0,
"properties": {
"chroma_siting": "1,2",
"codec_id": "V_MPEG4/ISO/AVC",
"codec_private_data": "014d4028ffe1001d674d4028ab12074087f2602d414041900000030010002bf200f183189801000668e88e1b2c80",
"codec_private_length": 46,
"color_matrix_coefficients": 6,
"color_primaries": 5,
"color_range": 1,
"color_transfer_characteristics": 1,
"default_duration": 40000000,
"default_track": true,
"display_dimensions": "928x522",
"display_unit": 0,
"enabled_track": true,
"forced_track": false,
"language": "und",
"minimum_timestamp": 23000000,
"num_index_entries": 561,
"number": 1,
"packetizer": "mpeg4_p10_video",
"pixel_dimensions": "928x522",
"tag_duration": "00:43:40.143000000",
"uid": 16178120784336989185
},
"type": "video"
},
{
"codec": "AAC",
"id": 1,
"properties": {
"audio_channels": 2,
"audio_sampling_frequency": 44100,
"codec_id": "A_AAC",
"codec_private_data": "121056e500",
"codec_private_length": 5,
"default_track": true,
"enabled_track": true,
"forced_track": false,
"language": "ita",
"language_ietf": "it",
"minimum_timestamp": 0,
"num_index_entries": 0,
"number": 2,
"tag_duration": "00:43:40.162000000",
"track_name": "Stereo",
"uid": 15400229157947398049
},
"type": "audio"
}
],
"warnings": []
}
The output might be too verbose, in that case, it can be filtered with jq
if one really wants too.
For example, the output filtered with jq '.tracks[] | select(.type == "audio")|{id,properties}'
yelds
jq '.tracks[] | select(.type == "audio")|{id,properties}'
{
"id": 1,
"properties": {
"audio_channels": 2,
"audio_sampling_frequency": 44100,
"codec_id": "A_AAC",
"codec_private_data": "121056e500",
"codec_private_length": 5,
"default_track": true,
"enabled_track": true,
"forced_track": false,
"language": "ita",
"language_ietf": "it",
"minimum_timestamp": 0,
"num_index_entries": 0,
"number": 2,
"tag_duration": "00:43:40.162000000",
"track_name": "Stereo",
"uid": 15400229157947398049
}
}
To print only the id
and language
, something like jq '.tracks[] | select(.type == "audio")|{id,language: .properties.language}'
should do the job:
jq '.tracks[] | select(.type == "audio")|{id,language: .properties.language}'
{
"id": 1,
"language": "ita"
}
Note 📝 | mkvmerge --identification-format json --identify file.mkv also works for .mp4 files, but you’ll not be able to use mkvpropedit to edit them. |
Change default audio tracks
A .mkv
file has normally a defaul audio track, which is the audio track that the player selects automatically.
I have a collection of mkv with two audio tracks, the first one being english, but I always want to hear the non english version. Up until now I’ve selected manually the audio track I wanted after starting the video, but it occurred to me that I could simply flag the track I wanted as default audio track, and remove the default flag from the english track (I’m not sure what’s suppsoed to happne if there are two default audio tracks):
mkvpropedit "$file" --edit track:a1 --set flag-default=0 --edit track:a2 --set flag-default=1
Other examples
mkvpropedit
can be used for changing other properties, like subtitles, embedded images and other attributes of a mkv file.
Most tools do not bother to read the metadata attached to video files.
For example Kodi uses the folder structure and file name 🗄️ to search online for informations like movie name, release year, actors, and so on. Otherwise it can use a separate file for storing and reading all the metadata.
It does not even look at, at least by default 🗄️, at the embedded metadata.
I suppose the main reason is that reading and parsing a video file for getting the metadata is in general harder, or at least costs more resources, than reading the information from a dedicated file.
Do you want to share your opinion? Or is there an error, some parts that are not clear enough?
You can contact me anytime.