Android本地視頻壓縮方案

前言

本文討論的不是類似秒拍的短視頻錄制惑畴,而是用戶選擇本地一個(gè)現(xiàn)有視頻,壓縮后上傳寡夹。秒拍的實(shí)現(xiàn)其實(shí)是自定義視頻錄制功能,從而控制錄制時(shí)長(zhǎng)厂置,分辨率菩掏,碼率等,生成體積很小的視頻再上傳昵济。而我們則沒辦法控制原視頻的參數(shù)智绸,可能是一個(gè)很大的視頻需要壓縮處理。

思路

利用ffmpeg對(duì)視頻轉(zhuǎn)碼访忿,通過設(shè)定參數(shù)生成分辨率和碼率更小的視頻瞧栗,實(shí)現(xiàn)壓縮。當(dāng)然海铆,ffmpeg的功能遠(yuǎn)不止如此迹恐,這是一個(gè)很大的專題。
用到的開源庫(kù):https://github.com/WritingMinds/ffmpeg-android-java

使用方法

基本原理:將android環(huán)境下可執(zhí)行文件ffmpeg存放在本地卧斟,代碼執(zhí)行ffmpeg的壓縮命令殴边。


//將開源庫(kù)中asset目錄的ffmpeg可執(zhí)行文件憎茂,拷貝到 app的data/data/files目錄

FFmpeg.getInstance(this).loadBinary(null);

這個(gè)方法是異步執(zhí)行,所以最好在Application中執(zhí)行锤岸。方法有執(zhí)行成功與否的回調(diào)竖幔,這里我傳入null不關(guān)心結(jié)果。執(zhí)行完看下手機(jī)中的目錄:

image.png

既然是可執(zhí)行文件是偷,那么在android shell環(huán)境下肯定可以執(zhí)行了拳氢。adb shell進(jìn)入手機(jī)看下(前提是手機(jī)已經(jīng)獲取root權(quán)限):

image.png

執(zhí)行ffmpeg的一個(gè)命令:比如查看ffmpeg的當(dāng)前版本:./ffmpeg -version

image.png

接著就可以在代碼中,使用ffmpeg的各種命令了:把命令寫入String[]蛋铆,然后調(diào)用fFmpeg.execute 即可

獲取視頻文件的信息

String[] command = new String[]{"-i", arg.filePath};

try {

            fFmpeg.execute(commands, new ExecuteBinaryResponseHandler(){

                @Override

                public void onStart() {}

                @Override

                public void onProgress(String message) {

                    Log.e("dml", "onProgress: message is " + message);

                }

                @Override

                public void onFailure(String message) {

                    Log.e("dml", "onFailure: message is " + message);

                }

                @Override

                public void onSuccess(String message) {

                    Log.e("dml", "onSuccess: message is " + message);

                }

                @Override

                public void onFinish() {

                    Log.e("dml", "onFinish: ");

                }

            });

        } catch (FFmpegCommandAlreadyRunningException e) {

            e.printStackTrace();

        }

壓縮視頻:

String[] commands = new String[]{"-threads","1","-i", arg.filePath, "-c:v", "libx264","-crf","30","-preset", "superfast" ,"-y", "-acodec","libmp3lame",arg.thumbVideoPath};

fFmpeg.execute(commands, new ExecuteBinaryResponseHandler(){});

參數(shù)解釋:

  • -threads: 執(zhí)行線程數(shù)馋评,傳入1 單線程壓縮

  • -i:input路徑,傳入視頻文件的路徑

  • -c:v:編碼格式戒职,一般都是指定libx264

  • -crf: 編碼質(zhì)量栗恩,取值范圍是0-51,默認(rèn)值為23洪燥,數(shù)字越小輸出視頻的質(zhì)量越高磕秤。這里的30是我們經(jīng)過測(cè)試得到的經(jīng)驗(yàn)值

  • -preset:轉(zhuǎn)碼速度,ultrafast捧韵,superfast市咆,veryfast,faster再来,fast蒙兰,medium,slow芒篷,slower搜变,veryslow和placebo。ultrafast編碼速度最快针炉,但壓縮率低挠他,生成的文件更大,placebo則正好相反篡帕。x264所取的默認(rèn)值為medium殖侵。需要說(shuō)明的是,preset主要是影響編碼的速度镰烧,并不會(huì)很大的影響編碼出來(lái)的結(jié)果的質(zhì)量拢军。

  • -acodec:音頻編碼,一般采用libmp3lame

  • arg.thumbVideoPath:最后傳入的是視頻壓縮后保存的路徑

  • -y:輸出時(shí)覆蓋輸出目錄已存在的同名文件(如果不加此參數(shù)怔鳖,就不會(huì)覆蓋)

問題解決

此開源庫(kù)用于視頻壓縮在實(shí)際開發(fā)中存在不少問題茉唉,下面一一解決
1.壓縮進(jìn)度反饋
執(zhí)行轉(zhuǎn)碼命令后,onProgress只是不停輸出字符串,而且文本很長(zhǎng) 需要正則表達(dá)式從中截取轉(zhuǎn)碼進(jìn)度反饋:

                @Override
                public void onProgress(String s) {
                    Pattern timePattern = Pattern.compile("(?<=time=)[\\d:.]*");
                    Scanner sc = new Scanner(s);
                    String match = sc.findWithinHorizon(timePattern, 0);
                    if (match != null) {
                        String[] matchSplit = match.split(":");
                        if (duration!= 0) {
                            float progress = (Integer.parseInt(matchSplit[0]) * 3600 +
                                    Integer.parseInt(matchSplit[1]) * 60 +
                                    Float.parseFloat(matchSplit[2])) / duration;
                            int showProgress = (int) (progress * 100);
                            if(showProgress>100){
                                showProgress = 100;
                            }
                            notify.compressProgress(getTag(),showProgress);
                        }
                    }
                }

