通過ffmpeg將視頻編碼為H.264

瀏覽器的video標(biāo)簽,只支持部分編碼格式的視頻播放,由于客戶的視頻編碼各不相同,所以需要通過后端幫忙轉(zhuǎn)碼成統(tǒng)一的編碼。記錄一下通過 ffmpeg 工具解決視頻編碼問題。

首先下載ffmpeg工具,下載windows版本的,地址:https://ffmpeg.zeranoe.com/builds/
這個(gè)builds版本自動(dòng)很多編碼器,通過ffmpeg命令可以看到

ffmpeg.png

使用windows版是因?yàn)樵贚inux上折騰很久,編碼器沒有安裝成功,所以就放棄了,在windows上通過Kafka弄了個(gè)視頻轉(zhuǎn)碼服務(wù)。

命令參數(shù):http://www.mikewootc.com/wiki/sw_develop/multimedia/ffmpeg_app_param.html (找了很多,這是比較全的參數(shù)說明)

以下是視頻解碼的工具類,功能是將視頻轉(zhuǎn)碼成視頻編碼為 H.264,音頻編碼為 aac,是為了支持video標(biāo)簽,直接在瀏覽器播放,其他參數(shù)是為了壓縮視頻大小:

package com.spider.culture.process;

import java.util.ArrayList;
import java.util.List;

import com.spider.culture.util.Logger;

/**
 * 關(guān)于moov在前的說明
 * 一、關(guān)于chrome的快速播放和拖拽
 * 1、chrome使用H5的video標(biāo)簽來播放
 * 2、chrome很智能,如果讀取MP4文件,發(fā)現(xiàn)moov box不在文件前部,會(huì)直接讀取MP4的文件尾部,加載moov box
 * 3、拖拽時(shí),chrome根據(jù)moov box得到的關(guān)鍵幀的字節(jié)偏移量,采用range請(qǐng)求來請(qǐng)求
 * 二、關(guān)于Flash
 * 1、Flash如果讀取MP4文件,發(fā)現(xiàn)moov box不在文件前部,不會(huì)直接讀取MP4的文件尾部去尋找moov box,所以Flash要等文件全部下載完,取到文件尾部的moov頭,才可以正常播放。
 * @author spider
 *
 */
public class TransCodec {
    
    /**  
     * 視頻轉(zhuǎn)碼 (PC端MP4) 
     * @param ffmpegPath    轉(zhuǎn)碼工具的存放路徑 
     * @param upFilePath    用于指定要轉(zhuǎn)換格式的文件,要截圖的視頻源文件 
     * @param codcFilePath    格式轉(zhuǎn)換后的的文件保存路徑 
     * @return  
     * @throws Exception  
     */    
    public static boolean exchangeToMp4(String ffmpegPath,String upFilePath, String codcFilePath) {    
        // 創(chuàng)建List集合來保存轉(zhuǎn)換視頻文件為flv格式的命令   
        List<String> convert = new ArrayList<String>();    
        convert.add(ffmpegPath); // 添加轉(zhuǎn)換工具路徑    
        convert.add("-y"); // 該參數(shù)指定將覆蓋已存在的文件    
        convert.add("-i");  //輸入文件
        convert.add(upFilePath);  
        convert.add("-c:v");   //視頻
        convert.add("libx264");  //視頻編碼格式
        convert.add("-c:a");  //音頻編碼格式
        convert.add("aac");  
        convert.add("-strict");  //FFmpeg自帶的aac音頻編碼要帶上-strict -2 參數(shù)
        convert.add("-2");  
        convert.add("-pix_fmt");  //像素格式
        convert.add("yuv420p");  
        convert.add("-movflags");  //moov頭在前
        convert.add("faststart");  
        convert.add("-s");  //屏幕大小
        convert.add("320x240");
        convert.add("-b:v");    //視頻比特率 值越小文件越?。▎挝籦/s)
        convert.add("262144");  //262144 = 256*1024 bit/s
        convert.add("-b:a");    //音頻比特率(單位b/s)
        convert.add("131072");   //131072 = 1024*128 bit/s
        convert.add("-ac"); //音頻通道
        convert.add("2"); 
        convert.add("-ar"); //音頻采樣率
        convert.add("44100"); 
        //convert.add("-vf");   // 添加水印  
        //convert.add("movie=watermark.gif[wm];[in][wm]overlay=20:20[out]");  
        convert.add(codcFilePath);    //輸出文件
    
        boolean mark = true;    
                  
        try {    
            // redirectErrorStream(true) 標(biāo)準(zhǔn)錯(cuò)誤將與標(biāo)準(zhǔn)輸出合并,使得關(guān)聯(lián)錯(cuò)誤消息和相應(yīng)的輸出變得更容易
            Process videoProcess = new ProcessBuilder(convert).
                    redirectErrorStream(true).start();              
            // 合并的數(shù)據(jù)可從 Process.getInputStream() 返回的流讀取
            new PrintStream(videoProcess.getInputStream()).start();
            // 加上這句,系統(tǒng)會(huì)等待轉(zhuǎn)換完成。不加,就會(huì)在服務(wù)器后臺(tái)自行轉(zhuǎn)換。
            // 但是后期測(cè)試一直報(bào)錯(cuò),ffmpeg卡住,無法轉(zhuǎn)換,線程也在一直等待
//            videoProcess.waitFor();  
        } catch (Exception e) {    
            mark = false;
            Logger.error(String.format("視頻%s編碼轉(zhuǎn)換出錯(cuò)", upFilePath),e);   
        }    
        return mark;    
    }   

}
/**
 * 視頻轉(zhuǎn)換過程
 * @author spider
 *
 */
class PrintStream extends Thread{  
    
     java.io.InputStream __is = null;  
     public PrintStream(java.io.InputStream is)   
     {  
         __is = is;  
     }   
   
     public void run()   
     {  
         try   
         {  
             while(this != null)   
             {  
                 int _ch = __is.read();  
                 if(_ch != -1)   
                     System.out.print((char)_ch);
                 else break;  
             }  
         }   
         catch (Exception e)   
         {  
             e.printStackTrace();  
         }   
     }  
 }  

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容