Question

Most Matroska Video Files (.mkv's) nowadays have header compression enabled. This breaks compatibility with hardware players, and so I created a batch long ago "fixing" that by using mkvtoolnix to reassemble the files without using header compression. But strangely the batch doesn't work on some .mkv's, even though the source is correct. There's just no pattern in the hiccups...

Because of that I started to write a small Python 3.2 script today, with the only purpose to iterate through the .mkv-files in the CWD and use them as parameters to call the mkvtoolnix-.exe using parameters. I tried using both os.popen() and os.system() on my prepared command, and while system() seems to misinterprete the command, removing double quotes where it shouldn't, even when escaped, popen seems to work atleast a bit.

And that's my problem here. Executing the script now, it creates a .mkv_fix-file for every .mkv-file in the folder, which is fine, but it's size is only a small part of the original one and it is unplayable. To me it seems like popen calls the .exe just fine, but terminates it almost instantly afterwards, leaving only an unfinished file.

I've taken the mkvtoolnix windows executables as a 7zip archive from here and put them in a subdirectory of the CWD of the script.

I should also note that the executables produce console output when called from the batch, which isn't the case with the .py-script.

The important part of the code:

for file in glob.iglob('*.mkv'):
    if file.count('_fix') == 0:
        print(file)
        convertCMD = '"{0}\mkvtoolnix\mkvmerge.exe" -o "{1}_fix" --engage keep_bitstream_ar_info -A -S --compression -1:none "{1}" -D -S --compression -1:none "{1}" -A -D "{1}"'.format(os.getcwd(),file)
        os.popen(convertCMD)
        print('Converted '+file)

Any kind of help is appreciated.

Additional info:

Usual mkvtoolnix output:

mkvmerge v5.5.0 ('Healer') built on Apr  6 2012 21:43:24
'F:\$PRECONVERT\MKVFILENAME': Using the demultiplexer for the format 'Matroska'.
'F:\$PRECONVERT\MKVFILENAME': Using the demultiplexer for the format 'Matroska'.
'F:\$PRECONVERT\MKVFILENAME': Using the demultiplexer for the format 'Matroska'.
'F:\$PRECONVERT\MKVFILENAME' track 0: Using the output module for the format 'MPEG-4'.
'F:\$PRECONVERT\MKVFILENAME' track 1: Using the output module for the format 'Vorbis'.
'F:\$PRECONVERT\MKVFILENAME' track 2: Using the output module for the format 'Vorbis'.
'F:\$PRECONVERT\MKVFILENAME' track 3: Using the output module for the format 'text subtitles'.
'F:\$PRECONVERT\MKVFILENAME' track 4: Using the output module for the format 'text subtitles'.
The file 'F:\$PRECONVERT\MKVFILENAME.mkv_fix' has been opened for writing.
Progress: 0%
Progress: 16%
Progress: 39%
Progress: 56%
Progress: 78%
Progress: 96%
Progress: 100%
The cue entries (the index) are being written...
Muxing took 3 seconds.
Was it helpful?

Solution

os.popen is deprecated, and I haven't used it, at least not the last few years, so I don't remember the details. But documentation indicates that you need to call os.wait() to wait for the subprocess to finish.

For subprocess.Popen you need to call wait() on that object to see if it has finished. If you do so before starting the next one, outputs will not be mixed. On the other hand, if you start all at once, you can use any number of processor cores, which would be nice. To not have mixed outputs you then need to create one output for each subprocess, by calling Popen() with a stdout argument pointing to a file you opened for the purpose. You'll get one logfile per conversion that way, which makes sense.

OTHER TIPS

I wrote a script that I use on daily basis to mux some .srt subtitles to a mkv file.
This is the relevant code:

import subprocess

mkvmerge_args = [
    mkvmerge_path,
    '-o',
    dest_file_path,
    original_file,
    #other arguments...
    ]

returncode = subprocess.call(mkvmerge_args)

(Works perfectly on my Ubuntu Server machine and it should work also on Windows)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top