Cordova+vue混合開發app中實現短視頻拍攝功能


在最近項目中需要實現一個前端拍攝短視頻並上傳后端的功能。

最初考慮的實現方式是使用拍攝短視頻的安卓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
        }
      )
    },

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM