2009年12月10日星期四

Extract Audio to Ogg with mencoder and oggenc

If you got a video of a though-provoking speech, you may want to convert it to a audio file which could copy into your mp3 player and be with you all the time. You can listen to it without boot up the computers. In some situations listen is much easier than seeing.

mp3 is one of the choice of the audio file formats. But for patent reason, my distribution doesn't ship lame. And I know there is ogg format [Ref1] which is more open and free. So I decided to encode all the audio into ogg format.

mencoder is part of mplayer which is very very powerful multi-media player. With mencoder/mplayer, you can play nearly all kind of video/audio files. We only care about the audio here. Let's start to work!

Basicly we need to extract the audio from the multi-media stream first:

mencoder video.mp4 -of rawaudio -ovc copy -oac pcm -o audio.pcm

-of rawaudio tells the mencoder to output audio stream only. Although the man page told me the -of option is still BETA but it works like a charm here. -ovc copy tells mencoder not to decode the video stream, which would consume less resources on your computer. -oac pcm tells mencoder to encode the audio to uncompressed PCM. Now, we can use ogg --raw audio.pcm to convert the raw pcm file to an ogg file.

But it's far from perfect. One big problem is this way of converting will last long time. When mencoder is extracting, oggenc doesn't convert simultaneously. So the time will be doubled. The other problem is you have to provide a relatively large temperary file to contain the pcm data. The method that could kill two birds with one stone is using a pipe. So the second version will be:

mencoder video.mp4 -of rawaudio -ovc copy -oac pcm -o - | \
    oggenc --raw - -o audio.ogg                            

But this version have bugs too. mencoder will print out something like:

MEncoder r29789-4.3.3 (C) 2000-2009 MPlayer Team
success: format: 0  data: 0x0 - 0x34468059      
libavformat file format detected.               
[lavf] Audio stream found,  -aid 0              
[lavf] Video stream found,  -vid 1              
VIDEO:  [H264]  1280x720  24bpp  29.970 fps    0.0 kbps ( 0.0 kbyte/s)
[V] filefmt:44  fourcc:0x34363248  size:1280x720  fps:29.970  ftime:=0.0334
========================================================================== 
Opening audio decoder: [faad] AAC (MPEG2/4 Advanced Audio Coding)          
FAAD: compressed input bitrate missing,  assuming 128kbit/s!               
AUDIO: 44100 Hz,  2 ch,  s16le,  128.0 kbit/9.07% (ratio: 16000->176400)
Selected audio codec: [faad] afm: faad (FAAD AAC (MPEG-2/MPEG-4 Audio))    
========================================================================== 
Ignoring video stream!                                                     
videocodec: framecopy (1280x720 24bpp fourcc=34363248)                     
Pos:   0.7s     22f ( 0%)  0.00fps Trem:   0min 141mb  A-V:0.068 [0:1411]  
Skipping frame!                                                            

which will corrupt the pcm stream to stdout and cause a corrupted ogg file eventually. In man page, it said -quiet will Make console output less verbose and -really-quiet will Display even less output and status messages than with -quiet but there is no guarantee that There won't be any message to stdout. That's unbearable for our condition.

So I come up with the idea that shell can redirect file-descriptor 3-10 to stdout, stdin or stderr. So we can write the pcm stream to file descriptor 3, and redirect the fd 3 to stdout. Then, redirect the origin stdout where the messages going to /dev/null. But how to tell mencoder write the pcm stream to fd 3? The trick is simple. Actually, fd n is /proc/self/fd/n for the process. What a great design of Linux system! Now, the pipe should be clean. Here is the final version:

mencoder video.mp4 -of rawaudio -ovc copy -oac pcm \
    -o /proc/self/fd/3 3>&1 1>/dev/null | \
    oggenc --raw - -o audio.ogg

There are two things you should care:

  1. You must redirect fd 3 when dumping things into it, otherwise it will break.
  2. The order in redirection is important. 3>&1 means redirect 3 to what 1 currently is. If you 1>/dev/null and then 3>&1, fd 3 will be redirected to /dev/null as well.

Now, you can extract the audio to ogg file flawlessly. Big thanks to http://www.commandlinefu.com where tell me the usage of mencoder.

[Ref1]http://www.vorbis.com/

没有评论:

发表评论