在最近项目中需要实现一个前端拍摄短视频并上传后端的功能。

最初考虑的实现方式是使用拍摄短视频的安卓sdk并且改成cordova插件。

考虑目前做的比较成熟的sdk有七牛云的短视频拍摄sdk,功能强大。

此sdk实现了类似与微信的按住拍摄松开停止的功能,并且可以自动转码并且上传七牛云服务器。

但是缺点如下:

1.sdk只提供函数接口,即使改成cordova插件页面也需要再重写一个类似于上图的vue页面,不如调用系统原生摄像功能方便。

2.改造为cordova插件需要考虑ios版本的问题。

3.拍摄的视频会打上七牛云水印并且上传七牛云的服务器。

4.sdk使用收费。

 

 

故最终采用了cordova提供的现有插件实现。

效果如下:

 

 

 

用到了三个插件:

实现思路:

1.使用media-capture打开摄像头拍摄视频,控制时间在10秒以内。

2.此插件拍摄成功以后返回一个file类型的文件,对此文件调用video-editor插件转码成1M左右文件并且生成缩略图。此方法调用返回一个文件地址。

3.用cordvoa的file插件读取此地址,转码成base64格式二进制流。

4.在vue页面使用video.js组件展示预览视频,用户可以选择删除或者上传。

具体代码:

 

//调用video-capture插件拍摄
    obtainVideo() {
      var vuetmp = this
     
      //先申请读取拌机文件权限
      var permissions = cordova.plugins.permissions
      permissions.checkPermission(
        permissions.WRITE_EXTERNAL_STORAGE,
        function(s) {
          //hasPermission 验证是否成功
          if (!s.hasPermission) {
            //没有权限
            //app申请写入权限
            permissions.requestPermission(
              permissions.WRITE_EXTERNAL_STORAGE,
              function(s) {
                if (s.hasPermission) {
                  //申请成功
                } else {
                  msgbus.vm.setSnackBar({
                    value: {
                      color: \'error\',
                      text: `写入权限申请失败`,
                      visible: true
                    }
                  })
                }
              },
              function(error) {}
            )
          } else {
            //拥有权限
            vuetmp.videoPath = null
            vuetmp.videoImg = null
            var options = { limit: 1, duration: 10 }
            //插件提供的拍视函数
            navigator.device.capture.captureVideo(
              vuetmp.videoCaptureSuccess,
              error => {},
              options
            )
          }
        },
        function(error) {}
      )
    },

 

拍摄成功执行转码:

videoCaptureSuccess(mediaFiles) {
      this.dialog = true
      var file = mediaFiles[0]
      var vuetmp = this
      //resolveLocalFileSystemURL()方法将接受device-absolute-path,并返回Entry
      //js无法读取安卓绝对路径,需要使用toURL()函数转换成url
      resolveLocalFileSystemURL(file.fullPath, function(entry) {
        debugHelper.log(\'resolveLocalFileSystemURL\')
        var fileurl = entry.toURL()//如果此步转换失败检查app文件读取权限
        debugHelper.log(fileurl)
        debugHelper.log(\'cdvfile URI: \' + fileurl)
        vuetmp.videoPath = fileurl
        //调用转码插件
        VideoEditor.transcodeVideo(
          vuetmp.videoTranscodeSuccess, // success cb
          vuetmp.videoTranscodeError, // error cb
          {
            fileUri: fileurl, // the path to the video on the device
            outputFileName: \'ReportVideo\', // the file name for the transcoded video
            outputFileType: VideoEditorOptions.OutputFileType.mp4, // android is always mp4
            saveToLibrary: true, // optional, defaults to true
            maintainAspectRatio: true,
            deleteInputFile: false, // optional (android only), defaults to false
            width: 640, // optional, see note below on width and height
            height: 640, // optional, see notes below on width and height
            videoBitrate: 1000000, // optional, bitrate in bits, defaults to 1 megabit (1000000)
            fps: 24, // optional (android only), defaults to 24
            audioChannels: 2, // optional (ios only), number of audio channels, defaults to 2
            progress: function(info) {
              console.log(\'transcodeVideo progress callback, info: \' + info)
            } // info will be a number from 0 to 100
          }
        )
      })
    },

转码成功生成Base64格式二进制流;

//转码成功函数
    videoTranscodeSuccess(result) {
      this.videoPath = result
      var vuetmp = this
      //resolveLocalFileSystemURL需要传入\'file:///\'前缀的地址,故加上
      var resulttmp = \'file:///\' + result
      debugHelper.log(resulttmp)
      resolveLocalFileSystemURL(resulttmp, function(entry) {
        entry.file(function(file) {
          var reader = new FileReader()
          reader.onloadend = function() {
            vuetmp.videoBase64 = this.result//readAsDataURL函数执行成功返回result
            vuetmp.$emit(\'putFile\', vuetmp.videoBase64)
            vuetmp.dialog = false
          }
          reader.readAsDataURL(file)//此函数把文件读取为Base64二进制流
        }, vuetmp.onErrorReadFile)
      })
      //生成视频缩略图
      VideoEditor.createThumbnail(
        this.createThumbnailSuccess,
        this.createThumbnailError,
        {
          fileUri: result,
          outputFileName: \'ReportVideoThumbnail\',
          atTime: 2,
          width: 320,
          height: 480,
          quality: 100
        }
      )
    },

 

版权声明:本文为pihaochen原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/pihaochen/p/11264275.html