Home > Linux > Remuxing mkv for the Xbox 360…

Remuxing mkv for the Xbox 360…

So you downloaded an HD .mkv video file. So you wanna watch your nice video on your Xbox 360 but you don’t want to use Windows? Well look no further, you can do this quickly and easily. No need to re-encode the video and wait for an hour or longer, extract and remux the streams to an mp4 and stream it across your home network with a UPnP program like fuppes or ushare. I have created a script based on the DIY steps found at LinuxLove.info. I have Ubuntu, so this guide will describe how to install the needed programs using Ubuntu’s apt-get package manager. So sit back, sip your coffee and learn.

Well, a lot of people use MP4Box for this sort of thing, but I was not able to get it to work, install, or compile at all on my system, instead I used mp4creator. So first thing is first, we need to install the necessary programs.

Setting Up

The necessary programs are mkvmerge, mkvextract (package mkvtoolnix), bbe, mplayer, normalize-audio, neroAacEnc, and mp4creator.
sudo apt-get update && sudo apt-get install mkvtoolnix bbe mplayer normalize-audio mpeg4ip-server
The only program we can’t get from the ubuntu repositories is neroAacEnc (The nero encoder for AAC). This can be gotten from here. Then do the following.
unzip NeroDigitalAudio.zip
cd linux
sudo mv neroAacEnc /usr/bin
sudo chmod +x /usr/bin/neroAacEnc

Afterwards you can remove the zip and the files you extracted from it. Now we’re all set up.

Explaining the Script

I’m going to go through the commands that the script uses so you can see what is going on. If you don’t care how it works, and just want to use it, just skip to the bottom and download the script.
VID=`mkvmerge -i "$MKV" | grep "Track ID .: video" | awk '{ print sprintf("%d",$3) }'`
FPS=`mplayer -identify "$MKV" -vc null -ao null -vo null -frames 0 2>/dev/null | grep ^ID_VIDEO_FPS | sed -e 's/^.*=//'`
BASE=`echo $MKV | sed 's/\.mkv//'`

This fills the VID variable with the Track ID of the video track from the mkv file, and FPS will have (can you guess?) FPS of the video. BASE will be the filename without the ‘.mkv’ at the end.
mkvextract tracks "$MKV" "$VID:$BASE.h264"
This extracts the video track from the file. We aren’t converting or anything, just taking the existing video from the file and taking it out of its container.
bbe -e "r 7 \41" --output="$BASE.tmp.h264" "$BASE.h264"
This changes the profile level to 4.1, this works on 90% of mkv files, but a few may still have some artifacts. Now we extract our audio from the video.
mplayer "$MKV" -novideo -vc null -vo null -ao pcm:fast:file="$BASE.wav" -channels 2
Then (this part is optional, just remove it from the script if you don’t want it, or time is of the essence) we normalize the audio levels. Personally I think this is great so if you have a video where the audio level is not consistent, this will fix it.
normalize-audio "$BASE.wav"
Then we just need to encode the audio from wav to m4a, unfortunately MP4Box was able to use m4a’s instead since we’re using mp4creator there’s the extra step of converting to the aac.
neroAacEnc -lc -ignorelength -q 0.50 -if "$BASE.wav" -of "$BASE.m4a"
mp4creator --extract=1 "$BASE.m4a" "$BASE.aac"

The -q value is for the quality. Smaller will produce a smaller file, higher will produce a larger but better looking file. Personally, I find that 0.5 is excellent quality and the file size is roughly the same as the original mkv if not a little smaller.
mp4creator --create="$BASE.tmp.h264" -rate=$FPS "$BASE.mp4"
mp4creator --create="$BASE.aac" -rate=$FPS "$BASE.mp4"

And those two commans remux the video and audio together into our new mp4 file. Shiny.

I admit, majority of these steps were just taken directly from the above LinuxLove link. It was quick and easy to put together this script with some tweaks (such as using mp4creator.) The script isn’t very robust, its just down and dirty simple. There are probably more robust scripts out there. Or if someone wants, I can add some extra functionality into my script. Enjoy my script!

Just one thing, for some reason the creation of the mp4 file produces a message “Error decoding sei message”. I don’t know if its the videos, or if its a usual thing all I know is that the videos come out perfectly fine with no problems. So its something that can be ignored, if someone knows the reason for/way to fix this error, I’d love to find out. =)

In another post I’ll go over the setting up of the fuppes program for streaming your brand new HD mp4 videos to your xbox 360.

