• Welcome! The TrekBBS is the number one place to chat about Star Trek with like-minded fans.
    If you are not already a member then please register an account and join in the discussion!

Reduce Matroska (MKV) file size?

CorporalClegg

Fleet Admiral
Admiral
Is there an easy way (software or whatever) reduce the size of mkv files?

I'd guess it'd have something to do with lowering the bit rate or resolution.

The quality isn't an issue, I just to be able to fit as many of them on a DVD as possible. I want to make the portable and I'm probably only going to play them on my laptop.
 
SUPER from erightsoft.com.

It's free and says it will handle mkv files.
Will convert any video format to any other.
Will also handle batches of files.

Did I mention it's FREE????

(darn handy tool to keep around if you're messing with video...)
 
Is there an easy way (software or whatever) reduce the size of mkv files?

I'd guess it'd have something to do with lowering the bit rate or resolution.

The quality isn't an issue, I just to be able to fit as many of them on a DVD as possible. I want to make the portable and I'm probably only going to play them on my laptop.

Lower the bitrate. The bitrate determines the size of the file. When you lower the bitrate, you might also consider lowering the resolution, depending on how much you reduce the bitrate by. As the bitrate is reduced, higher resolution video will start to look worse.

You should also choose the most efficient codec possible. Mkv is just a container for the video and the audio, inside the Mkv file are video and audio, and possibily even subtitles. Currently, H.264 is the most efficient codec available, allowing you to have low bitrates without significant drop in quality. But, it is very slow to encode if you don't have a powerful multi-core machine. If you don't have a powerful machine, then you'll probably want to go with Xvid, which is the current standard for most amature video rippers.

The Matroska container can hold multiple audio files, if the one's you're working with have multiple audio tracks you can reduce the size by simply removing and audio files that you don't need, such as dialog in superfluous languages.

For recompressing audio, you'll probably want to use MP3. There are other codecs available that can provide higher quality audio, but for compression to the smallest reasonable size it's either MP3 or Vorbis. Vorbis has very little support while everything plays MP3.
 
^
Well that's good advice and thank you, but do you have any software suggestions? All, the software that was on the page Hitman posted seems to be limited in one way or another. The one with the most promise is Avidemux except whenever I run it, I get a BSOD.

I did notice that it's built on QT4 so I suppose I could try it on my Linux box. The problem is I only have a couple of available flash drives and they're small (I have a lot of files.) and it doesn't have a DVD burner. So I'd have to copy them all over, convert them, and then transfer them back to the Windows machine.
 
I prefer MediaCoder. It is a bit complex, but it has an easy-to-use interface. I've been able to successfully transcode many files with it.

For removing unneeded audio from a matroska container, I prefer to use MKVExtractGUI to split the whole thing into it's parts and then puts the ones I want to keep into a new container using AVIMuxGUI.
 
^
Well that's good advice and thank you, but do you have any software suggestions? All, the software that was on the page Hitman posted seems to be limited in one way or another. The one with the most promise is Avidemux except whenever I run it, I get a BSOD.

I did notice that it's built on QT4 so I suppose I could try it on my Linux box. The problem is I only have a couple of available flash drives and they're small (I have a lot of files.) and it doesn't have a DVD burner. So I'd have to copy them all over, convert them, and then transfer them back to the Windows machine.

If you were to do this on linux then it's quite easy on the command-line with a little bit of bash. The tools are all freely available: mencoder, Matroska tools, ffmpeg, ogg vorbis, lame mp3, MP4Box, x264, xvid, etc.

Here I'll show you an example. I got a 380 Mb matroska file bebop_01.mkv (the first episode of Cowboy Bebop). It contains one video track encoded with x264, two unaltered DVD audio tracks (Dolby Digital), and one subtitle track (ssa). The resolution is 704x480 and the video bitrate is around 1470 kbps. Now I am going to reduce that file to something much smaller by using the following script that I wrote. The script uses the x264 encoder for the video and the vorbis encoder for the audio tracks. It produces a Matroska file as the output. Note: the script is not robust so it needs to be altered if your matroska file doesn't contain exactly one video file, two audio tracks and a subtitle file.

Code:
#!/bin/bash
# input arguments
VIDEO_RESOLUTION=$1 # entering the width is sufficient
VIDEO_FRAMERATE=$2 # usually 29.97 or 23.976024
VIDEO_BITRATE=$3 # pick a smaller bitrate
AUDIO_QUALITY=$4 # For vorbis a value of 20 here corresponds with ~90 kbps (which should be sufficient)

WORK=mkv_temp
CURRENT=$(pwd)
TEMP="${CURRENT}/${WORK}"
[[ ! -d ${TEMP} ]] && mkdir "${TEMP}"


# Demuxing the Matroska file

ls -1 *.mkv  | while read INPUT
do
	TITLE=${INPUT/.mkv/}
	echo ${TITLE}
	[[ ! -f "${TEMP}/${TITLE}.video" ]] && \
	mkvextract tracks "${INPUT}" 1:${TEMP}/${TITLE}.video 2:${TEMP}/${TITLE}_01.audio 3:${TEMP}/${TITLE}_02.audio 4:${TEMP}/${TITLE}.subtitle
done

# Video Transcoding
cd ${TEMP}
# mencoder filter settings and x264 settings
ENCODE1="-ovc x264 -x264encopts threads=auto:bitrate=${VIDEO_BITRATE}:subq=4:bframes=3:b_pyramid:weight_b:turbo=1:pass=1"
ENCODE2="-ovc x264 -x264encopts threads=auto:bitrate=${VIDEO_BITRATE}:subq=6:frameref=6:partitions=all:8x8dct:me=umh:bframes=3:b_pyramid:weight_b:pass=2"
FILTER1="-vf scale=${VIDEO_RESOLUTION}:-2,pullup,pp=md,softskip,harddup"
FILTER2="${FILTER1}"
# determining the mencoder frame rate
case ${VIDEO_FRAMERATE} in 
	23.976*)
	FRAMERATE_MENCODER="24000/1001";;
	29.97*)
	FRAMERATE_MENCODER="30000/1001";;
	25)
	FRAMERATE_MENCODER="25";;
