1. <table id="w9hw2"></table>
      <big id="w9hw2"></big>

      Cordova插件cordova-plugin-media-capture实现短视频的录制上传和播放

      小编:管理员 279阅读 2022.09.13

      效果图在这里插入图片描述写在前面(吐槽)

      1、网上的教程大部分都是虎头蛇尾的不全的。互相抄来抄去真的感觉就没有一个是真正自己去写一写的,不然这里面这么多的坑就没有一个人出来说说的?下面就写写我实现功能过程中的一些问题吧,代码绝对完整并且按照步骤来一定可以成功!

      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-transfer
      cordova 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、构建播放器容器:

      <video-player  class="video-player vjs-custom-skin"
      		        id="videoDiv"
      		        ref="videoPlayer"
      		        :playsinline="true"
      		        :webkit-playsinline="true"
      		        :options="playerOptions"
      				@pause="onPlayerPause($event)"
      				@play="onPlayerPlay($event)"
      				@ended="onPlayerEnded($event)"
      		    >
      			</video-player>
      复制

      options参数:

      playerOptions: {
      			  controls:false,
      			  autoplay: false, // 如果为true,浏览器准备好时开始回放。
      			  muted: false, // 默认情况下将会消除任何音频。
      			  loop: false, // 是否视频一结束就重新开始。
      			  preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。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、技术水平有限,但是每一行都是自己亲历亲为实现的,权当做个记录

      关联标签:
      免费一级片或者是视频
      1. <table id="w9hw2"></table>
        <big id="w9hw2"></big>