I have a bunch of .mkv files with diverse content, so I don't know about their audio, subtitle, chapter and attachment contents. Common denominator: They all have one video track.

I want to batch replace the video track only with a reencoded version of it, keeping the rest of the file with audio, subs, chapters and attachments intact. What is the easiest way to do this? Earlier questions always made assumptions about the other content of the file, so not really applicable - also, batch mode desired.

x264, ffmpeg or avconv can all be used if one of these is better for the job than the other.

  • I already have a single example for you, but I need more info to provide a batch command. Will the re-encoded version already exist, or do you want to re-encode it and mux all of the desired streams in one command? If it already exists where is it located in relation to the original? What is your OS? – llogan Nov 12 '14 at 1:44
  • Sorry for not being clear enough. The re-encoded version does not exist, I want to re-encode and re-mux afterward. One command would be ideal. I am using Linux, but Windows is also an option since the system is dual-boot. Doing by hand on the GUI, I would extract the video stream with mkvmerge, re-encode it by Handbrake, and use mkvmerge again to make a modified .mkv with the new videostream, rest untouched. – emk2203 Nov 12 '14 at 6:35

Single example

Using ffmpeg to re-encode the video stream(s) and stream copy everything else:

ffmpeg -i original.mkv -map 0 -c copy -c:v libx264 output.mkv
  • See one of the various encoding guides for info on whatever format you want.

  • All streams from the first input, labeled 0 and the only input in this case, are mapped with -map 0. Otherwise default stream selection will only map one stream per type. For example if your input has multiple audio streams, then using -map 0 will map all of them instead just one.

BASH "for loop"

To do the same as above to all MKV files in the current directory and output them to a directory named outputdir:

mkdir outputdir
for i in *.mkv; do ffmpeg -i "$i" -map 0 -c copy -c:v libx264 outputdir/"${i%.mkv}.mkv"; done
  • The weird looking "${i%.mkv}.mkv" is using parameter expansion. In your case you could simply use "$i", but it is useful if your input container formats are different than your output container formats. For example, without the parameter expansion, and if your inputs are MKV and the outputs are MP4, then output would end up being named something like output.mkv.mp4.
  • Beautiful answer. Is there any need to go beyond the -crf -preset -tune switches nowadays? In other words, will this give me the best results except in very rare cases? And a final thing: Would you advise using -tune animation for Anime? – emk2203 Nov 15 '14 at 23:42
  • @emk2203 You may have to use -profile:v if you are encoding for limited devices. Otherwise, -crf, -preset, and -tune should suffice for the vast majority of encodings in my opinion. -tune animation would be a good choice for anime. – llogan Nov 16 '14 at 4:00
  • If you say "vast majority", is there an indication when just using -crf -preset -tune is not sufficient? What source material would need more fine-tuning? – emk2203 Nov 16 '14 at 19:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.