esac

ls -1 *.video | while read VIDEO
do
	TITLE=${VIDEO/.video/}
	[[ ! -f "${TITLE}.264" ]] && \
	mencoder ./${VIDEO} ${FILTER1} -nosound ${ENCODE1} -ofps ${FRAMERATE_MENCODER} -of rawvideo -o ${TITLE}.264 && \
	mencoder ./${VIDEO} ${FILTER2} -nosound ${ENCODE2} -ofps ${FRAMERATE_MENCODER} -of rawvideo -o ${TITLE}.264
	MP4Box -fps ${VIDEO_FRAMERATE} -add ${TITLE}.264 ${TITLE}.mp4
	rm *.264
done

# Audio Transcoding
ENCODE3="-acodec vorbis -aq ${AUDIO_QUALITY} -ac 2"


ls -1 *.audio | while read AUDIO
do
	TITLE=${AUDIO/.audio/}
	[[ ! -f "${TITLE}.ogg" ]] && \
	ffmpeg -i ${AUDIO} ${ENCODE3} ${TITLE}.ogg </dev/null
done

# Muxing Everything Back Together

cd ../
ls -1 *.mkv  | while read INPUT
do
	TITLE=${INPUT/.mkv/}
	echo ${TITLE}
	mkvmerge -o ${TITLE}_new.mkv --default-duration 0:${VIDEO_FRAMERATE}fps ${TEMP}/${TITLE}.mp4 ${TEMP}/${TITLE}_01.ogg \
							${TEMP}/${TITLE}_02.ogg ${TEMP}/${TITLE}.subtitle
done

# cleaning up

Run the script in the directory where your mkv files are located.

mkvc <video resolution> <video fps> <video bitrate> <audio quality> i.e.
Code:
 mkvc 576 23.976024 600 20

The result is a 138 Mb file with a new resolution of 576x392 and a video bitrate of around 600 kpbs. Actually if I threw out the japanese audio track then the output is only 120 Mb.

I PM'ed you a link to the new and smaller mkv file. You can view it to check the quality.
 
I actually tried that and it worked quite nicely. But, as you said, I had to use a file that met all the criteria.

I'll have to read the man pages and any readmes and tinker with it a bit. But it's a good start. Thanks!
 
^ I could write a more robust and flexible script if I had more time. Anyhow you are welcome to PM me if you have any question or difficulty regarding transcoding on the command-line.

For gui tools avidemux is pretty nice on linux and probaby so is MediaCoder on windows. Of course personally I've always done transcoding jobs using bash and the command-line utilities.
 
