国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android本地視頻壓縮方案的示例代碼

2019-10-22 18:16:02
字體:
來源:轉載
供稿:網友

前言

本文討論的不是類似秒拍的短視頻錄制,而是用戶選擇本地一個現有視頻,壓縮后上傳。秒拍的實現其實是自定義視頻錄制功能,從而控制錄制時長,分辨率,碼率等,生成體積很小的視頻再上傳。而我們則沒辦法控制原視頻的參數,可能是一個很大的視頻需要壓縮處理。

思路

利用ffmpeg對視頻轉碼,通過設定參數生成分辨率和碼率更小的視頻,實現壓縮。當然,ffmpeg的功能遠不止如此,這是一個很大的專題。

用到的開源庫:https://github.com/WritingMinds/ffmpeg-android-java

使用方法

基本原理:將android環境下可執行文件ffmpeg存放在本地,代碼執行ffmpeg的壓縮命令。

//將開源庫中asset目錄的ffmpeg可執行文件,拷貝到 app的data/data/files目錄FFmpeg.getInstance(this).loadBinary(null);

這個方法是異步執行,所以最好在Application中執行。方法有執行成功與否的回調,這里我傳入null不關心結果。執行完看下手機中的目錄:

Android,本地視頻壓縮,視頻壓縮

既然是可執行文件,那么在android shell環境下肯定可以執行了。adb shell進入手機看下(前提是手機已經獲取root權限):

Android,本地視頻壓縮,視頻壓縮

執行ffmpeg的一個命令:比如查看ffmpeg的當前版本:./ffmpeg -version

Android,本地視頻壓縮,視頻壓縮

接著就可以在代碼中,使用ffmpeg的各種命令了:把命令寫入String[],然后調用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(){});

參數解釋:

  1. -threads: 執行線程數,傳入1 單線程壓縮
  2. -i:input路徑,傳入視頻文件的路徑
  3. -c:v:編碼格式,一般都是指定libx264
  4. -crf: 編碼質量,取值范圍是0-51,默認值為23,數字越小輸出視頻的質量越高。這里的30是我們經過測試得到的經驗值
  5. -preset:轉碼速度,ultrafast,superfast,veryfast,faster,fast,medium,slow,slower,veryslow和placebo。ultrafast編碼速度最快,但壓縮率低,生成的文件更大,placebo則正好相反。x264所取的默認值為medium。需要說明的是,preset主要是影響編碼的速度,并不會很大的影響編碼出來的結果的質量。
  6. -acodec:音頻編碼,一般采用libmp3lame
  7. arg.thumbVideoPath:最后傳入的是視頻壓縮后保存的路徑
  8. -y:輸出時覆蓋輸出目錄已存在的同名文件(如果不加此參數,就不會覆蓋)

問題解決

此開源庫用于視頻壓縮在實際開發中存在不少問題,下面一一解決

1.壓縮進度反饋

執行轉碼命令后,onProgress只是不停輸出字符串,而且文本很長 需要正則表達式從中截取轉碼進度反饋:

        @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.低碼率視頻壓縮會變大

實際中發現有些原質量較差的視頻壓縮后,體積反而變大。

處理方法:壓縮前先執行對視頻提取信息的命令,小于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);//執行壓縮                }else {                  //放棄壓縮,直接使用原文件                }              }catch (Exception e){              }            }          }        }

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

3.多線程壓縮多個視頻

開源庫中執行ffmpeg的命令是在AsycTask執行的:

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

execute 方法在api 11之后是串行方法,就是說開源庫已經限制為單線程。

改為:ffmpegExecuteAsyncTask.executeOnExecutor(Executors.newCachedThreadPool()); 可以使用多線程

測試中發現多個視頻同時壓縮,手機會嚴重發熱,強烈建議采用原設計 。

4.壓縮速度和質量

手機性能有限,壓縮視頻速度不太理想,即使在PC端用 格式工廠壓縮轉碼視頻也不是很快。

壓縮質量還可以,基本能保持和原視頻一樣的清晰度。下面是測試數據:

Android,本地視頻壓縮,視頻壓縮

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 象山县| 大化| 龙川县| 兴文县| 荣成市| 开平市| 大庆市| 镇巴县| 色达县| 迁西县| 天全县| 昌江| 岚皋县| 三原县| 武功县| 始兴县| 佛山市| 襄垣县| 忻州市| 华亭县| 锦屏县| 贵溪市| 太康县| 内黄县| 黑山县| 云龙县| 密云县| 天峻县| 岢岚县| 宁明县| 肇东市| 莎车县| 秦皇岛市| 岫岩| 东城区| 榆中县| 安图县| 日喀则市| 磐安县| 壤塘县| 名山县|