Converting MKV
1. Introduction
2. PS3 MPEG-4 Limits
3. Installing the tools
4. Splitting the .MKV
5. Getting .MKV info
6. Extract the Video
6.1 Check Video Profile
7. Convert the Audio
7.1 Down mixing to Stero is simple and compatible?
7.2 Understanding Channel Arrangements for 5.1 Audio Formats
7.3 Using mplayer with NeroAacEnc or faac to make AAC 5.1
8. Creating the MPEG-4
9. Scripting it all
9.1 MKV-Ripper.sh
10. Old Stuff
Introduction
This is based on the following blog post adding to effort of my own to correctly map channel assignments for AAC 5.1
Like the blog post above, I want to keep re-encoding to a minimum.
PS3 MPEG-4 Limits
During the process of figuring out the conversion of MKV to MP4 I have discovered there are some limits to what the PS3 will play.
- .MP4 files must be less than 4GB, that is a FAT32 limit too.
- Some people have mentioned that AAC must be encoded at less than 160kbps to be compatible with the PS3. That is a myth.
- I have downloaded movie trailers from the PS Store which are 224kbps and now also created MPEG-4 using ~300kbps 5.1 AAC which works fine.
Installing the tools
This install the tools for GPAC, mkvtoolnix, mpeg4ip and ffmpeg.
sudo aptitude install a52dec faac ffmpeg gpac hexedit mkvtoolnix-gui mpeg4ip-utils mpeg4ip-server
I also use the Nero AAC encoder as it produces better results than faac, for more details see the URL below...
wget http://ftp6.nero.com/tools/NeroDigitalAudio.zip
wget ftp://ftp6.nero.com/tutorials/nerodigital/audio_encoder/NeroDigitalAudio_tut_eng.pdf
unzip NeroDigitalAudio.zip
chmod 755 linux/*
sudo mv linux/* /usr/local/bin/
Splitting the .MKV
If the .mkv file is large than 4GB we need to split it. This is because, that although MP4Box support splitting MPEG-4 files, the PS3 will only play the first part and any subsequent parts refuse to play.
Therefore if the .mkv file is greater than 4GB we will split it then and convert those parts.
mkvmerge -o movie_split.mkv --split 4G movie.mkv
Getting .MKV info
In order to extract the video, audio and/or subtitles from the .mkv we first need to know what is in the container.
mkvmerge -i movie.mkv
Should return something like the following...
File ’movie.mkv’: container: Matroska
Track ID 1: video (V_MPEG4/ISO/AVC)
Track ID 2: audio (A_AC3)
Check the video is encoded in the proper format, look for "V_MPEG4/ISO/AVC" and make a note of which tracks hold the video and audio you are after. Now we need to get the framerate using the following...
mkvinfo movie.mkv | grep fps
...which should return something like...
| + Default duration: 41.708ms (23.976 fps for a video track)
Extract the Video
Use a command similar to the one below, simply replacing the video and audio track numbers are required.
mkvextract tracks movie.mkv 1:movie.h264
Check Video Profile
Some video comes in profile 5.1 which the PS3 doesn't support, the PS3 only supports profile 4.1. So first check the profile level...
file movie.h264
The output will look something like this.
movie.h264: JVT NAL sequence, H.264 video @ L 51
If the number after the @ is 41 you have 4.1 profile which is great and you can skip ahead to the
Convert the Audio section.
If you have 51 after the @ then you need to change the profile level which is easy to do and takes less than a second using the following bit of Python.
python -c "f=open('movie.h264','r+b'); f.seek(7); f.write('\x29'); f.close()"
You can open movie.h264 in hex editor, such as 'hexedit' and manually patch the file.
hexedit movie.h264
Look for the following on the first line:
67 4D 40 33
Which we change to:
67 4D 40 29
NOTE! Different number combinations than the above do exist, the good news is that the 33 remains the same and is the one that you want to change to 29. What you're looking for in the hex editor, is the 2nd distinct column grouping of numbers. The 33 will be on the top line and is the right most number in that 2nd grouping.
- To save and exit 'hexedit' use Ctrl+x
- To exit 'hexedit' use Ctrl+c
After changing the profile level check it is now 4.1
file movie.h264
Which should return something like...
movie.h264: JVT NAL sequence, H.264 video @ L 41
Convert the Audio
Whilst is it technically possible to include Dolby Digital and DTS audio in an MPEG-4 container, there are not currently any MPEG-4 container tools (other than Handbrake) which support that configuration and I have yet to get my PS3 to see, let alone play, an AC3 audio track embedded in an MPEG-4 container. Therefore, we do need to re-encode the AC3/DTS to AAC.
Down mixing to Stero is simple and compatible?
We can convert AC3/DTS in the .mkv to either Stereo or 5.1 multi channel AAC, but there are some considerations when choosing 5.1 AAC.
- Multi-channel 5.1 AAC is supported on the PS3 but not other devices, so if you also want to watch your MPEG-4 on Xbox 360 or other devices then you'll not have any audio if you use 5.1 AAC.
- The various 5.1 format channel arrangements are different, meaning that you will need to know how to map up the channels correctly. If you do not use the correct channel mappings then the centre channel is typically misplaced which sounds really odd.
- At the time of writing VLC 0.8.6e and Xine 0.99.5 do not correctly place the channels in AAC 5.1 audio, even if you get the channel arrangement right!
- To play 5.1 AAC you will need an amplifier that can decode AAC (few can) or one that can play the multichannel LPCM that the PS3 decodes.
- Depending on the method used, converting 5.1 AC3/DTS to 5.1 AAC can more time consuming than converting to Stereo AAC.
So, a lot of good reasons to not bother with AAC 5.1 and just down mix to stereo. If you need Stereo then use the method below.
ffmpeg : Downmix to Stereo AAC
This method works well for down mixing 5.1 audio to stereo and it works well with both AC3 and DTS. 'ffmpeg' has multi channel options but they garble DTS and have no channel re-mapping capability.
ffmpeg -i movie.mkv -vn -acodec mpeg4aac -ac 2 -ar 48000 -ab 160k movie_2ch.aac
Understanding Channel Arrangements for 5.1 Audio Formats
Now, I could have stopped with the simple down mix method above, but that just doesn't sit well with me because I want multi channel damn it! ;-)
Wouldn't it be great if all the 5.1 audio formats had the same channel arrangement? Fact, is they are nearly all different.
Channel Arrangement for Multi Channel 5.1 Audio Formats
| Format | Chan 0 | Chan 1 | Chan 2 | Chan 3 | Chan 4 | Chan 5
|
|---|
| 5.1 WAV | FL | FR | FC | LFE | SL | SR
|
| 5.1 AC3 | FL | FC | FR | SL | SR | LFE
|
| 5.1 DTS | FC | FL | FR | SL | SR | LFE
|
| 5.1 AAC | FC | FL | FR | SL | SR | LFE
|
| 5.1 AIFF | FL | SL | FC | FR | SR | LFE
|
- FL : Front Left
- FC : Front Center
- FR : Front Right
- SL : Surround Left
- SR : Surround Right
- LFE : Low Frequency Effects (Sub)
Using mplayer with NeroAacEnc or faac to make AAC 5.1
This is the only method I have found which can create 5.1 Multi-Channel AAC
with the correct channel assignments. That last point needs driving home,
with the correct channel assignments. I have found numerous methods which claim they convert AC3 5.1 or DTS 5.1 to AAC 5.1, and certainly the resultant AAC files do have 6 channels. It is just a shame the channels are in the wrong places which sounds extremely funky when you playback through a 5.1 capable home cinema sound system. Grrr.
The problem is this, the .wav that 'mplayer' outputs will have the channel arrangement of the source audio (i.e AC3 or DTS) and 'NeroAacEnc' and 'faac' expect different channel arrangements (different from each other and different from AC3 and DTS) for their input.
After some extensive testing I have figured out several channel mappings to correctly created AAC 5.1 from AC3 5.1, DTS 5.1 and WAV 5.1.
NOTE! some of following has been validated and some hasn't. For example, AC3 5.1 to AAC 5.1 is confirmed working when using 'NeroAacEnc' and I'm fairly sure the DTS 5.1 to AAC 5.1 using 'NeroAacEnc' works too. So, apart from possible typos, I think my tables are correct.
- 'NeroAacEnc' expects the .wav input file to have a WAV 5.1 channel arrangement as shown below.
- I am fairly sure 'faac' expects the .wav input file to have the following channel arrangement.
- mplayer and Totem (with GStreamer) playback the AAC 5.1 multi-channel stuff correctly on my laptop.
- Xine 0.95 and VLC 0.8.6.e do not playback the AAC 5.1 multi-channel stuff correctly on my laptop.
- When I play AAC 5.1 with mplayer and Totem (GStreamer) the channel arrangement match what my PS3 produces through my home cinena system.
Channel Arrangement for NeroAacEnc and faac 5.1 WAV input
| Format | Chan 0 | Chan 1 | Chan 2 | Chan 3 | Chan 4 | Chan 5
|
|---|
| NeroAacEnc | FL | FR | FC | LFE | SL | SR
|
| faac | SL | SR | FL | FR | C | LFE
|
Multi Channel 5.1 Channel Maps for encoding AAC 5.1
Therefore, based on the assumptions above, here are the mplayer channel mappings that should correctly present AC3 5.1, DTS 5.1 and WAV 5.1 to 'NeroAacEnc' and 'faac'
AC3 5.1 -> AAC 5.1 Encoder Input
mplayer Channel Map - AC3 5.1 to
NeroAacEnc and faac
| Channel Name | Source AC3 5.1 Chan No. | Input NeroAacEnc Chan No. | mplayer Map
|
|---|
| FL | 0 | 0 | 0:0
|
| C | 1 | 2 | 1:2
|
| FR | 2 | 1 | 2:1
|
| SL | 3 | 4 | 3:4
|
| SR | 4 | 5 | 4:5
|
| LFE | 5 | 3 | 5:3
|
- NeroAacEnc : channels=6:6:0:0:1:2:2:1:3:4:4:5:5:3
| Channel Name | Source AC3 5.1 Chan No. | Input faac Chan No. | mplayer Map
|
|---|
| FL | 0 | 2 | 0:2
|
| C | 1 | 4 | 1:4
|
| FR | 2 | 3 | 2:3
|
| SL | 3 | 0 | 3:0
|
| SR | 4 | 1 | 4:1
|
| LFE | 5 | 5 | 5:5
|
- faac : channels=6:6:0:2:1:4:2:3:3:0:4:1:5:5
DTS 5.1 -> AAC 5.1 Encoder Input
mplayer Channel Map - DTS 5.1 to
NeroAacEnc and faac
| Channel Name | Source DTS 5.1 Chan No. | Input NeroAacEnc Chan No. | mplayer Map
|
|---|
| C | 0 | 2 | 0:2
|
| FL | 1 | 0 | 1:0
|
| FR | 2 | 1 | 2:1
|
| SL | 3 | 4 | 3:4
|
| SR | 4 | 5 | 4:5
|
| SR | 5 | 3 | 5:3
|
- NeroAacEnc : channels=6:6:0:2:1:0:2:1:3:4:4:5:5:3
| Channel Name | Source DTS 5.1 Chan No. | Input faac Chan No. | mplayer Map
|
|---|
| C | 0 | 4 | 0:4
|
| FL | 1 | 2 | 1:2
|
| FR | 2 | 3 | 2:3
|
| SL | 3 | 0 | 3:0
|
| SR | 4 | 1 | 4:1
|
| SR | 5 | 5 | 5:5
|
- faac : channels=6:6:0:4:1:2:2:3:3:0:4:1:5:5
WAV 5.1 -> AAC 5.1 Encoder Input
mplayer Channel Map - WAV 5.1 to
NeroAacEnc and faac
| Channel Name | Source WAV 5.1 Chan No. | Input NeroAacEnc Chan No. | mplayer Map
|
|---|
| FL | 0 | 0 | 0:0
|
| FR | 1 | 1 | 1:1
|
| C | 2 | 2 | 2:2
|
| LFE | 3 | 3 | 3:3
|
| SL | 4 | 4 | 4:4
|
| SR | 5 | 5 | 5:5
|
- NeroAacEnc : channels=6:6:0:0:1:1:2:2:3:3:4:4:5:5
| Channel Name | Source WAV 5.1 Chan No. | Input faac Chan No. | mplayer Map
|
|---|
| FL | 0 | 2 | 0:2
|
| FR | 1 | 3 | 1:3
|
| C | 2 | 4 | 2:4
|
| LFE | 3 | 5 | 3:5
|
| SL | 4 | 0 | 4:0
|
| SR | 5 | 1 | 5:1
|
- faac : channels=6:6:0:2:1:3:2:4:3:5:4:0:5:1
The mplayer Methods
Here are the methods using 'mplayer' with 'faac' and 'NeroAacEnc'. I use 'NeroAacEnc' since it is a better quality encoder, but I've include details for use 'faac' if you can't (or won't) use 'NeroAacEnc'.
AC3 5.1 to AAC 5.1 using mplayer and NeroAacEnc
mkfifo audiodump.wav
neroAacEnc -ignorelength -q 0.30 -if audiodump.wav -of movie_6ch.aac & mplayer movie.mkv -ac ffac3 -channels 6 -af format=s16le,channels=6:6:0:0:1:2:2:1:3:4:4:5:5:3 -vo null -vc null -ao pcm:fast:waveheader:file=audiodump.wav -novideo -quiet -nolirc
rm audiodump.wav
AC3 5.1 to AAC 5.1 using mplayer and faac
mkfifo audiodump.wav
faac -q 234 -o movie_6ch.aac -P -C 6 -X --mpeg-vers 4 audiodump.wav & mplayer movie.mkv -ac ffac3 -channels 6 -af format=s16le,channels=6:6:0:2:1:4:2:3:3:0:4:1:5:5 -vo null -vc null -ao pcm:fast:waveheader:file=audiodump.wav -novideo -quiet -nolirc
rm audiodump.wav
DTS 5.1 to AAC 5.1 using mplayer and NeroAacEnc
mkfifo audiodump.wav
neroAacEnc -ignorelength -q 0.30 -if audiodump.wav -of movie_6ch.aac & mplayer movie.mkv -ac ffdca -channels 6 -af format=s16le,channels=6:6:0:2:1:0:2:1:3:4:4:5:5:3 -vo null -vc null -ao pcm:fast:waveheader:file=audiodump.wav -novideo -quiet -nolirc
rm audiodump.wav
DTS 5.1 to AAC 5.1 using mplayer and faac
mkfifo audiodump.wav
faac -q 234 -o movie_6ch.aac -P -C 6 -X --mpeg-vers 4 audiodump.wav & mplayer movie.mkv -ac ffdca -channels 6 -af format=s16le,channels=6:6:0:4:1:2:2:3:3:0:4:1:5:5 -vo null -vc null -ao pcm:fast:waveheader:file=audiodump.wav -novideo -quiet -nolirc
rm audiodump.wav
Creating the MPEG-4
Now we need to make a MPEG-4 file with the video and audio we extracted/converted, specifying the video's frame rate that we noted earlier.
MP4Box -add movie.h264 -add movie_2ch.aac -fps 23.976 movie_2ch.mp4
Sadly, if MP4Box is used the split the .mp4 the PS3 will only play the first part, any subsequent parts refuse to play. This is why we split the .mkv, if it is large than 4GB, and then convert those .mkv parts. It ensures compatibility.
Scripting it all
After working out the various steps above, I have put it all together in an automated shell script.
MKV-Ripper.sh
Features
- Does work on Ubuntu Linux, should work on any other Linux/Unix flavour and possibly MacOSX providing you have the required tools installed.
- Checks that the required tools are available and tells you what is missing.
- Automated conversion of .mkv to PS3 compatible .mp4
- Also compatible with Xbox360 if '-2ch' override is used.
- Splits the .mkv, if it is greater than 4GB, to maintain PS3 and FAT32 compatibility for the resulting MPEG-4 files.
- Does not re-encode the H264 video
- Will detect profile 5.1 H264 and patch it to 4.1 in under a second
- Creates AAC 5.1 from AC3 5.1 and DTS 5.1 with the correct channel assignments
- Will use NeroAacEnc if available but fails over to faac.
- Any subtitles in the .mkv are extracted and converted to 3GPP Timed Text.
- 3GPP Timed Text is not (currently) accessible from the PS3, but does work with some software players.
Requirements
- file, stat, grep, cut, sed, rm, python, mktemp, mkfifo, mkvmerge, mkvinfo, mkvextract, mplayer, MP4Box, faac and optionally neroAacEnc.
Download
You can get the current version of my script from my SVN repository.
Screenshot
As if ;-)
Old Stuff
Err, this is older stuff, not being worked on right now.
References
$Id: ConvertingMKV,v 1.79 2008/08/19 07:01:38 martin Exp $