Cordova插件cordova-plugin-media-capture實現短視頻的錄制上傳和播放
小編:管理員 406閱讀 2022.09.13

1、網上的教程大部分都是虎頭蛇尾的不全的;ハ喑瓉沓フ娴母杏X就沒有一個是真正自己去寫一寫的,不然這里面這么多的坑就沒有一個人出來說說的?下面就寫寫我實現功能過程中的一些問題吧,代碼絕對完整并且按照步驟來一定可以成功!
2、本文主要講在Android中的實現,IOS端目前還在適配,不少問題到時候再另外單獨發一篇
實現邏輯1、客戶端利用cordova-plugin-media-capture插件調用攝像機權限進行視頻拍攝
2、拍攝的視頻上傳至服務器
3、服務端接收視頻文件并轉碼保存刪除源文件,將保存鏈接返回給客戶端
4、客戶端接收鏈接利用vedio插件進行顯示播放
實現步驟安裝cordova-plugin-media-capture插件這個沒啥可說的直接上代碼:
cordova plugin add cordova-plugin-media-capture復制客戶端調用攝像頭拍攝視頻
實現的過程中第一個坑出現了,就是cordova這個插件方法navigator.device.capture.captureVideo正如網上大部分教程一樣,確實能很順利的調起攝像頭進行拍攝,但是拍攝完之后總是顯示失敗的!原因是這個插件是需要獲取手機存儲權限的!然而偏偏這個插件就是沒有先去獲取這個存儲權限!必須要自己寫代碼去獲取權限!我就不信那些教程能不獲取權限直接調用攝像頭拍攝成功?要么就是他們在app中其他地方已經獲取過存儲權限了!比如調用圖庫的這個插件就會彈窗提示給權限!然后這個插件并不會,這是第一個坑!
調用方法前手動獲取手機權限首先要安裝權限的插件cordova-plugin-android-permissions
cordova plugin add cordova-plugin-android-permissions復制
查看客戶端是否有存儲權限如果沒有就申請獲取存儲權限
//申請存儲權限 var permissions = cordova.plugins.permissions; permissions.requestPermission(permissions.WRITE_EXTERNAL_STORAGE, successCallback, errorCallback) var successCallback = function(s){} var errorCallback = function(r){ alert("申請權限失敗請重試"); }復制調用相機進行短視頻拍攝
var options = { limit: 1, duration: 10, quality: 1 }; navigator.device.capture.captureVideo(this.onSuccess, this.onError, options);復制
1、這里對參數options進行一下說明
limit:拍攝視頻的數量
duration:拍攝視頻的時長(單位:s)
quality:拍攝視頻的質量(0:低質量 1高質量)
這里遇到了第二個坑,其實也跟Cordova官方有關,畢竟比較冷門的插件,也情有可原。但是我始終覺得比Hbuild的那個一套代碼走天下(小程序,Android,ios)好用的多
這里視頻拍攝我們完全不能自定義拍攝的畫質,官方只給了你兩個選擇,0低畫質,這個低畫質是真的低,低到就是你完全沒辦法看,所以拍攝質量其實就一個選項沒得選擇,那就是1高畫質,搞到什么程度呢?部分手機拍攝出來的居然是4K視頻!這個坑就是高畫質哪怕僅僅拍攝一兩秒的視頻都會有好幾M大,一個是上傳下載的時候服務器帶寬壓力,還有一個是這種極度高畫質的視頻在獲取到鏈接放vedio渲染到前端顯示的時候基本就是1s的視頻都會卡頓,哪怕你的服務器是10M的帶寬也是如此,那么這個坑就直接導致了需要多進行一個步驟---服務端轉碼保存
所以要么就是棄用這個插件用別的辦法實現,要么就是硬著頭皮直接來!所以沒得選擇!quality必須只能選擇高畫質了
2、在this.onSuccess成功回調方法中我們就可以獲取到視頻在客戶端的保存路徑了
onFail(message) { //取消照相功能提示 }, onSuccess(mediaFiles) { var _this = this var i, len; for (i = 0, len = mediaFiles.length; i < len; i += 1) { _this.path = mediaFiles[i].fullPath; _this.filename = mediaFiles[i].name; } },復制
this.path就是我們需要的路徑
利用文件上傳插件講拍攝的視頻上傳至服務器安裝cordova-plugin-file-transfercordova plugin add cordova-plugin-file-transfer復制上傳文件至服務器
上傳方法
//fileURL就是上面步驟中文件的路徑this.path upload(fileURL) { var options = new FileUploadOptions(); options.fileKey = "file1"; options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1); var params = {}; params.value1 = "test"; params.value2 = "param"; options.params = params; var ft = new FileTransfer(); //上傳地址:下面步驟我會講服務器接收文件的方法的 var SERVER = "填寫自己后臺的服務API地址"; ft.upload(fileURL, encodeURI(SERVER), success, fail, options); }復制
服務端接收文件的方法在下面步驟中有先別著急
success成功回調中會返回文件在服務器保存的url的
//上傳成功 var success = function (r) { var strs = JSON.parse(r.response); // alert("上傳成功! Code = " + JSON.parse(r.response).data.vedioShowUrl); _this.show = true; _this.uploadFlag = false; _this.playerOptions.sources[0].src = JSON.parse(r.response).data.vedioShowUrl; _this.saveVedioUrl = JSON.parse(r.response).data.saveVedioUrl; }復制
saveVedioUrl就是服務端返回的url
服務端接收視頻文件并轉碼保存,返回URL給客戶端接收視頻文件move_uploaded_file($_FILES["file1"]["tmp_name"],$_SERVER["DOCUMENT_ROOT"]."/Public/vedios/" . $_FILES["file1"]["name"]); $ofile = $_SERVER["DOCUMENT_ROOT"]."/Public/vedios/" . $_FILES["file1"]["name"];復制
文件保存在服務器的路徑是$_SERVER["DOCUMENT_ROOT"]."/Public/vedios/" . $_FILES["file1"]["name"];
轉碼1、轉碼我們需要使用ffmpeg來實現(本人服務器centos nginx)
這里第三個坑出現了,網上一堆的教程關于安裝ffmpeg大部分都是瞎寫的,全是紙上談兵壓根就是自己沒有去寫一寫的,所以千萬不要隨便找一個教程就去安裝,后面卸載可是個十分麻煩的事情
這里貼出來了一個用心寫代碼的兄弟的鏈接,非常好,鏈接上面已經貼出來了,再次非常感謝這位兄弟的教程,按照他的步驟一步步走就能成功安裝了

2、接下來我們就是利用ffmpeg命令進行轉碼操作了
轉碼命令:
ffmpeg -y -i 需要轉碼的文件路徑 -s 720x960 -b:v 562k -c:v libx264 轉碼成功后文件的保存路徑復制
經過此步驟之后轉碼后的文件就只有幾百K了,視頻的質量也還可以
直接貼代碼:
//設置轉碼后的文件路徑(避免重復命令我們加一個時間戳隨機數) $randnum = date('His').str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); $nfile = $_SERVER["DOCUMENT_ROOT"]."/Public/vedios/" . $randnum .$_FILES["file1"]["name"]; $nfile2 = "/Public/vedios/" . $randnum .$_FILES["file1"]["name"]; //exec函數執行ffmpeg終端轉碼命令 $str = "ffmpeg -y -i ". $ofile. " -s 720x960 -b:v 562k -c:v libx264 " . $nfile; exec("$str", $output,$status);//$status為0即表示轉碼成功 //unlink($ofile)方法刪除源文件 if(!$status && unlink($ofile)){ $VedioStr = C('URL').$nfile2; $VedioUrl = $nfile2; $vedioData = array( 'vedioShowUrl'=>$VedioStr, 'saveVedioUrl'=>$VedioUrl ); $this->res['code'] = 200; $this->res['msg'] = '上傳轉碼成功'; $this->res['data'] = $vedioData; $this->response($this->res,'json'); }else{ $this->res['code'] = 101; $this->res['msg'] = '轉碼錯誤請重試!'; $this->res['data'] = $output; $this->response($this->res,'json'); }復制客戶端拿到返回的視頻URL利用vedio插件進行顯示安裝vue-video-player插件
1、vue項目中執行:
npm install vue-video-player --save復制
2、在main.js入口文件中引入:
import VideoPlayer from 'vue-video-player' require('video.js/dist/video-js.css') require('vue-video-player/src/custom-theme.css') Vue.use(VideoPlayer)復制
3、在使用的頁面中引用:
import { videoPlayer } from 'vue-video-player' import 'video.js/dist/video-js.css'復制
4、構建播放器容器:
復制
options參數:
playerOptions: { controls:false, autoplay: false, // 如果為true,瀏覽器準備好時開始回放。 muted: false, // 默認情況下將會消除任何音頻。 loop: false, // 是否視頻一結束就重新開始。 preload: 'auto', // 建議瀏覽器在復制修改播放器默認樣式實現點擊屏幕暫停和播放加載元素后是否應該開始下載視頻數據。auto瀏覽器選擇最佳行為,立即開始加載視頻(如果瀏覽器支持) language: 'zh-CN', aspectRatio: '9:16', // 將播放器置于流暢模式,并在計算播放器的動態大小時使用該值。值應該代表一個比例 - 用冒號分隔的兩個數字(例如"16:9"或"4:3") sources: [{ type: "video/mp4", // 類型 src: '' // url地址 }], poster:'http://81.68.107.23/uploads/poster.png', // 封面地址 notSupportedMessage: '此視頻暫無法播放,請稍后再試', // 允許覆蓋Video.js無法播放媒體源時顯示的默認信息。 controlBar: { timeDivider: true, // 當前時間和持續時間的分隔符 durationDisplay: true, // 顯示持續時間 remainingTimeDisplay: false, // 是否顯示剩余時間功能 fullscreenToggle: false // 是否顯示全屏按鈕 } },
這里默認的播放器樣式很丑的,我們需要自定義樣式實現點擊視頻屏幕播放和暫停功能
貼出來自定義的css
/*播放按鈕設置成寬高一致,圓形,居中*/ .vjs-custom-skin > .video-js .vjs-big-play-button { background: url("../../assets/img/pause.png"); background-color: rgba(255, 255, 255, 0.4); margin-left: -1em !important; width: 2em !important; background-size: cover; border: none; width: 100px; height: 100px; } .video-js .vjs-big-play-button .vjs-icon-placeholder:before { position: absolute; left: 0; width: 100%; height: 100%; } /* 去掉中間的播放箭頭 */ .vjs-big-play-button .vjs-icon-placeholder { font-size: 0em; } /* 加載圓圈 */ .vjs-loading-spinner { font-size: 2.5em; width: 2em; height: 2em; border-radius: 1em; margin-top: -1em; margin-left: -1.5em; } /*control-bar布局時flex,通過order調整剩余時間的位置到進度條右邊*/ .vjs-custom-skin > .video-js .vjs-control-bar .vjs-remaining-time{ order:3 !important; } /*進度條背景軌道*/ .video-js .vjs-slider{ border-radius: 1em; } /*進度條進度*/ .vjs-custom-skin > .video-js .vjs-play-progress, .vjs-custom-skin > .video-js .vjs-volume-level{ border-radius: 1em; } /*鼠標進入播放器后,播放按鈕顏色會變*/ .video-js:hover .vjs-big-play-button, .vjs-custom-skin>.video-js .vjs-big-play-button:active, .vjs-custom-skin>.video-js .vjs-big-play-button:focus{ background-color: rgba(0,0,0,0.4) !important; } /*control bar*/ .video-js .vjs-control-bar{ background-color: rgba(0,0,0,0.2) !important; } /*點擊按鈕時不顯示藍色邊框*/ .video-js .vjs-control-bar button{ outline: none; }復制
在上面步驟的main.js文件中引入我們剛剛創建的自定義css
import './assets/css/vediocommon.css'復制
js方法
@pause="onPlayerPause($event)"@play="onPlayerPlay($event)"@ended="onPlayerEnded($event)" onPlayerClick
onPlayerPause($event) { this.isPlay = false; }, onPlayerPlay($event) { this.isPlay = true; }, onPlayerEnded($event) {}, onPlayerClick() { if (this.isPlay) { this.player.pause(); } else { this.player.play(); } },復制源碼文件
由于項目中很多地方可能涉及到引用的本地的一些icon文件導致你們復制粘貼后不能正常運行,所以將此視頻上傳封裝成了一個組件方便大家在項目中直接引用
總結(永遠記得做一個有靈魂的人)1、一部分人寫CSDN是為了自己記個筆記所以別人看不懂正常,可以理解
2、復制粘貼紙上談兵別人的東西就沒有什么意思了
3、技術水平有限,但是每一行都是自己親歷親為實現的,權當做個記錄
相關推薦
- Cordova 什么是Cordova? Cordova是用于使用HTML,CSS和JS構建移動應用的平臺。我們可以認為Cordova是一個容器,用于將我們的網絡應用程序與本機移動功能連接。默認情況下,Web應用程序不能使用本機移動功能。這就是Cordova進來的地方。它為網絡應用和移動設備之間的連…
- Hibernate Criterion 在查詢方法設計上能夠靈活的依據Criteria的特點來方便地進行查詢條件的組裝.Hibernate設計了CriteriaSpecification作為Criteria的父接口,以下提供了Criteria和DetachedCriteria.Criteria和DetachedCriteria的主要差別在于創建的形式不一樣,Criteria是在線的,所…