Nah. I think I should be okay. I'm not a RHCE by any means (Not that that means much these days.), but I've done enough shell scripting that I should be able to figure things out. I think the biggest hurtle his going to work out a way to efficiently do batches.
 
^ Actually up to now I never wrote one general transcoding script so I started one this morning and tested on a dozen different Matroska files (all anime). It seems to be working very well going from Matroska files to Matroska with x264 and vorbis. The other container/encoder formats just needs to filled in. In the future I might just use only this script for any transcoding batch jobs.

Code:
#!/bin/bash
# input arguments
OUTPUT_VIDEO_ENCODER=$1 # only x264 is available at the moment
VIDEO_RESOLUTION=$2 # entering the width is sufficient
VIDEO_BITRATE=$3 # pick a smaller bitrate
OUTPUT_AUDIO_ENCODER=$4 # only vorbis is available at the moment
AUDIO_QUALITY=$5 # For vorbis a value of 20 here corresponds with ~90 kbps (which should be sufficient)
OUTPUT_CONTAINER=$6 # only matroska available at the moment
WORK=work_tmp
CURRENT=$(pwd)
TEMP="${CURRENT}/${WORK}"
[[ ! -d ${TEMP} ]] && mkdir "${TEMP}"

# collects output encoding settings from a configuration file
# for now just use some pre-written settings.
# mencoder filter settings and x264 settings
ENCODEX264_1="-ovc x264 -x264encopts threads=auto:bitrate=${VIDEO_BITRATE}:subq=4:bframes=3:b_pyramid:weight_b:turbo=1:pass=1"
ENCODEX264_2="-ovc x264 -x264encopts threads=auto:bitrate=${VIDEO_BITRATE}:subq=6:frameref=6:partitions=all:8x8dct:me=umh:bframes=3:b_pyramid:weight_b:pass=2"
FILTER_1="-vf scale=${VIDEO_RESOLUTION}:-2,pullup,pp=md,softskip,harddup"
FILTER_2="${FILTER_1}"
# ffmpeg vorbis setting
ENCODE_VORBIS="-acodec vorbis -ar 44100 -aq ${AUDIO_QUALITY} -ac 2"



# Demuxing the file