2.低碼率視頻壓縮會(huì)變大
實(shí)際中發(fā)現(xiàn)有些原質(zhì)量較差的視頻壓縮后赌渣,體積反而變大魏铅。
處理方法:壓縮前先執(zhí)行對(duì)視頻提取信息的命令,小于1024kb/s的視頻 不壓縮:

                @Override
                public void onProgress(String s) {
                    //Log.d("dml","pre onProgress  = " + s);
                    if(s.contains("Stream #0:0")){
                        String tem = s.substring(0, s.indexOf("kb/s"));
                        String type ;
                        int pos = tem.lastIndexOf(",");
                        if (pos != -1) {
                            type = tem.substring(pos + 1,tem.length()).trim();
                            try {
                                Integer integer = Integer.parseInt(type);
                                if(integer > 1024){
                                    pressV(fFmpeg);//執(zhí)行壓縮
                                }else {
                                   //放棄壓縮坚芜,直接使用原文件
                                }
                            }catch (Exception e){
                            }
                        }
                    }
                }

并且在壓縮成功后览芳,檢查壓縮后的文件和原文件大小,如果變大了鸿竖,直接使用原文件沧竟。

3.多線程壓縮多個(gè)視頻
開源庫(kù)中執(zhí)行ffmpeg的命令是在AsycTask執(zhí)行的:

            ffmpegExecuteAsyncTask = new FFmpegExecuteAsyncTask(command , timeout, ffmpegExecuteResponseHandler);
            ffmpegExecuteAsyncTask.execute();

execute 方法在api 11之后是串行方法,就是說(shuō)開源庫(kù)已經(jīng)限制為單線程缚忧。
改為:ffmpegExecuteAsyncTask.executeOnExecutor(Executors.newCachedThreadPool()); 可以使用多線程
測(cè)試中發(fā)現(xiàn)多個(gè)視頻同時(shí)壓縮悟泵,手機(jī)會(huì)嚴(yán)重發(fā)熱,強(qiáng)烈建議采用原設(shè)計(jì) 闪水。

4.壓縮速度和質(zhì)量
手機(jī)性能有限糕非,壓縮視頻速度不太理想,即使在PC端用 格式工廠壓縮轉(zhuǎn)碼視頻也不是很快球榆。
壓縮質(zhì)量還可以朽肥,基本能保持和原視頻一樣的清晰度。下面是測(cè)試數(shù)據(jù):


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末持钉,一起剝皮案震驚了整個(gè)濱河市衡招,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌每强,老刑警劉巖始腾,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異空执,居然都是意外死亡浪箭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門辨绊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)奶栖,“玉大人,你說(shuō)我怎么就攤上這事邢羔。” “怎么了桑孩?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵拜鹤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我流椒,道長(zhǎng)敏簿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮惯裕,結(jié)果婚禮上温数,老公的妹妹穿的比我還像新娘。我一直安慰自己蜻势,他們只是感情好撑刺,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著握玛,像睡著了一般够傍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上挠铲,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天冕屯,我揣著相機(jī)與錄音,去河邊找鬼拂苹。 笑死安聘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瓢棒。 我是一名探鬼主播浴韭,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼音羞!你這毒婦竟也來(lái)了囱桨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗅绰,失蹤者是張志新(化名)和其女友劉穎舍肠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窘面,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡翠语,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了财边。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肌括。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖酣难,靈堂內(nèi)的尸體忽然破棺而出谍夭,到底是詐尸還是另有隱情,我是刑警寧澤憨募,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布紧索,位于F島的核電站,受9級(jí)特大地震影響菜谣,放射性物質(zhì)發(fā)生泄漏珠漂。R本人自食惡果不足惜晚缩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望媳危。 院中可真熱鬧荞彼,春花似錦、人聲如沸待笑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)滋觉。三九已至签夭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間椎侠,已是汗流浹背第租。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留我纪,地道東北人慎宾。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像浅悉,于是被迫代替她去往敵國(guó)和親趟据。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,303評(píng)論 25 707
  • 前幾天項(xiàng)目需要壓縮視頻术健,Github上找了許多庫(kù)汹碱,要么就是太大,要么就是質(zhì)量不高荞估,其實(shí)我只需要壓縮視頻咳促,最好的方案...
    voiddog閱讀 26,301評(píng)論 59 82
  • 任之行于英彬日精進(jìn)分享 顯現(xiàn)-練習(xí)——使用 我行,一切行勘伺,我行任之行 選好人跪腹,做對(duì)事 懂人事 體驗(yàn)價(jià)值從滿足身...
    于英彬閱讀 161評(píng)論 0 0
  • 第一次接觸簡(jiǎn)書,就愛上了這個(gè)地方飞醉,簡(jiǎn)單干凈冲茸,只有單純的文字音符,卻每一次都會(huì)演繹靈魂的序曲缅帘。有雞湯卻樸實(shí)轴术,聽聽別人...
    Mango芒芒閱讀 393評(píng)論 1 1
  • 使用的東西我自己知道好不好。最令人感慨的就是明明我用的是好東西钦无,但是消費(fèi)者不買賬逗栽,最后企業(yè)虧損,這些好東西都銷聲匿...
    評(píng)綜俠影閱讀 591評(píng)論 0 51