224

I simply want to convert files, any format to any format (at the moment, I need to convert MKV to MP4-h264), without losing quality. I don't want to resize (scale) the video, I don't want to change its aspect ratio and I don't want it to lose quality (this is very important); all I want is "to change the format", that's all. Reason: my DVD player won't recognize any formats other than AVI or MP4. I don't care about file size, unless the difference between the input and the output files is absurdly huge. So, how do I do that?

I've already tried programs such as WinFF, Arista, Format Junkie, but their presets always change something which I don't want to be changed (size, aspec ratio, etc.). I'm not really sure, but I think the best way to get what I want is to go with the pure ffmpeg commands. But how?

By the way, Ubuntu 13.04 (64-bit), here. Thanks for your time, guys.

user229552
  • 2,341
  • 2
  • 13
  • 3

2 Answers2

366

If you only want to convert MKV to MP4 then you will save quality and a lot of time by just changing the containers. Both of these are just wrappers over the same content so the CPU only needs to do a little work. Don't re encode as you will definitely lose quality.

It's very straight forward using ffmpeg:

ffmpeg -i LostInTranslation.mkv -codec copy LostInTranslation.mp4

Here, you are copying the video codec and audio codec so nothing is being encoded.

Tip: To convert all MKV files in the current directory, run a simple loop in terminal:

for i in *.mkv; do
    ffmpeg -i "$i" -codec copy "${i%.*}.mp4"
done

For future conversions, like from AVI to MP4, check out HandBrake.

David Foerster
  • 36,264
  • 56
  • 94
  • 147
Sayem
  • 3,643
  • 1
  • 13
  • 11
  • Sayem, I tried your suggestion, but got this result: "[mp4 @ 0x134da20] Application provided invalid, non monotonically increasing dts to muxer in stream 0: -2 >= -2 av_interleaved_write_frame(): Invalid argument". Anyway, I've got what I want with the following command: "avconv -i input.mkv -codec copy output.mp4" which is pretty similar to the one you suggested. Thanks a lot for your time. :) – user229552 Dec 28 '13 at 18:45
  • 1
    That for-loop dies when there are spaces in the file names ;-; – EaterOfCode Sep 26 '14 at 10:54
  • 12
    And don't forget -movflags +faststart because mp4 sucks; without that, you can't play a partial file (where the end of the file isn't written yet). – Peter Cordes Jan 15 '15 at 02:44
  • How come when I "re-wrap" MKV files as MP4 files, the subtitles in the original MKV aren't being transferred over?? – oldboy Sep 14 '17 at 01:28
  • @Anthony: Probably because the FFmpeg command didn't include instructions how to convert subtitle streams. My changes (-codec copy) should take care of that because they tell FFmpeg to copy all encountered data streams and codecs. – David Foerster Dec 08 '17 at 11:33
  • 3
    Windows users may need to add the -strict experimental flag after the input file for this to work: ffmpeg -i LostInTranslation.mkv -strict experimental -codec copy LostInTranslation.mp4. According to this bug report, the -strict option must be specified after the input file; otherwise, it will not recognize that you specified the option. That took me quite a while to find out. – Alexander Feb 18 '19 at 08:20
  • 2
    @Alexander I am on Windows 10, did not use the -strict flag, and had no problems. FYI. In any case, the bug report is 9 years old and was closed 9 years ago. – Sabuncu Mar 21 '20 at 15:10
  • Amazing. This just saved me an hour of conversion. Is there any way to make ffmpeg choose the fastest option possible for any conversion? I suppose that changing for example .mov to .mp4 might require different options and a command that just guesses the best command would be amazing. – nicusor Dec 16 '21 at 20:11
  • Not sure if it is related but rewrote this piece to make it work on Windows for %%f in (.\*.mkv) do ( ffmpeg -i "%%~nf.mkv" -codec copy "%%~nf.mp4" ) – FamousSnake Oct 17 '22 at 05:56
  • Add option -map 0 if your video has multiple audio tracks. Otherwise, this will only copy the first audio track. – Michael Yaworski May 10 '23 at 19:02
  • Good god, I've been absolutely blasting my CPU for so, so many hours before I learned of this. – max pleaner May 18 '23 at 03:51
17

Here is one you haven't tried. Handbrake

theherk
  • 287
  • 2
  • 5
  • TheHerk, I couldn't install it. Added PPA, updated sources, tried to install "handbrake" package, but it says there's no such package to be installed. Go figure! – user229552 Dec 28 '13 at 19:36
  • 3
    Never mind, TheHerk. I found the correct name of the package: handbrake-gtk. Installed it, but didn't like it. But thanks anyway. :) – user229552 Dec 28 '13 at 20:05
  • 2
    Handbrake is incapable of lossless video conversion, as specified in the OP's question. It has no "copy" option for video. It is only capable of transcoding, which will always cause a loss of quality. – Kurt Fitzner Apr 22 '20 at 02:08
  • 1
    It may be true that handbrake doesn't have any lossless options, but the second statement is absolutely not true. You can convert from one data type to another without losing quality as long as the second can store more information that the first. https://video.stackexchange.com/a/21623 – theherk Apr 23 '20 at 17:30
  • 1
    Handbrake is slow as H3ll, use the below python script ...

    import os files = [f for f in os.listdir('.') if os.path.isfile(f)] for f in files: if 'mkv' in f: os.system('ffmpeg -i "' + str(f) + '" -codec copy "' + str(f).split('.mkv')[0] + '.mp4"')

    – PanDe Jun 06 '21 at 06:56
  • 1
    @PanDe Generally bad practice to just plop strings directly into a command, so probably shouldn't suggest it to someone who might be unfamiliar with python; a better way would be to also import subprocess and use files = [ f for f in os.listdir() if os.path.isfile(f) and f[-4:] == '.mkv' ] followed by for f in files: subprocess.Popen([ 'ffmpeg', '-i', f, '-codec', 'copy', f[:-4] + '.mp4' ]) – SliceThePi Sep 15 '21 at 00:43