ls -1 *{mkv,avi,mp4,ogm,vob} 2>/dev/null | while read INPUT
do
	# declare variables
	VIDS=0;	AUDS=0;	SUBS=0; EXTRACTION=""; TRACKS=0; TITLE=""; MUX="";
	declare -a TRACKTYPE VIDEOFPS FRAMERATE_MENCODER VIDEOAR AUDIOTYPE AUDIOLANG SUBTYPE SUBLANG 
	# Collecting Info
	mplayer ${INPUT} -endpos 0 -ao null -vo null 2>/dev/null 1>log </dev/null
	EXT_TMP=$(cat log | grep "format detected" | cut -f 1 -d " ")
	case ${EXT_TMP} in
		Matroska)
		EXT="mkv";;
		AVI)
		EXT="avi";;
		libavformat)
		EXT=$(echo ${INPUT##*.});;
	esac
	# Demuxing
	case ${EXT} in
		mkv)
		TITLE=${INPUT/.mkv/}
		echo ${TITLE}
		TRACKS=$(grep "Track ID [0-9]*" log | wc -l)
		for ID in $(seq 1 ${TRACKS})
		do
			i=$((ID-1))
			TRACK=$(grep "Track ID ${ID}" log)
			TRACKTYPE[$i]=$(echo ${TRACK} | egrep -o "(video|audio|subtitles)")
			case ${TRACKTYPE[$i]} in
				video)
				VIDEOTYPE[$VIDS]=$(echo ${TRACK} | egrep -o "video \([A-Z1-9_/]*" | sed -e 's/^.*(//g') ## storing video encoder information
				## for multiple video tracks we'll have play each to find out the frame rates
				VID=$(echo ${TRACK} | egrep -o "vid [0-9]*" | sed -e 's/vid //g')
				mplayer ${INPUT} -endpos 0 -ao null -vo null -vid ${VID} 2>/dev/null 1>log1 </dev/null
				VIDEOFPS[$VIDS]=$(cat log1 | egrep -o "  [0-9.]* fps" | grep -o "[0-9.]*") # grabbing the frame rate # this may not be robust
				case ${VIDEOFPS[$VIDS]} in 
					23.976*)
					FRAMERATE_MENCODER[$VIDS]="24000/1001"
					VIDEOFPS[$VIDS]="23.976024";;
					29.97*)
					FRAMERATE_MENCODER[$VIDS]="30000/1001"
					VIDEOFPS[$VIDS]="29.970030";;
					25*)
					FRAMERATE_MENCODER[$VIDS]="25";;
				esac
				VIDEOAR[$VIDS]=$(cat log1 | egrep -o "Aspect is 1[0-9.]*" | egrep -o "1[0-9.]*")
				echo "The video is encoded with ${VIDEOTYPE[$VIDS]}"
				echo "The video has a framerate of ${VIDEOFPS[$VIDS]}"
				echo "The video has an aspect ratio of ${VIDEOAR[$VIDS]}"
				VIDS=$((VIDS+1))
				VIDEOTRACK="${TEMP}/${TITLE}_${VIDS}.video"
				EXTRACTION="${EXTRACTION} ${ID}:${VIDEOTRACK}"
				;;
				audio)
				AUDIOTYPE[$AUDS]=$(echo ${TRACK} | egrep -o "audio \([A-Z1-9_/]*" | sed -e 's/^.*(//g')
				AUDIOLANG[$AUDS]=$(echo ${TRACK} | egrep -o "alang [a-z]*" | sed -e 's/alang //g') ## storing audio encoder information
				echo "The audio is encoded with ${AUDIOTYPE[$AUDS]}"
				echo "The audio language is ${AUDIOLANG[$AUDS]}"
				AUDS=$((AUDS+1))
				AUDIOTRACK="${TEMP}/${TITLE}_${AUDS}.audio"
				EXTRACTION="${EXTRACTION} ${ID}:${AUDIOTRACK}"
				;;
				subtitles)
				SUBTYPE[$SUBS]=$(echo ${TRACK} | egrep -o "subtitles \([A-Z1-9_/]*" | sed -e 's/^.*(//g') 
				SUBLANG[$SUBS]=$(echo ${TRACK} | egrep -o "slang [a-z]*" | sed -e 's/slang //g') ## storing subtitle information
				echo "The subtitle is ${SUBTYPE[$SUBS]}"
				echo "The subtitle language is ${SUBLANG[$SUBS]}"
				SUBS=$((SUBS+1))
				SUBTRACK="${TEMP}/${TITLE}_${SUBS}.subtitles"
				EXTRACTION="${EXTRACTION} ${ID}:${SUBTRACK}"
				;;
			esac
		done
		mkvextract tracks ${INPUT} ${EXTRACTION} </dev/null
		;;
		avi) 
		echo "Under Construction" ;;
		mp4) 
		echo "Under Construction" ;;
		ogm) 
		echo "Under Construction" ;;
		vob)
		echo "Under Construction" ;;

	esac
	## Transcoding the video tracks
	for VIDEOID in $(seq 1 ${VIDS})
	do
		i=$((VIDEOID-1))
		VIDEOTRACK="${TEMP}/${TITLE}_${VIDEOID}.video"
		if [ -f "${VIDEOTRACK}" ]; then 
			case ${OUTPUT_VIDEO_ENCODER} in
				x264)
				TMP1=$(echo ${VIDEOTRACK/.video/.264})
				TMP2=$(echo ${VIDEOTRACK/.video/.mp4})
				echo "The VIDEO output is ${TMP2}"
				[[ ! -f "${TMP2}" ]] && \
				mencoder ${VIDEOTRACK} ${FILTER_1} -nosound ${ENCODEX264_1} -ofps ${FRAMERATE_MENCODER[$i]} -of rawvideo -o ${TMP1} </dev/null && \
				mencoder ${VIDEOTRACK} ${FILTER_2} -nosound ${ENCODEX264_2} -ofps ${FRAMERATE_MENCODER[$i]} -of rawvideo -o ${TMP1} </dev/null && \
				MP4Box -fps ${VIDEOFPS[$i]} -add ${TMP1} ${TMP2} </dev/null
				cp "${TMP2}" "${VIDEOTRACK}"
				rm "${TMP1}" "${TMP2}" 2>/dev/null
				;;
				xvid)
				echo "Under Construction"
				;;
			esac
		fi
	done
	## Transcoding the audio tracks	
	for AUDIOID in $(seq 1 ${AUDS})
	do
		i=$((AUDIOID-1))
		AUDIOTRACK="${TEMP}/${TITLE}_${AUDIOID}.audio"
		if [ -f "${AUDIOTRACK}" ]; then
			case ${OUTPUT_AUDIO_ENCODER} in
				vorbis)
				TMP1=$(echo ${AUDIOTRACK/.audio/.ogg})
				[[ ! -f "${TMP1}" ]] && \
				ffmpeg -i ${AUDIOTRACK} ${ENCODE_VORBIS} ${TMP1} </dev/null
				cp "${TMP1}" "${AUDIOTRACK}" 2>/dev/null
				rm "${TMP1}"
				;;
				mp3)
				echo "Under Construction"
			esac
		fi
	done
	# Muxing Everything Back together
	VIDS=0; AUDS=0; SUBS=0;
	OUTPUT="${TITLE}_new.${EXT}"
	case ${OUTPUT_CONTAINER} in 
		matroska) 
		for TRACKID in $(seq 1 ${TRACKS})
		do
			i=$((TRACKID-1))
			case ${TRACKTYPE[$i]} in
				video)
				j=$(echo ${VIDS})
				VIDS=$((VIDS+1))
				VIDEOTRACK="${TEMP}/${TITLE}_${VIDS}.video"
				if [ -f "${VIDEOTRACK}" ]; then 
					if [ ${j} -eq 0 ]; then
						MUX="${MUX} --default-track -1"
					fi
					MUX="${MUX} --default-duration -1:${VIDEOFPS[$j]}fps --aspect-ratio -1:${VIDEOAR[$j]} ${VIDEOTRACK}"
				fi
				;;
				audio)
				j=$(echo ${AUDS})
				AUDS=$((AUDS+1))
				AUDIOTRACK="${TEMP}/${TITLE}_${AUDS}.audio"
				if [ -f "${AUDIOTRACK}" ]; then
					if [ ${j} -eq 0 ]; then
						MUX="${MUX} --default-track 0"
					fi
					MUX="${MUX} --language 0:${AUDIOLANG[$j]} ${AUDIOTRACK}"
				fi
				;;
				subtitles)
				j=$(echo ${SUBS})
				SUBS=$((SUBS+1))
				SUBTRACK="${TEMP}/${TITLE}_${SUBS}.subtitles"
				if [ -f "${SUBTRACK}" ]; then
					if [ ${j} -eq 0 ]; then
						MUX="${MUX} --default-track 0"
					fi
					MUX="${MUX} --language 0:${SUBLANG[$j]} ${SUBTRACK}"
				fi
				;;
			esac
			
		done
		echo ${MUX}
		mkvmerge -o ${OUTPUT} ${MUX} </dev/null
		;;
		avi)
		echo "Under Construction"
	esac
	## Clean up 
	rm "${TEMP}"/* -fr
	rm divx2*
	rm log log1
done

I ran
Code:
vtc x264 576 550 vorbis 15 matroska

x264 looks very very good with only 550 kbps. I am sure that can be pushed even lower.

Also vorbis sounds very good even at a quality of 15 (~80 kbps).

The total resulting filesize was only 40% of the original.
 
Last edited:
As far as I know, there are mainly two methods to compress MKV video file size

Method one: Compress MKV by converting MKV to MP4, AVI, 3GP or other video formats

In the same video quality situation, the MKV file size is much larger than other video formats like MP4. To shrink MKV without loss of video quality, we may convert MKV to MP4, 3GP, AVI and etc. If you do not want to change the video format, you may refer to Method two.

Method two: Shrink MKV by adjusting MKV video bit rate, resolution, frame rate etc

This method helps to resize MKV files to get a good balance of quality and file size. And you may choose to compress MKV as well as keep the MKV as the output video format. You may also choose to shrink and convert MKV to other video format.
 
Last edited by a moderator:
I've found that Format Factory by Softtronic (?) works well for me, and converts between all the popular video and audio file formats, with pretty much every option for bit rate, codecs, and such. It's also free.
 
Holy thread resurrection Batman!

MKV is only a container. I believe what's inside it could be anything, but it's usually AVC, the same as MP4, or in older cases DivX or Xvid codec formats.

Avidemux is kick ass software for a free tool.
 
If you are not already a member then please register an account and join in the discussion!

Sign up / Register


Back
Top