Thursday, May 13, 2010
Having recently bought a Sony Handycam video camera, I was suddenly faced with an unanticipated need to manually convert the recorded movies into a usable format using open source tools available for Linux. Sony assumes that you run their proprietary software (of course available for Windows and OS X only) for copying recorded movies to your hard drive and burning them to DVD or Blu-Ray discs. For burning HD movies, Sony's solution is the AVCHD format, which is a Blu-Ray-like format for DVDs. A far from optimal solution, considering I do not and do not plan to install Windows or OS X, and that the AVCHD format seems poorly standardized, so that an AVCHD disc working on a Sony Blu-Ray player might not work on Blu-Ray players from other manufacturers. My solution to this problem is converting the movies to a more standardized format.
In many cases, you can convert the .mts files with ffmpeg directly, so you should try that first. However, with some clips from my camera, ffmpeg has problems interpreting the file. In that case, it seems you have to take the long way home, converting the video to a raw YUV format, before recoding it to your desired output format.
To begin with, you need to extract the movies stored on the camera. When mounting the camera as a USB mass storage device, a large directory structure is revealed, in parts similar to the AVCHD directory structure. The recorded movies can be found as .mts files in the AVCHD/BDMV/STREAM folder. Copy these files to a working directory.
We will need to compile some tools for the conversion. The first of these is xporthdmv. Download the source package (xport.zip) from the developers web page and unzip it. Then compile it:
gcc -o xporthdmv xport.c
Now adjust file permissions and copy the executable to somewhere in your path as needed.
The next tool is ldecod. Download the source package (latest version, which at the time of writing is jm17.0.zip) from the developers web page, and unpack it. The source can be compiled with the following commands, executed from the JM folder:
chmod 755 unixprep.sh
sed -i s/-march=pentium4//g Makefile
Now adjust the file permissions of the resulting ldecod.exe executable (located in the JM/bin directory) and copy it as ldecod to somewhere in your path as needed.
You will also need ffmpeg, but since this is probably available through repositories for your Linux distribution, I will leave that installation safely in your hands.
Now we are ready to start converting. First, the .mts file will need to be demuxed into the corresponding audio and video files:
xporthdmv -nh movie.mts 1 1 1
This will result in two files bits0001.mpv (H.264 video) and bits0001.mpa (AC3 audio). The reason why we are using xporthdmv to demux, and not using ffmpeg directly, is that ffmpeg has trouble reading some of the .mts files that the Sony Handycam generates.
Next, we will use ldecod to convert the video to YUV. It might be possible to use the demuxed video directly with ffmpeg, but in my attempts, ffmpeg has been having problems reading the file, presumably since it is interlaced 50 fps video, while the container indicates that it is 25 fps. The resulting file is huge, so make sure you have enough space. This is how to do the conversion:
ldecod -i bits0001.mpv -o movie.yuv
We can now used the demuxed and converted video and audio files as input to ffmpeg. Even if recoding is not generally recommended, I wanted to have the movies in a standard-compliant mp4 container, and get rid of the horrible, horrible interlacing. Here is how to generate a deinterlaced mp4 with H.264 video and AAC audio:
/usr/bin/ffmpeg -r 25 -s 1440x1080 -i movie.yuv -i bits0001.mpa -acodec libfaac -ar 48000 -ab 160k -ac 2 -vcodec libx264 -vpre hq -b 3000k -aspect 16:9 -deinterlace movie.mp4
The options could need to be adjusted (for example the first and/or second -r 25, the first one indicating that I have a PAL camera, and the second that I want to keep that framerate for the output) if you have a different input, or if you want other bitrates etc, for the output.
In the next example, we are generating a low resolution AVI file with XViD video and MP3 audio, since this is one of the most widely supported formats for standalone players:
/usr/bin/ffmpeg -r 25 -s 1440x1080 -i movie.yuv -i bits0001.mpa -f avi -vcodec libxvid -vtag XVID -s 320x270 -r 25 -aspect 16:9 -b 700k -qmin 3 -qmax 5 -bufsize 4096 -mbd 2 -bf 2 -flags +4mv -trellis -aic -cmp 2 -subcmp 2 -g 300 -acodec libmp3lame -ar 48000 -ab 128k -ac 2 movie.avi
Again, adust the options if you want higher resolution, higher bitrate, etc.