1. 程式人生 > >ffmpeg無法將音訊轉為mp3問題解決

ffmpeg無法將音訊轉為mp3問題解決

安裝完成ffmpeg後,就可以使用ffmpeg進行音訊檔案格式轉換。比如 ./ffmpeg -i /media/1.mp3 /media/1.wav, 通過該命令列可以將/media資料夾下1.mp3檔案轉換成WAV格式的。

    但是反過來 ./ffmpeg -i /media/1.WAV /media/1.MP3 卻不能轉換成Mp3格式,提示如下錯誤(找不到編碼器):
    Stream mapping:
    Stream #0:0 -> #0:0 (wav -> ?)
    Encoder (codec none) not found for output stream #0:0
    如果強行指定編碼器 ./ffmpeg -i /media/1.wav -acodec mp3 /media/1.mp3, 仍提示找不到編碼器錯誤:

    Unknown encoder 'mp3'

    這是因為,ffmpeg雖然是個開源軟體,但因為具體格式的版權原因,它並沒有包含所有的編解碼格式,或者有個格式只有對應的解碼器,但沒有編碼器,比如 Mp3就只有解碼器,能播放Mp3檔案,但卻沒有Mp3的編碼器,無法將其它格式轉換成Mp3。可以通過命令列 ./ffmpeg -codecs 查詢編解碼配置,第一個D表示Decoder,該格式能夠解碼;E表示Encoder,該格式可以編碼。從中可以看出Mp3不能編碼,Mp2倒是即可解碼 也可編碼。如何解決這個問題呢?    
D A D  mp1             MP1 (MPEG audio layer 1)

D A D  mp1float        MP1 (MPEG audio layer 1)
DEA D  mp2             MP2 (MPEG audio layer 2)
D A D  mp2float        MP2 (MPEG audio layer 2)
D A D  mp3             MP3 (MPEG audio layer 3)
D A D  mp3adu          ADU (Application Data Unit) MP3 (MPEG audio layer 3)
D A D  mp3adufloat     ADU (Application Data Unit) MP3 (MPEG audio layer 3)


    我的第一個方法是自己寫程式碼來完成。原始碼檔案中,Allcodecs.c中對各個格式進行註冊,先修改Mp3的註冊行,改為同時註冊解碼器和編碼器:
    REGISTER_ENCDEC  (MP2, mp2);
    REGISTER_DECODER (MP2FLOAT, mp2float);
    REGISTER_DECODER (MP3, mp3)  // 此行修改為 REGISTER_ENCDEC  (MP3, mp3)
    然後新增Mp3編碼器的實現Struct,裡面Init函式、encode函式、close函式使用Mp2的函式,因為我也不知道如何去實現Mp3的函式,或者說到程式碼實現級我也不知道Mp3和Mp2的區別在哪。
    AVCodec ff_mp3_encoder = {
    .name           = "mp3",
    .type           = AVMEDIA_TYPE_AUDIO,
    .id             = CODEC_ID_MP3,
    .priv_data_size = sizeof(MpegAudioContext),
    .init           = MPA_encode_init,
    .encode         = MPA_encode_frame,
    .close          = MPA_encode_close,
    .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
    .supported_samplerates= (const int[]){44100, 48000,  32000, 22050, 24000, 16000, 0},
    .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"),
    .defaults       = mp3_defaults,
};
    重新編譯上線。 用命令列./ffmpeg -i /media/1.WAV /media/1.MP3 試了一下,能成功生成1.mp3檔案,檔案也能播放。似乎沒有問題了,單用 file /media/1.mp3 查看了一下,發現檔案不是Mp3格式的,而是Mp2格式的:
    /media/1.mp3: MPEG ADTS, layer II, v1, 128 kbps, 44.1 kHz, Stereo
    很遺憾,自行修改程式碼的方式行不通,因為不是每個編解碼格式協議的專家,自行修改程式碼失敗的風險很大,不僅是Mp3,還有一些其他格式比如AMR OGG H.263是沒有編碼器的。所以,第二個方案,使用成熟的第三方編碼器和ffmpeg結合。

    Mp3比較好的開源第三方庫是libmp3lame(簡稱Lame)。我下了一個最新版本(3.99.4)的Lame原始碼,編譯它:
    首先配置: ./configure --prefix=/shared --enable-shared --enable-static
    然後編譯:  make
               make install
    生成檔案: 動態連結庫 /shared/lib/libmp3lame.so 和 靜態連結庫 /shared/lib/libmp3lame.a。這裡只需要使用動態連結庫,將.so檔案拷貝到/lib中,這個資料夾是動態連結庫的預設搜尋路徑, 讓ffmpeg執行時可以找到。
    然後對ffmpeg配置libmp3lame: ./configure --enable-libmp3lame
    重新編譯ffmpeg,執行轉化命令,看看效果如何。
    首先執行 ./ffmpeg -codecs 檢視可用編解碼的變化,可以看到多出了libmp3lame編碼器,帶E的:
    D V D  lagarith        Lagarith lossless
    EA    libmp3lame      libmp3lame MP3 (MPEG audio layer 3)
    EV    ljpeg           Lossless JPEG
    D V D  loco            LOCO
    然後執行 ./ffmpeg -i /media/1.WAV /media/1.MP3, 生成1.mp3,用File命令檢視,確實是Mp3檔案。
    /media/1.mp3: Audio file with ID3 version 2.4.0, contains: MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
    大功告成,問題解決。
    也可在命令列中指定編解碼生成Mp3檔案:./ffmpeg -i /media/1.WAV -acodec libmp3lame /media/1.MP3.