w00t w00t.

  1. savant
    February 20, 2009 at 2:52 am | #1

    Great writeup. Yours is the only solution I found that worked without any hitches. Thanks!

  2. February 20, 2009 at 3:01 am | #2

    Glad it helped! =)

  3. savant
    February 23, 2009 at 9:58 pm | #3

    Hey Zero,

    Have you come across this? It seems any TV show mkv I remux comes out perfect, but I’ve not successfully been able to remux a movie in mkv format for xbox 360. The xbox recognizes that it’s a video file, but when I try and load it, it fails. Eep.

  4. February 24, 2009 at 12:38 am | #4

    @savant

    Is there a specific error message associated with the failure? Also does the converted mp4 movie play fine on your computer? I haven’t run into this problem myself, but if you can get me more information I have no problem helping to troubleshoot it. =)

  5. savant
    February 24, 2009 at 2:24 am | #5

    Yeap, I just had to find a good file to replicate the failure. Looks like mp4creator borked.

    ——Creating mp4 video—————
    Error decoding sei message
    mp4creator: mp4atom.cpp:752: virtual void MP4Atom::FinishWrite(bool): Assertion `(m_size <= (u_int64_t)0xFFFFFFFF)’ failed.
    /usr/bin/vidconv.sh: line 70: 23014 Aborted mp4creator –create=”$BASE.tmp.h264″ -rate=$FPS “$BASE.mp4”
    ——Adding audio to the video——–
    MP4ERROR: MP4File::FindIntegerProperty: no such property – moov.iods.audioProfileLevelId
    ——Removing h264 and aac————
    ——Done! Enjoy your video! =)——-

  6. savant
    February 25, 2009 at 1:52 am | #6

    Huh, so I did some research and it would appear to be a result of a file size limitation in the xbox 360? Apparently it doesn’t like files over 4gb. Strange, I’ve got an HFS+ formatted usb drive that feeds it 12+GB wmv files without any problems. *shrug*

  7. February 25, 2009 at 1:58 am | #7

    @savant

    I remember reading about that somewhere. The Xbox360 has an issue about streaming and buffering files larger than 4GB over the network. Therefore this can be dealt with by splitting the video and running the script on each piece. You can split the video with the following command:


    mkvmerge -o output.mkv --split 2300m input.mkv

    Replace the 2300m with whatever size you like, Then run the script on each of the resulting files separately.

  8. mazeman
    February 25, 2009 at 11:32 am | #8

    For using MP4Box instead of mp4creator just comment lines 60 – end of the script and add this at the end:

    MP4Box -new $BASE.mp4 -add $BASE.tmp.h264 -add $BASE.m4a -fps $FPS

    echo “——Removing h264 and aac————”
    rm “$BASE.tmp.h264” “$BASE.aac” “$BASE.m4a” “$BASE.wav”

    Thanks for the script!

  9. savant
    February 27, 2009 at 2:02 am | #9

    @zero:
    Good call, thanks. I’m working out the bash arithmetic to compare the file size and, if it’s greater than 4 gigs, shave it at 4 gigs, then compare the shavings for size…etc… My server took a dump, but if/when I get the mkvmerge scriptlet finished I’ll send it your way.

  10. savant
    March 6, 2009 at 1:38 am | #10

    @zero: Maybe you want to take a stab at this with me. Since some mkv files for movies can be as large as 12 gigs, I was thinking of a for loop with a nested if statement that checks filesize with stat -c %s, which returns file size in bytes. Then, use mkvmerge to split the file into 3.9 gig chunks, or 4 gig chunks that are JUST small enough to make the 360 happy.

    Here’s some partial bash:

    #!/bin/bash

    for i in `ls *.mkv`;
    do

    # Get size of file in bytes
    BYTE_SIZE=`stat -c %s $i`;
    if [ “$BYTE_SIZE” -gt 4294967296 ];
    then
    echo “$i is larger than 4 Gigabytes (4294967296 bytes) at $BYTE_SIZE bytes.”
    else
    echo “$i is less than or equal to 4 Gigabytes (4294967296 bytes) at $BYTE_SIZE bytes”
    fi
    done

  11. adame
    March 8, 2009 at 2:25 pm | #11

    hey,

    Good script dude.

    Well, I used it to turn some mkvs to mp4s so I can watch them using my 360. I worked like a charm so far.
    Yesterday, I splited a movie so to make it watchable on my 360. I’ve converted the 2 parts & left the rest for today. When I tried to do it, nothing happended! Though it’s the same movie… and the files are @ equal sizes. So, any clue guys?

    Ah, no error message was prompted…

    Waiting for your help!

    Thanks.

  12. March 9, 2009 at 8:36 pm | #12

    @savant

    Lets see if we can’t get a little more reusable =)

    #!/bin/bash
    
    GIGS=4
    BYTES=$((2**30 * $GIGS))
    # The above makes it easy to just change the 
    # size of the file you want to split on.
    
    for i in `ls *.mkv`; do
        FSIZE=`stat -c %s $i`
        if [ "$FSIZE" -gt "$BYTES" ]; then
           mkvmerge -o output.mkv --split ${GIGS}g $i
        fi
    done
    
    for i in `ls *.mkv`; do
        vidconv $i
    done
    

    So this will first go through all the mkv files in the directory and split them into the chunks of whatever size you want. Then it loops through the entire directory of mkv files again this time converting each one into an mp4 (assuming you left the name of the script to be vidconv and put it in a directory in your path so that it can be executed as seen above.

    How’s that for you?

  13. April 1, 2009 at 2:48 pm | #13

    @adame

    I really don’t know. The converter didn’t do anything? Try running the commands to get the info from the file (what gets set to FPS, VID, etc.) and see if the output looks strange.

  14. July 26, 2009 at 10:39 pm | #14

    Thank you for the script! I’ve been searching for something like this for a while.

    I was able to run the script, successfully converting a file from mkv to mp4. However when I attempted to play it on my xbox 360 (using ushare) it refused the play the file. If I change the file’s extension to m4v it will play but the quality does not look so great. Will playing the file as m4v actually decrease the quality or is that just my mind messing with me.

    Any ideas why the xbox won’t play the file when it has the mp4 extension?

  15. Scott Howie
    March 3, 2010 at 11:07 am | #15

    Thanks a bunch for this, works like a charm and is super fast too. Streams great through fuppes

  16. Mike
    May 21, 2010 at 5:30 am | #16

    Thanks so much – worked perfectly. Saved me having to revert to my old windows-based method. This is a lot quicker too.

  17. Shane
    October 2, 2010 at 2:14 am | #17

    When I use your script it creates a mp4 file with 24 fps. The original is 23.976. This throws the audio off. Is there something I’m missing? I followed your tutorial to the letter.

  18. Shane
    October 7, 2010 at 3:10 am | #18

    Hi. Thanks for the great script.
    I have a problem though. “mplayer -identify “$MKV”” returns a ID_VIDEO_FPS of 24fps from all my 23.976fps Matroska files. The result of this is the remuxed video is out of sync. Any help?

  19. MikeFishcake
    December 11, 2010 at 4:51 pm | #19

    Been trying to do something like this for ages. Tried other scripts, other programs, nothing working.

    Who needs a GUI? (And that’s coming from someone who hadn’t even touched Linux 6 months ago)

  20. MikeFishcake
    December 11, 2010 at 4:52 pm | #20

    Just realised that statement makes it sound like this script didn’t work. It did work great – it was the others that didn’t..

    Thanks 🙂

  21. December 11, 2010 at 7:34 pm | #21

    I’m glad it worked! 🙂

  22. laki
    December 22, 2010 at 9:12 pm | #22

    I too have a problem where video/audio is out of sync after your script. I’m not sure if my problem is the same one shane has, but the end result is that audio and video are totally out of sync. (in the middle of the video they’re off by a second or two). Just thought i throw it out there. I’ll try to figure out what the issue is – but if anyone knows what it could be any feedback would be appreciated.

  23. laki
    December 22, 2010 at 9:38 pm | #23

    the 24 vs 23.976 fps problem can be solved by replacing the following line:

    FPS=`mplayer -identify “$MKV” -vc null -ao null -vo null -frames 0 2>/dev/null | grep ^ID_VIDEO_FPS | sed -e ‘s/^.*=//’`

    With this one:

    FPS=`mkvinfo “$MKV” | grep duration | sed ‘s/.*(//’ | sed ‘s/f.*//’ | head -n 1`

    mkvinfo appears to be fetching the correct fps and mplayer does not…. strange… I don’t know which universe of files this is true for – but it is for a few i tested on!

  24. laki
    December 23, 2010 at 1:32 am | #24

    I’m correcting myself… that one line should be replaced with the following 5 lines:

    if [ $VID = 1 ]; then
    FPS=`mkvinfo “$MKV” | grep duration | sed ‘s/.*(//’ | sed ‘s/f.*//’ | head -n 1`
    else
    FPS=`mkvinfo “$MKV” | grep duration | sed ‘s/.*(//’ | sed ‘s/f.*//’ | tail -n 1`
    fi

    my original post assumed that video was the first track, but this is not necessarily the case. These 5 lines are the way to go.

    I would still be curious to know why mplayer -identify does not return correct FPS in some instances? Does anyone know?

  25. EgoRiot
    August 3, 2011 at 5:18 pm | #25

    I wanted to thank you, this worked great for me! I am now able to convert mkv to mp4s to play on my ps3. thanks!

  26. Sam
    September 1, 2011 at 12:23 pm | #26

    On the ‘Error decoding sei message’: Could it be subtitles? This converter has removed all the subtitles that were in my files, and given this error message. Just a thought. Other than that, great tool!

  27. September 1, 2011 at 12:28 pm | #27

    Hmm, it is a possibility. I hadn’t noticed it removing subtitles, although that makes sense since I’m just pulling the video and audio tracks out of the MKV container.

    Glad I could help! 🙂

  1. December 22, 2009 at 9:54 am | #1
  2. April 18, 2010 at 5:40 pm | #2

Leave a Reply

Your email address will not be published. Required fields are marked *